mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 07:56:16 +00:00
merge from develop
This commit is contained in:
commit
acbe60343c
@ -38,6 +38,7 @@ import java.util.Collections;
|
|||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import static java.util.Objects.nonNull;
|
import static java.util.Objects.nonNull;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
@ -58,7 +59,6 @@ import javax.imageio.ImageReadParam;
|
|||||||
import javax.imageio.ImageReader;
|
import javax.imageio.ImageReader;
|
||||||
import javax.imageio.event.IIOReadProgressListener;
|
import javax.imageio.event.IIOReadProgressListener;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
@ -962,7 +962,7 @@ public class ImageUtils {
|
|||||||
LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT, ImageUtils.getContentPathSafe(file));
|
LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT, ImageUtils.getContentPathSafe(file));
|
||||||
} else if (fxImage.isError()) {
|
} else if (fxImage.isError()) {
|
||||||
//if there was somekind of error, log it
|
//if there was somekind of error, log it
|
||||||
LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT + ": " + ObjectUtils.toString(fxImage.getException()), ImageUtils.getContentPathSafe(file));
|
LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT + ": " + Objects.toString(fxImage.getException()), ImageUtils.getContentPathSafe(file));
|
||||||
}
|
}
|
||||||
} catch (InterruptedException | ExecutionException ex) {
|
} catch (InterruptedException | ExecutionException ex) {
|
||||||
failed();
|
failed();
|
||||||
@ -972,7 +972,7 @@ public class ImageUtils {
|
|||||||
@Override
|
@Override
|
||||||
protected void failed() {
|
protected void failed() {
|
||||||
super.failed();
|
super.failed();
|
||||||
LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT + ": " + ObjectUtils.toString(getException()), ImageUtils.getContentPathSafe(file));
|
LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT + ": " + Objects.toString(getException()), ImageUtils.getContentPathSafe(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,438 @@
|
|||||||
|
/*
|
||||||
|
* 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.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
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.StringUtils;
|
||||||
|
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.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.IngestJobInfo;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides information about how a datasource relates to a previous case. NOTE:
|
||||||
|
* This code is fragile and has certain expectations about how the central
|
||||||
|
* repository handles creating artifacts. So, if the central repository changes
|
||||||
|
* ingest process, this code could break. This code expects that the central
|
||||||
|
* repository ingest module:
|
||||||
|
*
|
||||||
|
* a) Creates a TSK_INTERESTING_FILE_HIT artifact for a file whose hash is in
|
||||||
|
* the central repository as a notable file.
|
||||||
|
*
|
||||||
|
* b) Creates a TSK_INTERESTING_ARTIFACT_HIT artifact for a matching id in the
|
||||||
|
* central repository.
|
||||||
|
*
|
||||||
|
* c) The created artifact will have a TSK_COMMENT attribute attached where one
|
||||||
|
* of the sources for the attribute matches
|
||||||
|
* CentralRepoIngestModuleFactory.getModuleName(). The module display name at
|
||||||
|
* time of ingest will match CentralRepoIngestModuleFactory.getModuleName() as
|
||||||
|
* well.
|
||||||
|
*
|
||||||
|
* d) The content of that TSK_COMMENT attribute will be of the form "Previous
|
||||||
|
* Case: case1,case2...caseN"
|
||||||
|
*/
|
||||||
|
public class PastCasesSummary implements DefaultArtifactUpdateGovernor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception that is thrown in the event that a data source has not been
|
||||||
|
* ingested with a particular ingest module.
|
||||||
|
*/
|
||||||
|
public static class NotIngestedWithModuleException extends Exception {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final String moduleDisplayName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param moduleName The module name.
|
||||||
|
* @param message The message for the exception.
|
||||||
|
*/
|
||||||
|
public NotIngestedWithModuleException(String moduleName, String message) {
|
||||||
|
super(message);
|
||||||
|
this.moduleDisplayName = moduleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param moduleName The module name.
|
||||||
|
* @param message The message for the exception.
|
||||||
|
* @param thrwbl Inner exception if applicable.
|
||||||
|
*/
|
||||||
|
public NotIngestedWithModuleException(String moduleName, String message, Throwable thrwbl) {
|
||||||
|
super(message, thrwbl);
|
||||||
|
this.moduleDisplayName = moduleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The module display name.
|
||||||
|
*/
|
||||||
|
public String getModuleDisplayName() {
|
||||||
|
return moduleDisplayName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return type for results items in the past cases tab.
|
||||||
|
*/
|
||||||
|
public static class PastCasesResult {
|
||||||
|
|
||||||
|
private final List<Pair<String, Long>> sameIdsResults;
|
||||||
|
private final List<Pair<String, Long>> taggedNotable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main constructor.
|
||||||
|
*
|
||||||
|
* @param sameIdsResults Data for the cases with same id table.
|
||||||
|
* @param taggedNotable Data for the tagged notable table.
|
||||||
|
*/
|
||||||
|
public PastCasesResult(List<Pair<String, Long>> sameIdsResults, List<Pair<String, Long>> taggedNotable) {
|
||||||
|
this.sameIdsResults = sameIdsResults;
|
||||||
|
this.taggedNotable = taggedNotable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Data for the cases with same id table.
|
||||||
|
*/
|
||||||
|
public List<Pair<String, Long>> getSameIdsResults() {
|
||||||
|
return sameIdsResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Data for the tagged notable table.
|
||||||
|
*/
|
||||||
|
public List<Pair<String, Long>> getTaggedNotable() {
|
||||||
|
return taggedNotable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
private static final Set<Integer> CR_DEVICE_TYPE_IDS = new HashSet<>(Arrays.asList(
|
||||||
|
ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID(),
|
||||||
|
ARTIFACT_TYPE.TSK_DEVICE_INFO.getTypeID(),
|
||||||
|
ARTIFACT_TYPE.TSK_SIM_ATTACHED.getTypeID(),
|
||||||
|
ARTIFACT_TYPE.TSK_WIFI_NETWORK_ADAPTER.getTypeID()
|
||||||
|
));
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the provided sources for an attribute, aims to determine if one of
|
||||||
|
* those sources is the Central Repository Ingest Module.
|
||||||
|
*
|
||||||
|
* @param sources The list of sources found on an attribute.
|
||||||
|
*
|
||||||
|
* @return Whether or not this attribute (and subsequently the parent
|
||||||
|
* artifact) is created by the Central Repository Ingest Module.
|
||||||
|
*/
|
||||||
|
private static boolean isCentralRepoGenerated(List<String> sources) {
|
||||||
|
if (sources == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sources.stream().anyMatch((str) -> {
|
||||||
|
return str != null && CENTRAL_REPO_INGEST_NAME.equalsIgnoreCase(str.trim());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of cases from the TSK_COMMENT of an artifact. The cases
|
||||||
|
* string is expected to be of a form of "Previous Case:
|
||||||
|
* case1,case2...caseN".
|
||||||
|
*
|
||||||
|
* @param artifact The artifact.
|
||||||
|
*
|
||||||
|
* @return The list of cases if found or empty list if not.
|
||||||
|
*/
|
||||||
|
private static List<String> getCasesFromArtifact(BlackboardArtifact artifact) {
|
||||||
|
if (artifact == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
BlackboardAttribute commentAttr = null;
|
||||||
|
try {
|
||||||
|
commentAttr = artifact.getAttribute(TYPE_COMMENT);
|
||||||
|
} catch (TskCoreException ignored) {
|
||||||
|
// ignore if no attribute can be found
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commentAttr == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isCentralRepoGenerated(commentAttr.getSources())) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
String commentStr = commentAttr.getValueString();
|
||||||
|
|
||||||
|
int prefixCharIdx = commentStr.indexOf(PREFIX_END);
|
||||||
|
if (prefixCharIdx < 0 || prefixCharIdx >= commentStr.length() - 1) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
String justCasesStr = commentStr.substring(prefixCharIdx + 1).trim();
|
||||||
|
return Stream.of(justCasesStr.split(CASE_SEPARATOR))
|
||||||
|
.map(String::trim)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a stream of case ids, groups the strings in a case-insensitive
|
||||||
|
* manner, and then provides a list of cases and the occurrence count sorted
|
||||||
|
* from max to min.
|
||||||
|
*
|
||||||
|
* @param cases A stream of cases.
|
||||||
|
*
|
||||||
|
* @return The list of unique cases and their occurrences sorted from max to min.
|
||||||
|
*/
|
||||||
|
private 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()))
|
||||||
|
.values();
|
||||||
|
|
||||||
|
return groupedCases
|
||||||
|
.stream()
|
||||||
|
// get any cases where an actual case is found
|
||||||
|
.filter((lst) -> lst != null && lst.size() > 0)
|
||||||
|
// get non-normalized (i.e. not all caps) case name and number of items found
|
||||||
|
.map((lst) -> Pair.of(lst.get(0), (long) lst.size()))
|
||||||
|
// sorted descending
|
||||||
|
.sorted((a, b) -> -Long.compare(a.getValue(), b.getValue()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an artifact with a TYPE_ASSOCIATED_ARTIFACT attribute, retrieves the related artifact.
|
||||||
|
* @param skCase The sleuthkit case.
|
||||||
|
* @param artifact The artifact with the TYPE_ASSOCIATED_ARTIFACT attribute.
|
||||||
|
* @return The artifact if found or null if not.
|
||||||
|
* @throws SleuthkitCaseProviderException
|
||||||
|
*/
|
||||||
|
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 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the artifact has an associated artifact of a device type.
|
||||||
|
* @param artifact The artifact.
|
||||||
|
* @return True if there is a device associated artifact.
|
||||||
|
* @throws SleuthkitCaseProviderException
|
||||||
|
*/
|
||||||
|
private boolean hasDeviceAssociatedArtifact(BlackboardArtifact artifact) throws SleuthkitCaseProviderException {
|
||||||
|
BlackboardArtifact parent = getParentArtifact(artifact);
|
||||||
|
if (parent == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CR_DEVICE_TYPE_IDS.contains(parent.getArtifactTypeID());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the past cases data to be shown in the past cases tab.
|
||||||
|
* @param dataSource The data source.
|
||||||
|
* @return The retrieved data.
|
||||||
|
* @throws SleuthkitCaseProviderException
|
||||||
|
* @throws TskCoreException
|
||||||
|
* @throws NotIngestedWithModuleException
|
||||||
|
*/
|
||||||
|
public PastCasesResult getPastCasesData(DataSource dataSource)
|
||||||
|
throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, NotIngestedWithModuleException {
|
||||||
|
|
||||||
|
throwOnNotCentralRepoIngested(dataSource);
|
||||||
|
|
||||||
|
SleuthkitCase skCase = caseProvider.get();
|
||||||
|
|
||||||
|
List<String> deviceArtifactCases = new ArrayList<>();
|
||||||
|
List<String> nonDeviceArtifactCases = new ArrayList<>();
|
||||||
|
|
||||||
|
for (BlackboardArtifact artifact : skCase.getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID(), dataSource.getId())) {
|
||||||
|
List<String> cases = getCasesFromArtifact(artifact);
|
||||||
|
if (cases == null || cases.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasDeviceAssociatedArtifact(artifact)) {
|
||||||
|
deviceArtifactCases.addAll(cases);
|
||||||
|
} else {
|
||||||
|
nonDeviceArtifactCases.addAll(cases);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<String> filesCases = skCase.getBlackboard().getArtifacts(ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(), dataSource.getId()).stream()
|
||||||
|
.flatMap((art) -> getCasesFromArtifact(art).stream());
|
||||||
|
|
||||||
|
return new PastCasesResult(
|
||||||
|
getCaseCounts(deviceArtifactCases.stream()),
|
||||||
|
getCaseCounts(Stream.concat(filesCases, nonDeviceArtifactCases.stream()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the ingest job info contains an ingest module that
|
||||||
|
* matches the Central Repo Module ingest display name.
|
||||||
|
*
|
||||||
|
* @param info The info.
|
||||||
|
*
|
||||||
|
* @return True if there is a central repo ingest match.
|
||||||
|
*/
|
||||||
|
private boolean hasCentralRepoIngest(IngestJobInfo info) {
|
||||||
|
if (info == null || info.getIngestModuleInfo() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return info.getIngestModuleInfo().stream()
|
||||||
|
.anyMatch((moduleInfo) -> {
|
||||||
|
return StringUtils.isNotBlank(moduleInfo.getDisplayName())
|
||||||
|
&& moduleInfo.getDisplayName().trim().equalsIgnoreCase(CENTRAL_REPO_INGEST_NAME);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the central repository ingest module has been run on the
|
||||||
|
* datasource.
|
||||||
|
*
|
||||||
|
* @param dataSource The data source.
|
||||||
|
*
|
||||||
|
* @return True if there is an ingest job pertaining to the data source
|
||||||
|
* where an ingest module matches the central repo ingest module
|
||||||
|
* display name.
|
||||||
|
*
|
||||||
|
* @throws SleuthkitCaseProviderException
|
||||||
|
* @throws TskCoreException
|
||||||
|
*/
|
||||||
|
public boolean isCentralRepoIngested(DataSource dataSource)
|
||||||
|
throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException {
|
||||||
|
if (dataSource == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
long dataSourceId = dataSource.getId();
|
||||||
|
|
||||||
|
return this.caseProvider.get().getIngestJobs().stream()
|
||||||
|
.anyMatch((ingestJob) -> {
|
||||||
|
return ingestJob != null
|
||||||
|
&& ingestJob.getObjectId() == dataSourceId
|
||||||
|
&& hasCentralRepoIngest(ingestJob);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws an exception if the current data source has not been ingested with
|
||||||
|
* the Central Repository Ingest Module.
|
||||||
|
*
|
||||||
|
* @param dataSource The data source to check if it has been ingested with
|
||||||
|
* the Central Repository Ingest Module.
|
||||||
|
*
|
||||||
|
* @throws SleuthkitCaseProviderException
|
||||||
|
* @throws TskCoreException
|
||||||
|
* @throws NotIngestedWithModuleException
|
||||||
|
*/
|
||||||
|
private void throwOnNotCentralRepoIngested(DataSource dataSource)
|
||||||
|
throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException, NotIngestedWithModuleException {
|
||||||
|
|
||||||
|
if (!isCentralRepoIngested(dataSource)) {
|
||||||
|
String objectId = (dataSource == null) ? "<null>" : String.valueOf(dataSource.getId());
|
||||||
|
String message = String.format("Data source: %s has not been ingested with the Central Repository Ingest Module.", objectId);
|
||||||
|
throw new NotIngestedWithModuleException(CENTRAL_REPO_INGEST_NAME, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,18 +19,22 @@
|
|||||||
package org.sleuthkit.autopsy.datasourcesummary.datamodel;
|
package org.sleuthkit.autopsy.datasourcesummary.datamodel;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor;
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.DefaultArtifactUpdateGovernor;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import org.openide.util.NbBundle.Messages;
|
import org.openide.util.NbBundle.Messages;
|
||||||
import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException;
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.SleuthkitCaseProvider.SleuthkitCaseProviderException;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
@ -51,6 +55,7 @@ import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
|||||||
public class UserActivitySummary implements DefaultArtifactUpdateGovernor {
|
public class UserActivitySummary implements DefaultArtifactUpdateGovernor {
|
||||||
|
|
||||||
private static final BlackboardArtifact.Type TYPE_DEVICE_ATTACHED = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
|
private static final BlackboardArtifact.Type TYPE_DEVICE_ATTACHED = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
|
||||||
|
private static final BlackboardArtifact.Type TYPE_WEB_HISTORY = new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_WEB_HISTORY);
|
||||||
|
|
||||||
private static final BlackboardAttribute.Type TYPE_DATETIME = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME);
|
private static final BlackboardAttribute.Type TYPE_DATETIME = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME);
|
||||||
private static final BlackboardAttribute.Type TYPE_DATETIME_ACCESSED = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED);
|
private static final BlackboardAttribute.Type TYPE_DATETIME_ACCESSED = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED);
|
||||||
@ -59,15 +64,14 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor {
|
|||||||
private static final BlackboardAttribute.Type TYPE_DEVICE_MODEL = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL);
|
private static final BlackboardAttribute.Type TYPE_DEVICE_MODEL = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL);
|
||||||
private static final BlackboardAttribute.Type TYPE_MESSAGE_TYPE = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE);
|
private static final BlackboardAttribute.Type TYPE_MESSAGE_TYPE = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE);
|
||||||
private static final BlackboardAttribute.Type TYPE_TEXT = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT);
|
private static final BlackboardAttribute.Type TYPE_TEXT = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT);
|
||||||
|
|
||||||
private static final BlackboardAttribute.Type TYPE_DATETIME_RCVD = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_RCVD);
|
private static final BlackboardAttribute.Type TYPE_DATETIME_RCVD = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_RCVD);
|
||||||
private static final BlackboardAttribute.Type TYPE_DATETIME_SENT = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_SENT);
|
private static final BlackboardAttribute.Type TYPE_DATETIME_SENT = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_SENT);
|
||||||
private static final BlackboardAttribute.Type TYPE_DATETIME_START = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START);
|
private static final BlackboardAttribute.Type TYPE_DATETIME_START = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START);
|
||||||
private static final BlackboardAttribute.Type TYPE_DATETIME_END = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_END);
|
private static final BlackboardAttribute.Type TYPE_DATETIME_END = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_END);
|
||||||
|
private static final BlackboardAttribute.Type TYPE_DOMAIN = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DOMAIN);
|
||||||
|
|
||||||
private static final Comparator<TopAccountResult> TOP_ACCOUNT_RESULT_DATE_COMPARE = (a, b) -> a.getLastAccess().compareTo(b.getLastAccess());
|
private static final Comparator<TopAccountResult> TOP_ACCOUNT_RESULT_DATE_COMPARE = (a, b) -> a.getLastAccess().compareTo(b.getLastAccess());
|
||||||
private static final Comparator<TopWebSearchResult> TOP_WEBSEARCH_RESULT_DATE_COMPARE = (a, b) -> a.getDateAccessed().compareTo(b.getDateAccessed());
|
private static final Comparator<TopWebSearchResult> TOP_WEBSEARCH_RESULT_DATE_COMPARE = (a, b) -> a.getDateAccessed().compareTo(b.getDateAccessed());
|
||||||
private static final String ROOT_HUB_IDENTIFIER = "ROOT_HUB";
|
|
||||||
|
|
||||||
private static final Set<Integer> ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList(
|
private static final Set<Integer> ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList(
|
||||||
ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(),
|
ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY.getTypeID(),
|
||||||
@ -78,39 +82,12 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor {
|
|||||||
ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()
|
ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()
|
||||||
));
|
));
|
||||||
|
|
||||||
private static final long SLEEP_TIME = 5000;
|
private static final Set<String> DEVICE_EXCLUDE_LIST = new HashSet<>(Arrays.asList("ROOT_HUB", "ROOT_HUB20"));
|
||||||
|
private static final Set<String> DOMAIN_EXCLUDE_LIST = new HashSet<>(Arrays.asList("127.0.0.1", "LOCALHOST"));
|
||||||
|
|
||||||
/**
|
private static final long MS_PER_DAY = 1000 * 60 * 60 * 24;
|
||||||
* A function to calculate a result from 2 parameters.
|
private static final long DOMAIN_WINDOW_DAYS = 30;
|
||||||
*/
|
private static final long DOMAIN_WINDOW_MS = DOMAIN_WINDOW_DAYS * MS_PER_DAY;
|
||||||
interface Function2<A1, A2, O> {
|
|
||||||
|
|
||||||
O apply(A1 a1, A2 a2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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<TopDomainsResult> getRecentDomains(DataSource dataSource, int count) throws InterruptedException {
|
|
||||||
Thread.sleep(SLEEP_TIME);
|
|
||||||
final String dId = Long.toString(dataSource.getId());
|
|
||||||
final Function2<String, Integer, String> getId = (s, idx) -> String.format("d:%s, f:%s, i:%d", dId, s, idx);
|
|
||||||
return IntStream.range(0, count)
|
|
||||||
.mapToObj(num -> new TopDomainsResult(
|
|
||||||
getId.apply("domain", num),
|
|
||||||
getId.apply("url", num),
|
|
||||||
(long) num,
|
|
||||||
new Date(((long) num) * 1000 * 60 * 60 * 24)
|
|
||||||
))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private final SleuthkitCaseProvider caseProvider;
|
private final SleuthkitCaseProvider caseProvider;
|
||||||
private final TextTranslationService translationService;
|
private final TextTranslationService translationService;
|
||||||
@ -159,6 +136,143 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<TopDomainsResult> getRecentDomains(DataSource dataSource, int count) throws TskCoreException, SleuthkitCaseProviderException {
|
||||||
|
assertValidCount(count);
|
||||||
|
|
||||||
|
Pair<Long, Map<String, List<Long>>> mostRecentAndGroups = getDomainGroupsAndMostRecent(dataSource);
|
||||||
|
// if no recent domains, return accordingly
|
||||||
|
if (mostRecentAndGroups.getKey() == null || mostRecentAndGroups.getValue().size() == 0) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final long mostRecentMs = mostRecentAndGroups.getLeft();
|
||||||
|
Map<String, List<Long>> groups = mostRecentAndGroups.getRight();
|
||||||
|
|
||||||
|
return groups.entrySet().stream()
|
||||||
|
.map(entry -> getDomainsResult(entry.getKey(), entry.getValue(), mostRecentMs))
|
||||||
|
.filter(result -> result != null)
|
||||||
|
// sort by number of visit times in those 30 days (max to min)
|
||||||
|
.sorted((a, b) -> -Long.compare(a.getVisitTimes(), b.getVisitTimes()))
|
||||||
|
// limit the result number to the parameter provided
|
||||||
|
.limit(count)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 number of visits.
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
private TopDomainsResult getDomainsResult(String domain, List<Long> visits, long mostRecentMs) {
|
||||||
|
long visitCount = 0;
|
||||||
|
Long thisMostRecentMs = null;
|
||||||
|
|
||||||
|
for (Long visitMs : visits) {
|
||||||
|
// make sure that visit is within window of mostRecentMS; otherwise skip it.
|
||||||
|
if (visitMs + DOMAIN_WINDOW_MS < mostRecentMs) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if visit is within window, increment the count and get most recent
|
||||||
|
visitCount++;
|
||||||
|
thisMostRecentMs = getMax(thisMostRecentMs, visitMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there are no visits within the window, return null
|
||||||
|
if (visitCount <= 0 || thisMostRecentMs == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
// create a top domain result with the domain, count, and most recent visit date
|
||||||
|
return new TopDomainsResult(domain, visitCount, new Date(thisMostRecentMs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries TSK_WEB_HISTORY artifacts and returning the latest web history
|
||||||
|
* date accessed and a mapping of domains to all of their visits.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @throws TskCoreException
|
||||||
|
* @throws SleuthkitCaseProviderException
|
||||||
|
*/
|
||||||
|
private Pair<Long, Map<String, List<Long>>> getDomainGroupsAndMostRecent(DataSource dataSource) throws TskCoreException, SleuthkitCaseProviderException {
|
||||||
|
List<BlackboardArtifact> artifacts = DataSourceInfoUtilities.getArtifacts(caseProvider.get(), TYPE_WEB_HISTORY,
|
||||||
|
dataSource, TYPE_DATETIME_ACCESSED, DataSourceInfoUtilities.SortOrder.DESCENDING, 0);
|
||||||
|
|
||||||
|
Long mostRecentMs = null;
|
||||||
|
Map<String, List<Long>> domainVisits = new HashMap<>();
|
||||||
|
|
||||||
|
for (BlackboardArtifact art : artifacts) {
|
||||||
|
Long artifactDateSecs = DataSourceInfoUtilities.getLongOrNull(art, TYPE_DATETIME_ACCESSED);
|
||||||
|
String domain = DataSourceInfoUtilities.getStringOrNull(art, TYPE_DOMAIN);
|
||||||
|
|
||||||
|
// if there isn't a last access date or domain for this artifact, it can be ignored.
|
||||||
|
// Also, ignore the loopback address.
|
||||||
|
if (artifactDateSecs == null || StringUtils.isBlank(domain) || DOMAIN_EXCLUDE_LIST.contains(domain.toUpperCase().trim())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long artifactDateMs = artifactDateSecs * 1000;
|
||||||
|
|
||||||
|
// update the most recent visit date overall
|
||||||
|
mostRecentMs = getMax(mostRecentMs, artifactDateMs);
|
||||||
|
|
||||||
|
//Normalize the domain to lower case.
|
||||||
|
domain = domain.toLowerCase().trim();
|
||||||
|
|
||||||
|
// add this visit date to the list of dates for the domain
|
||||||
|
List<Long> domainVisitList = domainVisits.get(domain);
|
||||||
|
if (domainVisitList == null) {
|
||||||
|
domainVisitList = new ArrayList<>();
|
||||||
|
domainVisits.put(domain, domainVisitList);
|
||||||
|
}
|
||||||
|
|
||||||
|
domainVisitList.add(artifactDateMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Pair.of(mostRecentMs, domainVisits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum value given two longs handling possible null values.
|
||||||
|
*
|
||||||
|
* @param num1 The first number.
|
||||||
|
* @param num2 The second number.
|
||||||
|
*
|
||||||
|
* @return The maximum non-null number or null if both numbers are null.
|
||||||
|
*/
|
||||||
|
private static Long getMax(Long num1, Long num2) {
|
||||||
|
if (num1 == null) {
|
||||||
|
return num2;
|
||||||
|
} else if (num2 == null) {
|
||||||
|
return num1;
|
||||||
|
} else {
|
||||||
|
return num2 > num1 ? num2 : num1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to obtain a web search result record from a blackboard artifact.
|
* Attempts to obtain a web search result record from a blackboard artifact.
|
||||||
*
|
*
|
||||||
@ -291,7 +405,7 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor {
|
|||||||
// remove Root Hub identifier
|
// remove Root Hub identifier
|
||||||
.filter(result -> {
|
.filter(result -> {
|
||||||
return result.getDeviceModel() == null
|
return result.getDeviceModel() == null
|
||||||
|| !result.getDeviceModel().trim().toUpperCase().equals(ROOT_HUB_IDENTIFIER);
|
|| !DEVICE_EXCLUDE_LIST.contains(result.getDeviceModel().trim().toUpperCase());
|
||||||
})
|
})
|
||||||
.limit(count)
|
.limit(count)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
@ -555,7 +669,6 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor {
|
|||||||
public static class TopDomainsResult {
|
public static class TopDomainsResult {
|
||||||
|
|
||||||
private final String domain;
|
private final String domain;
|
||||||
private final String url;
|
|
||||||
private final Long visitTimes;
|
private final Long visitTimes;
|
||||||
private final Date lastVisit;
|
private final Date lastVisit;
|
||||||
|
|
||||||
@ -567,9 +680,8 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor {
|
|||||||
* @param visitTimes The number of times it was visited.
|
* @param visitTimes The number of times it was visited.
|
||||||
* @param lastVisit The date of the last visit.
|
* @param lastVisit The date of the last visit.
|
||||||
*/
|
*/
|
||||||
public TopDomainsResult(String domain, String url, Long visitTimes, Date lastVisit) {
|
public TopDomainsResult(String domain, Long visitTimes, Date lastVisit) {
|
||||||
this.domain = domain;
|
this.domain = domain;
|
||||||
this.url = url;
|
|
||||||
this.visitTimes = visitTimes;
|
this.visitTimes = visitTimes;
|
||||||
this.lastVisit = lastVisit;
|
this.lastVisit = lastVisit;
|
||||||
}
|
}
|
||||||
@ -581,13 +693,6 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor {
|
|||||||
return domain;
|
return domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The url for the result.
|
|
||||||
*/
|
|
||||||
public String getUrl() {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The number of times this site is visited.
|
* @return The number of times this site is visited.
|
||||||
*/
|
*/
|
||||||
@ -601,6 +706,5 @@ public class UserActivitySummary implements DefaultArtifactUpdateGovernor {
|
|||||||
public Date getLastVisit() {
|
public Date getLastVisit() {
|
||||||
return lastVisit;
|
return lastVisit;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ import org.sleuthkit.datamodel.DataSource;
|
|||||||
/**
|
/**
|
||||||
* Base class from which other tabs in data source summary derive.
|
* Base class from which other tabs in data source summary derive.
|
||||||
*/
|
*/
|
||||||
abstract class BaseDataSourceSummaryPanel extends JPanel implements AutoCloseable {
|
abstract class BaseDataSourceSummaryPanel extends JPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ -57,11 +57,8 @@ abstract class BaseDataSourceSummaryPanel extends JPanel implements AutoCloseabl
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes listeners and resources.
|
* Closes listeners and resources.
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
@Override
|
public void close() {
|
||||||
public void close() throws Exception {
|
|
||||||
executor.cancelRunning();
|
executor.cancelRunning();
|
||||||
updateHandler.unregister();
|
updateHandler.unregister();
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ ContainerPanel.acquisitionDetailsLabel.text=Acquisition Details:
|
|||||||
ContainerPanel.unallocatedSizeLabel.text=Unallocated Space:
|
ContainerPanel.unallocatedSizeLabel.text=Unallocated Space:
|
||||||
ContainerPanel.unallocatedSizeValue.text=
|
ContainerPanel.unallocatedSizeValue.text=
|
||||||
UserActivityPanel.programsRunLabel.text=Recent Programs
|
UserActivityPanel.programsRunLabel.text=Recent Programs
|
||||||
UserActivityPanel.recentAccountsLabel.text=Recent Accounts
|
UserActivityPanel.recentAccountsLabel.text=Recent Account Types Used
|
||||||
UserActivityPanel.topWebSearchLabel.text=Recent Web Searches
|
UserActivityPanel.topWebSearchLabel.text=Recent Web Searches
|
||||||
UserActivityPanel.topDevicesAttachedLabel.text=Recent Devices Attached
|
UserActivityPanel.topDevicesAttachedLabel.text=Recent Devices Attached
|
||||||
UserActivityPanel.recentDomainsLabel.text=Recent Domains
|
UserActivityPanel.recentDomainsLabel.text=Recent Domains
|
||||||
@ -39,3 +39,5 @@ AnalysisPanel.interestingItemLabel.text=Interesting Item Hits
|
|||||||
RecentFilesPanel.openDocsLabel.text=Recently Opened Documents
|
RecentFilesPanel.openDocsLabel.text=Recently Opened Documents
|
||||||
RecentFilesPanel.downloadLabel.text=Recent Downloads
|
RecentFilesPanel.downloadLabel.text=Recent Downloads
|
||||||
RecentFilesPanel.attachmentLabel.text=Recent Attachments
|
RecentFilesPanel.attachmentLabel.text=Recent Attachments
|
||||||
|
PastCasesPanel.notableFileLabel.text=Cases with Common Items That Were Tagged as Notable
|
||||||
|
PastCasesPanel.sameIdLabel.text=Past Cases with the Same Device IDs
|
||||||
|
@ -44,9 +44,13 @@ DataSourceSummaryNode.viewDataSourceAction.text=Go to Data Source
|
|||||||
DataSourceSummaryTabbedPane_analysisTab_title=Analysis
|
DataSourceSummaryTabbedPane_analysisTab_title=Analysis
|
||||||
DataSourceSummaryTabbedPane_detailsTab_title=Container
|
DataSourceSummaryTabbedPane_detailsTab_title=Container
|
||||||
DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History
|
DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History
|
||||||
|
DataSourceSummaryTabbedPane_pastCasesTab_title=Past Cases
|
||||||
DataSourceSummaryTabbedPane_recentFileTab_title=Recent Files
|
DataSourceSummaryTabbedPane_recentFileTab_title=Recent Files
|
||||||
DataSourceSummaryTabbedPane_typesTab_title=Types
|
DataSourceSummaryTabbedPane_typesTab_title=Types
|
||||||
DataSourceSummaryTabbedPane_userActivityTab_title=User Activity
|
DataSourceSummaryTabbedPane_userActivityTab_title=User Activity
|
||||||
|
PastCasesPanel_caseColumn_title=Case
|
||||||
|
PastCasesPanel_countColumn_title=Count
|
||||||
|
PastCasesPanel_onNoCrIngest_message=No results will be shown because the Central Repository module was not run.
|
||||||
RecentFilePanel_col_header_domain=Domain
|
RecentFilePanel_col_header_domain=Domain
|
||||||
RecentFilePanel_col_header_path=Path
|
RecentFilePanel_col_header_path=Path
|
||||||
RecentFilePanel_col_header_sender=Sender
|
RecentFilePanel_col_header_sender=Sender
|
||||||
@ -76,7 +80,7 @@ TypesPanel_osLabel_title=OS
|
|||||||
TypesPanel_sizeLabel_title=Size
|
TypesPanel_sizeLabel_title=Size
|
||||||
TypesPanel_usageLabel_title=Usage
|
TypesPanel_usageLabel_title=Usage
|
||||||
UserActivityPanel.programsRunLabel.text=Recent Programs
|
UserActivityPanel.programsRunLabel.text=Recent Programs
|
||||||
UserActivityPanel.recentAccountsLabel.text=Recent Accounts
|
UserActivityPanel.recentAccountsLabel.text=Recent Account Types Used
|
||||||
UserActivityPanel.topWebSearchLabel.text=Recent Web Searches
|
UserActivityPanel.topWebSearchLabel.text=Recent Web Searches
|
||||||
UserActivityPanel.topDevicesAttachedLabel.text=Recent Devices Attached
|
UserActivityPanel.topDevicesAttachedLabel.text=Recent Devices Attached
|
||||||
UserActivityPanel.recentDomainsLabel.text=Recent Domains
|
UserActivityPanel.recentDomainsLabel.text=Recent Domains
|
||||||
@ -86,6 +90,8 @@ AnalysisPanel.interestingItemLabel.text=Interesting Item Hits
|
|||||||
RecentFilesPanel.openDocsLabel.text=Recently Opened Documents
|
RecentFilesPanel.openDocsLabel.text=Recently Opened Documents
|
||||||
RecentFilesPanel.downloadLabel.text=Recent Downloads
|
RecentFilesPanel.downloadLabel.text=Recent Downloads
|
||||||
RecentFilesPanel.attachmentLabel.text=Recent Attachments
|
RecentFilesPanel.attachmentLabel.text=Recent Attachments
|
||||||
|
PastCasesPanel.notableFileLabel.text=Cases with Common Items That Were Tagged as Notable
|
||||||
|
PastCasesPanel.sameIdLabel.text=Past Cases with the Same Device IDs
|
||||||
UserActivityPanel_noDataExists=No communication data exists
|
UserActivityPanel_noDataExists=No communication data exists
|
||||||
UserActivityPanel_tab_title=User Activity
|
UserActivityPanel_tab_title=User Activity
|
||||||
UserActivityPanel_TopAccountTableModel_accountType_header=Account Type
|
UserActivityPanel_TopAccountTableModel_accountType_header=Account Type
|
||||||
@ -93,9 +99,9 @@ UserActivityPanel_TopAccountTableModel_lastAccess_header=Last Accessed
|
|||||||
UserActivityPanel_TopDeviceAttachedTableModel_dateAccessed_header=Last Accessed
|
UserActivityPanel_TopDeviceAttachedTableModel_dateAccessed_header=Last Accessed
|
||||||
UserActivityPanel_TopDeviceAttachedTableModel_deviceId_header=Device Id
|
UserActivityPanel_TopDeviceAttachedTableModel_deviceId_header=Device Id
|
||||||
UserActivityPanel_TopDeviceAttachedTableModel_makeModel_header=Make and Model
|
UserActivityPanel_TopDeviceAttachedTableModel_makeModel_header=Make and Model
|
||||||
|
UserActivityPanel_TopDomainsTableModel_count_header=Visits
|
||||||
UserActivityPanel_TopDomainsTableModel_domain_header=Domain
|
UserActivityPanel_TopDomainsTableModel_domain_header=Domain
|
||||||
UserActivityPanel_TopDomainsTableModel_lastAccess_header=Last Access
|
UserActivityPanel_TopDomainsTableModel_lastAccess_header=Last Accessed
|
||||||
UserActivityPanel_TopDomainsTableModel_url_header=URL
|
|
||||||
UserActivityPanel_TopProgramsTableModel_count_header=Run Times
|
UserActivityPanel_TopProgramsTableModel_count_header=Run Times
|
||||||
UserActivityPanel_TopProgramsTableModel_folder_header=Folder
|
UserActivityPanel_TopProgramsTableModel_folder_header=Folder
|
||||||
UserActivityPanel_TopProgramsTableModel_lastrun_header=Last Run
|
UserActivityPanel_TopProgramsTableModel_lastrun_header=Last Run
|
||||||
|
@ -97,12 +97,7 @@ final class DataSourceSummaryDialog extends javax.swing.JDialog implements Obser
|
|||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
IngestManager.getInstance().removeIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, ingestEventListener);
|
IngestManager.getInstance().removeIngestJobEventListener(INGEST_JOB_EVENTS_OF_INTEREST, ingestEventListener);
|
||||||
try {
|
this.dataSourceSummaryTabbedPane.close();
|
||||||
this.dataSourceSummaryTabbedPane.close();
|
|
||||||
} catch (Exception ex) {
|
|
||||||
logger.log(Level.WARNING, "There was an error disposing of resources in the tabbed pange for data source summary.", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,9 +37,10 @@ import org.sleuthkit.datamodel.DataSource;
|
|||||||
"DataSourceSummaryTabbedPane_userActivityTab_title=User Activity",
|
"DataSourceSummaryTabbedPane_userActivityTab_title=User Activity",
|
||||||
"DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History",
|
"DataSourceSummaryTabbedPane_ingestHistoryTab_title=Ingest History",
|
||||||
"DataSourceSummaryTabbedPane_recentFileTab_title=Recent Files",
|
"DataSourceSummaryTabbedPane_recentFileTab_title=Recent Files",
|
||||||
|
"DataSourceSummaryTabbedPane_pastCasesTab_title=Past Cases",
|
||||||
"DataSourceSummaryTabbedPane_analysisTab_title=Analysis"
|
"DataSourceSummaryTabbedPane_analysisTab_title=Analysis"
|
||||||
})
|
})
|
||||||
public class DataSourceSummaryTabbedPane extends JTabbedPane implements AutoCloseable {
|
public class DataSourceSummaryTabbedPane extends JTabbedPane {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Records of tab information (i.e. title, component, function to call on
|
* Records of tab information (i.e. title, component, function to call on
|
||||||
@ -50,7 +51,7 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane implements AutoClos
|
|||||||
private final String tabTitle;
|
private final String tabTitle;
|
||||||
private final Component component;
|
private final Component component;
|
||||||
private final Consumer<DataSource> onDataSource;
|
private final Consumer<DataSource> onDataSource;
|
||||||
private final AutoCloseable onClose;
|
private final Runnable onClose;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main constructor.
|
* Main constructor.
|
||||||
@ -60,7 +61,7 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane implements AutoClos
|
|||||||
* @param onDataSource The function to be called on a new data source.
|
* @param onDataSource The function to be called on a new data source.
|
||||||
* @param onClose Called to cleanup resources when closing tabs.
|
* @param onClose Called to cleanup resources when closing tabs.
|
||||||
*/
|
*/
|
||||||
DataSourceTab(String tabTitle, Component component, Consumer<DataSource> onDataSource, AutoCloseable onClose) {
|
DataSourceTab(String tabTitle, Component component, Consumer<DataSource> onDataSource, Runnable onClose) {
|
||||||
this.tabTitle = tabTitle;
|
this.tabTitle = tabTitle;
|
||||||
this.component = component;
|
this.component = component;
|
||||||
this.onDataSource = onDataSource;
|
this.onDataSource = onDataSource;
|
||||||
@ -77,7 +78,7 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane implements AutoClos
|
|||||||
this.tabTitle = tabTitle;
|
this.tabTitle = tabTitle;
|
||||||
this.component = panel;
|
this.component = panel;
|
||||||
this.onDataSource = panel::setDataSource;
|
this.onDataSource = panel::setDataSource;
|
||||||
this.onClose = panel;
|
this.onClose = panel::close;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,9 +103,9 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane implements AutoClos
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The object for closing when closing the tab.
|
* @return The action for closing resources in the tab.
|
||||||
*/
|
*/
|
||||||
public AutoCloseable getOnClose() {
|
public Runnable getOnClose() {
|
||||||
return onClose;
|
return onClose;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,8 +117,9 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane implements AutoClos
|
|||||||
private final List<DataSourceTab> tabs = Arrays.asList(
|
private final List<DataSourceTab> tabs = Arrays.asList(
|
||||||
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_typesTab_title(), new TypesPanel()),
|
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_typesTab_title(), new TypesPanel()),
|
||||||
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_userActivityTab_title(), new UserActivityPanel()),
|
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_userActivityTab_title(), new UserActivityPanel()),
|
||||||
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_recentFileTab_title(), new RecentFilesPanel()),
|
|
||||||
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_analysisTab_title(), new AnalysisPanel()),
|
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_analysisTab_title(), new AnalysisPanel()),
|
||||||
|
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_recentFileTab_title(), new RecentFilesPanel()),
|
||||||
|
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_pastCasesTab_title(), new PastCasesPanel()),
|
||||||
// do nothing on closing
|
// do nothing on closing
|
||||||
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_ingestHistoryTab_title(), ingestHistoryPanel, ingestHistoryPanel::setDataSource, () -> {
|
new DataSourceTab(Bundle.DataSourceSummaryTabbedPane_ingestHistoryTab_title(), ingestHistoryPanel, ingestHistoryPanel::setDataSource, () -> {
|
||||||
}),
|
}),
|
||||||
@ -163,13 +165,10 @@ public class DataSourceSummaryTabbedPane extends JTabbedPane implements AutoClos
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle close events on each tab.
|
* Handle close events on each tab.
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
*/
|
||||||
@Override
|
public void close() {
|
||||||
public void close() throws Exception {
|
|
||||||
for (DataSourceTab tab : tabs) {
|
for (DataSourceTab tab : tabs) {
|
||||||
tab.getOnClose().close();
|
tab.getOnClose().run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,194 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="mainScrollPane" alignment="0" pref="400" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="mainScrollPane" alignment="0" pref="300" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="mainScrollPane">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
|
<SubComponents>
|
||||||
|
<Container class="javax.swing.JPanel" name="mainContentPanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||||
|
<Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
|
||||||
|
<EmptyBorder bottom="10" left="10" right="10" top="10"/>
|
||||||
|
</Border>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
|
||||||
|
<Property name="axis" type="int" value="3"/>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JLabel" name="notableFileLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="PastCasesPanel.notableFileLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AccessibilityProperties>
|
||||||
|
<Property name="AccessibleContext.accessibleName" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="PastCasesPanel.notableFileLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</AccessibilityProperties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.Box$Filler" name="filler1">
|
||||||
|
<Properties>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[32767, 2]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 2]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 2]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
<Container class="javax.swing.JPanel" name="notableFilePanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="alignmentX" type="float" value="0.0"/>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[32767, 106]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[100, 106]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[100, 106]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="notableFileTable"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
|
||||||
|
</Container>
|
||||||
|
<Component class="javax.swing.Box$Filler" name="filler2">
|
||||||
|
<Properties>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[32767, 20]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 20]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 20]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.JLabel" name="sameIdLabel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/datasourcesummary/ui/Bundle.properties" key="PastCasesPanel.sameIdLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
<Component class="javax.swing.Box$Filler" name="filler3">
|
||||||
|
<Properties>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[32767, 2]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 2]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 2]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalStrut"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
<Container class="javax.swing.JPanel" name="sameIdPanel">
|
||||||
|
<Properties>
|
||||||
|
<Property name="alignmentX" type="float" value="0.0"/>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[32767, 106]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[100, 106]"/>
|
||||||
|
</Property>
|
||||||
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[100, 106]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="sameIdTable"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignFlowLayout"/>
|
||||||
|
</Container>
|
||||||
|
<Component class="javax.swing.Box$Filler" name="filler5">
|
||||||
|
<Properties>
|
||||||
|
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
|
<Dimension value="[0, 32767]"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="classDetails" type="java.lang.String" value="Box.Filler.VerticalGlue"/>
|
||||||
|
</AuxValues>
|
||||||
|
</Component>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2020 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.datasourcesummary.ui;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary.NotIngestedWithModuleException;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.datamodel.PastCasesSummary.PastCasesResult;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.CellModelTableCellRenderer.DefaultCellModel;
|
||||||
|
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.JTablePanel;
|
||||||
|
import org.sleuthkit.autopsy.datasourcesummary.uiutils.JTablePanel.ColumnModel;
|
||||||
|
import org.sleuthkit.datamodel.DataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tab shown in data source summary displaying information about a datasource
|
||||||
|
* and how it pertains to other cases.
|
||||||
|
*/
|
||||||
|
@Messages({
|
||||||
|
"PastCasesPanel_caseColumn_title=Case",
|
||||||
|
"PastCasesPanel_countColumn_title=Count",
|
||||||
|
"PastCasesPanel_onNoCrIngest_message=No results will be shown because the Central Repository module was not run."
|
||||||
|
|
||||||
|
})
|
||||||
|
public class PastCasesPanel extends BaseDataSourceSummaryPanel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static final ColumnModel<Pair<String, Long>> CASE_COL = new ColumnModel<>(
|
||||||
|
Bundle.PastCasesPanel_caseColumn_title(),
|
||||||
|
(pair) -> new DefaultCellModel(pair.getKey()),
|
||||||
|
300
|
||||||
|
);
|
||||||
|
|
||||||
|
private static final ColumnModel<Pair<String, Long>> COUNT_COL = new ColumnModel<>(
|
||||||
|
Bundle.PastCasesPanel_countColumn_title(),
|
||||||
|
(pair) -> new DefaultCellModel(String.valueOf(pair.getValue())),
|
||||||
|
100
|
||||||
|
);
|
||||||
|
|
||||||
|
private static final List<ColumnModel<Pair<String, Long>>> DEFAULT_COLUMNS = Arrays.asList(CASE_COL, COUNT_COL);
|
||||||
|
|
||||||
|
private final JTablePanel<Pair<String, Long>> notableFileTable = JTablePanel.getJTablePanel(DEFAULT_COLUMNS);
|
||||||
|
|
||||||
|
private final JTablePanel<Pair<String, Long>> sameIdTable = JTablePanel.getJTablePanel(DEFAULT_COLUMNS);
|
||||||
|
|
||||||
|
private final List<JTablePanel<?>> tables = Arrays.asList(
|
||||||
|
notableFileTable,
|
||||||
|
sameIdTable
|
||||||
|
);
|
||||||
|
|
||||||
|
private final List<DataFetchComponents<DataSource, ?>> dataFetchComponents;
|
||||||
|
|
||||||
|
public PastCasesPanel() {
|
||||||
|
this(new PastCasesSummary());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new form PastCasesPanel
|
||||||
|
*/
|
||||||
|
public PastCasesPanel(PastCasesSummary pastCaseData) {
|
||||||
|
// set up data acquisition methods
|
||||||
|
dataFetchComponents = Arrays.asList(
|
||||||
|
new DataFetchWorker.DataFetchComponents<>(
|
||||||
|
(dataSource) -> pastCaseData.getPastCasesData(dataSource),
|
||||||
|
(result) -> handleResult(result))
|
||||||
|
);
|
||||||
|
|
||||||
|
initComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* handles displaying the result for the table. If a
|
||||||
|
* NotCentralRepoIngestedException is thrown, then an appropriate message is
|
||||||
|
* shown. Otherwise, this method uses the tables default showDataFetchResult
|
||||||
|
* method.
|
||||||
|
*
|
||||||
|
* @param result The result.
|
||||||
|
*/
|
||||||
|
private void handleResult(DataFetchResult<PastCasesResult> result) {
|
||||||
|
if (result.getResultType() == ResultType.ERROR && result.getException() instanceof NotIngestedWithModuleException) {
|
||||||
|
notableFileTable.showMessage(Bundle.PastCasesPanel_onNoCrIngest_message());
|
||||||
|
sameIdTable.showMessage(Bundle.PastCasesPanel_onNoCrIngest_message());
|
||||||
|
} else {
|
||||||
|
notableFileTable.showDataFetchResult(getSubResult(result, (res) -> (res == null) ? null : res.getTaggedNotable()));
|
||||||
|
sameIdTable.showDataFetchResult(getSubResult(result, (res) -> (res == null) ? null : res.getSameIdsResults()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an input data fetch result, creates an error result if the original
|
||||||
|
* is an error. Otherwise, uses the getSubResult function on the underlying
|
||||||
|
* data to create a new DataFetchResult.
|
||||||
|
*
|
||||||
|
* @param inputResult The input result.
|
||||||
|
* @param getSubComponent The means of getting the data given the original
|
||||||
|
* data.
|
||||||
|
*
|
||||||
|
* @return The new result with the error of the original or the processed
|
||||||
|
* data.
|
||||||
|
*/
|
||||||
|
private <I, O> DataFetchResult<O> getSubResult(DataFetchResult<I> inputResult, Function<I, O> getSubResult) {
|
||||||
|
if (inputResult.getResultType() == ResultType.SUCCESS) {
|
||||||
|
return DataFetchResult.getSuccessResult(getSubResult.apply(inputResult.getData()));
|
||||||
|
} else {
|
||||||
|
return DataFetchResult.getErrorResult(inputResult.getException());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void fetchInformation(DataSource dataSource) {
|
||||||
|
fetchInformation(dataFetchComponents, dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onNewDataSource(DataSource dataSource) {
|
||||||
|
onNewDataSource(dataFetchComponents, tables, dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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")
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
javax.swing.JScrollPane mainScrollPane = new javax.swing.JScrollPane();
|
||||||
|
javax.swing.JPanel mainContentPanel = new javax.swing.JPanel();
|
||||||
|
javax.swing.JLabel notableFileLabel = 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(32767, 2));
|
||||||
|
javax.swing.JPanel notableFilePanel = notableFileTable;
|
||||||
|
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(32767, 20));
|
||||||
|
javax.swing.JLabel sameIdLabel = new javax.swing.JLabel();
|
||||||
|
javax.swing.Box.Filler filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 2), new java.awt.Dimension(0, 2), new java.awt.Dimension(32767, 2));
|
||||||
|
javax.swing.JPanel sameIdPanel = sameIdTable;
|
||||||
|
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));
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(notableFileLabel, org.openide.util.NbBundle.getMessage(PastCasesPanel.class, "PastCasesPanel.notableFileLabel.text")); // NOI18N
|
||||||
|
mainContentPanel.add(notableFileLabel);
|
||||||
|
notableFileLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(PastCasesPanel.class, "PastCasesPanel.notableFileLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
mainContentPanel.add(filler1);
|
||||||
|
|
||||||
|
notableFilePanel.setAlignmentX(0.0F);
|
||||||
|
notableFilePanel.setMaximumSize(new java.awt.Dimension(32767, 106));
|
||||||
|
notableFilePanel.setMinimumSize(new java.awt.Dimension(100, 106));
|
||||||
|
notableFilePanel.setPreferredSize(new java.awt.Dimension(100, 106));
|
||||||
|
mainContentPanel.add(notableFilePanel);
|
||||||
|
mainContentPanel.add(filler2);
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(sameIdLabel, org.openide.util.NbBundle.getMessage(PastCasesPanel.class, "PastCasesPanel.sameIdLabel.text")); // NOI18N
|
||||||
|
mainContentPanel.add(sameIdLabel);
|
||||||
|
mainContentPanel.add(filler3);
|
||||||
|
|
||||||
|
sameIdPanel.setAlignmentX(0.0F);
|
||||||
|
sameIdPanel.setMaximumSize(new java.awt.Dimension(32767, 106));
|
||||||
|
sameIdPanel.setMinimumSize(new java.awt.Dimension(100, 106));
|
||||||
|
sameIdPanel.setPreferredSize(new java.awt.Dimension(100, 106));
|
||||||
|
mainContentPanel.add(sameIdPanel);
|
||||||
|
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)
|
||||||
|
);
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
}
|
@ -50,9 +50,8 @@ import org.sleuthkit.datamodel.DataSource;
|
|||||||
"UserActivityPanel_TopProgramsTableModel_count_header=Run Times",
|
"UserActivityPanel_TopProgramsTableModel_count_header=Run Times",
|
||||||
"UserActivityPanel_TopProgramsTableModel_lastrun_header=Last Run",
|
"UserActivityPanel_TopProgramsTableModel_lastrun_header=Last Run",
|
||||||
"UserActivityPanel_TopDomainsTableModel_domain_header=Domain",
|
"UserActivityPanel_TopDomainsTableModel_domain_header=Domain",
|
||||||
"UserActivityPanel_TopDomainsTableModel_url_header=URL",
|
"UserActivityPanel_TopDomainsTableModel_count_header=Visits",
|
||||||
"UserActivityPanel_TopDomainsTableModel_lastAccess_header=Last Access",
|
"UserActivityPanel_TopDomainsTableModel_lastAccess_header=Last Accessed",
|
||||||
"UserActivityPanel_noDataExists=No communication data exists",
|
|
||||||
"UserActivityPanel_TopWebSearchTableModel_searchString_header=Search String",
|
"UserActivityPanel_TopWebSearchTableModel_searchString_header=Search String",
|
||||||
"UserActivityPanel_TopWebSearchTableModel_dateAccessed_header=Date Accessed",
|
"UserActivityPanel_TopWebSearchTableModel_dateAccessed_header=Date Accessed",
|
||||||
"UserActivityPanel_TopWebSearchTableModel_translatedResult_header=Translated",
|
"UserActivityPanel_TopWebSearchTableModel_translatedResult_header=Translated",
|
||||||
@ -60,7 +59,8 @@ import org.sleuthkit.datamodel.DataSource;
|
|||||||
"UserActivityPanel_TopDeviceAttachedTableModel_makeModel_header=Make and Model",
|
"UserActivityPanel_TopDeviceAttachedTableModel_makeModel_header=Make and Model",
|
||||||
"UserActivityPanel_TopDeviceAttachedTableModel_dateAccessed_header=Last Accessed",
|
"UserActivityPanel_TopDeviceAttachedTableModel_dateAccessed_header=Last Accessed",
|
||||||
"UserActivityPanel_TopAccountTableModel_accountType_header=Account Type",
|
"UserActivityPanel_TopAccountTableModel_accountType_header=Account Type",
|
||||||
"UserActivityPanel_TopAccountTableModel_lastAccess_header=Last Accessed",})
|
"UserActivityPanel_TopAccountTableModel_lastAccess_header=Last Accessed",
|
||||||
|
"UserActivityPanel_noDataExists=No communication data exists"})
|
||||||
public class UserActivityPanel extends BaseDataSourceSummaryPanel {
|
public class UserActivityPanel extends BaseDataSourceSummaryPanel {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@ -126,11 +126,14 @@ public class UserActivityPanel extends BaseDataSourceSummaryPanel {
|
|||||||
Bundle.UserActivityPanel_TopDomainsTableModel_domain_header(),
|
Bundle.UserActivityPanel_TopDomainsTableModel_domain_header(),
|
||||||
(recentDomain) -> new DefaultCellModel(recentDomain.getDomain()),
|
(recentDomain) -> new DefaultCellModel(recentDomain.getDomain()),
|
||||||
250),
|
250),
|
||||||
// url column
|
// count column
|
||||||
new ColumnModel<>(
|
new ColumnModel<>(
|
||||||
Bundle.UserActivityPanel_TopDomainsTableModel_url_header(),
|
Bundle.UserActivityPanel_TopDomainsTableModel_count_header(),
|
||||||
(recentDomain) -> new DefaultCellModel(recentDomain.getUrl()),
|
(recentDomain) -> {
|
||||||
250),
|
String visitTimes = recentDomain.getVisitTimes() == null ? "" : Long.toString(recentDomain.getVisitTimes());
|
||||||
|
return new DefaultCellModel(visitTimes);
|
||||||
|
},
|
||||||
|
100),
|
||||||
// last accessed column
|
// last accessed column
|
||||||
new ColumnModel<>(
|
new ColumnModel<>(
|
||||||
Bundle.UserActivityPanel_TopDomainsTableModel_lastAccess_header(),
|
Bundle.UserActivityPanel_TopDomainsTableModel_lastAccess_header(),
|
||||||
|
@ -12,8 +12,8 @@ ILeappAnalyzerIngestModule.report.name=iLeapp Html Report
|
|||||||
ILeappAnalyzerIngestModule.requires.windows=iLeapp module requires windows.
|
ILeappAnalyzerIngestModule.requires.windows=iLeapp module requires windows.
|
||||||
ILeappAnalyzerIngestModule.running.iLeapp=Running iLeapp
|
ILeappAnalyzerIngestModule.running.iLeapp=Running iLeapp
|
||||||
ILeappAnalyzerIngestModule.starting.iLeapp=Starting iLeapp
|
ILeappAnalyzerIngestModule.starting.iLeapp=Starting iLeapp
|
||||||
ILeappAnalyzerModuleFactory_moduleDesc=Runs iLeapp against files.
|
ILeappAnalyzerModuleFactory_moduleDesc=Uses iLEAPP to analyze logical acquisitions of iOS devices.
|
||||||
ILeappAnalyzerModuleFactory_moduleName=ILeapp Analyzer
|
ILeappAnalyzerModuleFactory_moduleName=iOS Analyzer (iLEAPP)
|
||||||
ILeappFileProcessor.cannot.load.artifact.xml=Cannor load xml artifact file.
|
ILeappFileProcessor.cannot.load.artifact.xml=Cannor load xml artifact file.
|
||||||
ILeappFileProcessor.cannotBuildXmlParser=Cannot buld an XML parser.
|
ILeappFileProcessor.cannotBuildXmlParser=Cannot buld an XML parser.
|
||||||
ILeappFileProcessor.completed=iLeapp Processing Completed
|
ILeappFileProcessor.completed=iLeapp Processing Completed
|
||||||
|
@ -33,7 +33,7 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
|
|||||||
@ServiceProvider(service = IngestModuleFactory.class)
|
@ServiceProvider(service = IngestModuleFactory.class)
|
||||||
public class ILeappAnalyzerModuleFactory extends IngestModuleFactoryAdapter {
|
public class ILeappAnalyzerModuleFactory extends IngestModuleFactoryAdapter {
|
||||||
|
|
||||||
@NbBundle.Messages({"ILeappAnalyzerModuleFactory_moduleName=ILeapp Analyzer"})
|
@NbBundle.Messages({"ILeappAnalyzerModuleFactory_moduleName=iOS Analyzer (iLEAPP)"})
|
||||||
static String getModuleName() {
|
static String getModuleName() {
|
||||||
return Bundle.ILeappAnalyzerModuleFactory_moduleName();
|
return Bundle.ILeappAnalyzerModuleFactory_moduleName();
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ public class ILeappAnalyzerModuleFactory extends IngestModuleFactoryAdapter {
|
|||||||
return getModuleName();
|
return getModuleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NbBundle.Messages({"ILeappAnalyzerModuleFactory_moduleDesc=Runs iLeapp against files."})
|
@NbBundle.Messages({"ILeappAnalyzerModuleFactory_moduleDesc=Uses iLEAPP to analyze logical acquisitions of iOS devices."})
|
||||||
@Override
|
@Override
|
||||||
public String getModuleDescription() {
|
public String getModuleDescription() {
|
||||||
return Bundle.ILeappAnalyzerModuleFactory_moduleDesc();
|
return Bundle.ILeappAnalyzerModuleFactory_moduleDesc();
|
||||||
|
@ -137,16 +137,8 @@ public class DataSourceSummaryResultViewer extends AbstractDataResultViewer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearComponent() {
|
public void clearComponent() {
|
||||||
// clear resources for summary panel
|
summaryPanel.close();
|
||||||
if (summaryPanel != null) {
|
summaryPanel = null;
|
||||||
try {
|
|
||||||
summaryPanel.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.log(Level.WARNING, "There was an error closing the datasource summary tabbed panel.", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
summaryPanel = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataSourceSummaryTabbedPane summaryPanel;
|
private DataSourceSummaryTabbedPane summaryPanel;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user