Merge branch '6016-enable-cr-in-sqlite' into 6035-cr-psql-default

This commit is contained in:
Greg DiCristofaro 2020-02-27 08:04:37 -05:00
commit 127cc0c9e1
52 changed files with 1266 additions and 539 deletions

View File

@ -345,6 +345,7 @@
<package>org.sleuthkit.autopsy.report</package>
<package>org.sleuthkit.autopsy.textextractors</package>
<package>org.sleuthkit.autopsy.textextractors.configs</package>
<package>org.sleuthkit.autopsy.textsummarizer</package>
<package>org.sleuthkit.autopsy.texttranslation</package>
<package>org.sleuthkit.datamodel</package>
<package>org.sleuthkit.datamodel.blackboardutils</package>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2018 Basis Technology Corp.
* Copyright 2018-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -61,10 +61,10 @@ public final class AddEditCentralRepoCommentAction extends AbstractAction {
*/
public AddEditCentralRepoCommentAction(AbstractFile file) {
fileId = file.getId();
correlationAttributeInstance = CorrelationAttributeUtil.getInstanceFromContent(file);
correlationAttributeInstance = CorrelationAttributeUtil.getCorrAttrForFile(file);
if (correlationAttributeInstance == null) {
addToDatabase = true;
correlationAttributeInstance = CorrelationAttributeUtil.makeInstanceFromContent(file);
correlationAttributeInstance = CorrelationAttributeUtil.makeCorrAttrFromFile(file);
}
if (file.getSize() == 0) {
putValue(Action.NAME, Bundle.AddEditCentralRepoCommentAction_menuItemText_addEditCentralRepoCommentEmptyFile());

View File

@ -1,7 +1,7 @@
/*
* Central Repository
*
* Copyright 2017-2019 Basis Technology Corp.
* Copyright 2017-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -464,7 +464,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
// correlate on blackboard artifact attributes if they exist and supported
BlackboardArtifact bbArtifact = getBlackboardArtifactFromNode(node);
if (bbArtifact != null && CentralRepository.isEnabled()) {
ret.addAll(CorrelationAttributeUtil.makeInstancesFromBlackboardArtifact(bbArtifact, false));
ret.addAll(CorrelationAttributeUtil.makeCorrAttrsFromArtifact(bbArtifact));
}
// we can correlate based on the MD5 if it is enabled

View File

@ -7,8 +7,10 @@ AbstractSqlEamDb.cannotUpgrage.message=Currently selected database platform "{0}
AbstractSqlEamDb.failedToReadMajorVersion.message=Failed to read schema version for Central Repository.
AbstractSqlEamDb.failedToReadMinorVersion.message=Failed to read schema minor version for Central Repository.
AbstractSqlEamDb.upgradeSchema.incompatible=The selected Central Repository is not compatible with the current version of the application, please upgrade the application if you wish to use this Central Repository.
CentralRepoDbManager.connectionErrorMsg.text=Failed to connect to central repository database.
CorrelationAttributeInstance.invalidName.message=Invalid database table name. Name must start with a lowercase letter and can only contain lowercase letters, numbers, and '_'.
CorrelationAttributeInstance.nullName.message=Database name is null.
CorrelationAttributeUtil.emailaddresses.text=Email Addresses
CorrelationType.DOMAIN.displayName=Domains
CorrelationType.EMAIL.displayName=Email Addresses
CorrelationType.FILES.displayName=Files
@ -23,7 +25,6 @@ DataSourceUpdateService.serviceName.text=Update Central Repository Data Sources
EamArtifactInstances.knownStatus.bad=Bad
EamArtifactInstances.knownStatus.known=Known
EamArtifactInstances.knownStatus.unknown=Unknown
EamArtifactUtil.emailaddresses.text=Email Addresses
EamCase.title.caseDisplayName=Case Name:
EamCase.title.caseNumber=Case Number:
EamCase.title.caseUUID=Case UUID:

View File

@ -803,4 +803,13 @@ public interface CentralRepository {
* @throws CentralRepoException
*/
public void processSelectClause(String selectClause, InstanceTableCallback instanceTableCallback) throws CentralRepoException;
/**
* Returns list of all correlation types.
*
* @return list of Correlation types
* @throws CentralRepoException
*/
List<CorrelationAttributeInstance.Type> getCorrelationTypes() throws CentralRepoException;
}

View File

@ -1,7 +1,7 @@
/*
* Central Repository
*
* Copyright 2015-2018 Basis Technology Corp.
* Copyright 2015-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -24,6 +24,7 @@ import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.TskData;
/**
@ -221,6 +222,9 @@ public class CorrelationAttributeInstance implements Serializable {
public static final int IMSI_TYPE_ID = 8;
public static final int ICCID_TYPE_ID = 9;
// An offset to assign Ids for additional correlation types.
public static final int ADDITIONAL_TYPES_BASE_ID = 1000;
/**
* Load the default correlation types
*
@ -238,18 +242,30 @@ public class CorrelationAttributeInstance implements Serializable {
"CorrelationType.IMSI.displayName=IMSI Number",
"CorrelationType.ICCID.displayName=ICCID Number"})
public static List<CorrelationAttributeInstance.Type> getDefaultCorrelationTypes() throws CentralRepoException {
List<CorrelationAttributeInstance.Type> DEFAULT_CORRELATION_TYPES = new ArrayList<>();
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(FILES_TYPE_ID, Bundle.CorrelationType_FILES_displayName(), "file", true, true)); // NON-NLS
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(DOMAIN_TYPE_ID, Bundle.CorrelationType_DOMAIN_displayName(), "domain", true, true)); // NON-NLS
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(EMAIL_TYPE_ID, Bundle.CorrelationType_EMAIL_displayName(), "email_address", true, true)); // NON-NLS
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(PHONE_TYPE_ID, Bundle.CorrelationType_PHONE_displayName(), "phone_number", true, true)); // NON-NLS
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(USBID_TYPE_ID, Bundle.CorrelationType_USBID_displayName(), "usb_devices", true, true)); // NON-NLS
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(SSID_TYPE_ID, Bundle.CorrelationType_SSID_displayName(), "wireless_networks", true, true)); // NON-NLS
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(MAC_TYPE_ID, Bundle.CorrelationType_MAC_displayName(), "mac_address", true, true)); //NON-NLS
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(IMEI_TYPE_ID, Bundle.CorrelationType_IMEI_displayName(), "imei_number", true, true)); //NON-NLS
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(IMSI_TYPE_ID, Bundle.CorrelationType_IMSI_displayName(), "imsi_number", true, true)); //NON-NLS
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(ICCID_TYPE_ID, Bundle.CorrelationType_ICCID_displayName(), "iccid_number", true, true)); //NON-NLS
return DEFAULT_CORRELATION_TYPES;
List<CorrelationAttributeInstance.Type> defaultCorrelationTypes = new ArrayList<>();
defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(FILES_TYPE_ID, Bundle.CorrelationType_FILES_displayName(), "file", true, true)); // NON-NLS
defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(DOMAIN_TYPE_ID, Bundle.CorrelationType_DOMAIN_displayName(), "domain", true, true)); // NON-NLS
defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(EMAIL_TYPE_ID, Bundle.CorrelationType_EMAIL_displayName(), "email_address", true, true)); // NON-NLS
defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(PHONE_TYPE_ID, Bundle.CorrelationType_PHONE_displayName(), "phone_number", true, true)); // NON-NLS
defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(USBID_TYPE_ID, Bundle.CorrelationType_USBID_displayName(), "usb_devices", true, true)); // NON-NLS
defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(SSID_TYPE_ID, Bundle.CorrelationType_SSID_displayName(), "wireless_networks", true, true)); // NON-NLS
defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(MAC_TYPE_ID, Bundle.CorrelationType_MAC_displayName(), "mac_address", true, true)); //NON-NLS
defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(IMEI_TYPE_ID, Bundle.CorrelationType_IMEI_displayName(), "imei_number", true, true)); //NON-NLS
defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(IMSI_TYPE_ID, Bundle.CorrelationType_IMSI_displayName(), "imsi_number", true, true)); //NON-NLS
defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(ICCID_TYPE_ID, Bundle.CorrelationType_ICCID_displayName(), "iccid_number", true, true)); //NON-NLS
// Create Correlation Types for Accounts.
int correlationTypeId = ADDITIONAL_TYPES_BASE_ID;
for (Account.Type type : Account.Type.PREDEFINED_ACCOUNT_TYPES) {
// Skip Phone and Email accounts as there are already Correlation types defined for those.
if (type != Account.Type.EMAIL && type != Account.Type.PHONE) {
defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(correlationTypeId, type.getDisplayName(), type.getTypeName().toLowerCase(), true, true)); //NON-NLS
correlationTypeId++;
}
}
return defaultCorrelationTypes;
}
/**

View File

@ -1,7 +1,7 @@
/*
* Central Repository
*
* Copyright 2015-2020 Basis Technology Corp.
* Copyright 2017-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -30,176 +30,280 @@ 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.Content;
import org.sleuthkit.datamodel.HashUtility;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
/**
* Utility class for correlation attributes in the central repository
* Utility class for working with correlation attributes in the central
* repository.
*/
public class CorrelationAttributeUtil {
private static final Logger logger = Logger.getLogger(CorrelationAttributeUtil.class.getName());
@Messages({"EamArtifactUtil.emailaddresses.text=Email Addresses"})
public static String getEmailAddressAttrString() {
return Bundle.EamArtifactUtil_emailaddresses_text();
/**
* Gets a string that is expected to be the same string that is stored in
* the correlation_types table in the central repository as the display name
* for the email address correlation attribute type. This string is
* duplicated in the CorrelationAttributeInstance class.
*
* TODO (Jira-6088): We should not have multiple deifnitions of this string.
*
* @return The display name of the email address correlation attribute type.
*/
@Messages({"CorrelationAttributeUtil.emailaddresses.text=Email Addresses"})
private static String getEmailAddressAttrDisplayName() {
return Bundle.CorrelationAttributeUtil_emailaddresses_text();
}
/**
* Static factory method to examine a BlackboardArtifact to determine if it
* has contents that can be used for Correlation. If so, return a
* EamArtifact with a single EamArtifactInstance within. If not, return
* null.
* Makes zero to many correlation attribute instances from the attributes of
* an artifact.
*
* @param artifact BlackboardArtifact to examine
* @param checkEnabled If true, only create a CorrelationAttribute if it is
* enabled
* IMPORTANT: The correlation attribute instances are NOT added to the
* central repository by this method.
*
* @return List of EamArtifacts
* TODO (Jira-6088): The methods in this low-level, utility class should
* throw exceptions instead of logging them. The reason for this is that the
* clients of the utility class, not the utility class itself, should be in
* charge of error handling policy, per the Autopsy Coding Standard. Note
* that clients of several of these methods currently cannot determine
* whether receiving a null return value is an error or not, plus null
* checking is easy to forget, while catching exceptions is enforced.
*
* @param artifact An artifact.
*
* @return A list, possibly empty, of correlation attribute instances for
* the artifact.
*/
public static List<CorrelationAttributeInstance> makeInstancesFromBlackboardArtifact(BlackboardArtifact artifact,
boolean checkEnabled) {
List<CorrelationAttributeInstance> eamArtifacts = new ArrayList<>();
public static List<CorrelationAttributeInstance> makeCorrAttrsFromArtifact(BlackboardArtifact artifact) {
List<CorrelationAttributeInstance> correlationAttrs = new ArrayList<>();
try {
BlackboardArtifact artifactForInstance = null;
if (BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() == artifact.getArtifactTypeID()) {
// Get the associated artifactForInstance
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
if (attribute != null) {
artifactForInstance = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong());
}
} else {
artifactForInstance = artifact;
}
if (artifactForInstance != null) {
int artifactTypeID = artifactForInstance.getArtifactTypeID();
BlackboardArtifact sourceArtifact = getCorrAttrSourceArtifact(artifact);
if (sourceArtifact != null) {
int artifactTypeID = sourceArtifact.getArtifactTypeID();
if (artifactTypeID == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
BlackboardAttribute setNameAttr = artifactForInstance.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
if (setNameAttr != null
&& CorrelationAttributeUtil.getEmailAddressAttrString().equals(setNameAttr.getValueString())) {
addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, CorrelationAttributeInstance.EMAIL_TYPE_ID);
BlackboardAttribute setNameAttr = sourceArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
if (setNameAttr != null && CorrelationAttributeUtil.getEmailAddressAttrDisplayName().equals(setNameAttr.getValueString())) {
makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, CorrelationAttributeInstance.EMAIL_TYPE_ID);
}
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID()
|| artifactTypeID == ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID()
|| artifactTypeID == ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID()
|| artifactTypeID == ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()) {
addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN, CorrelationAttributeInstance.DOMAIN_TYPE_ID);
makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN, CorrelationAttributeInstance.DOMAIN_TYPE_ID);
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_CONTACT.getTypeID()
|| artifactTypeID == ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()
|| artifactTypeID == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) {
makeCorrAttrFromArtifactPhoneAttr(sourceArtifact);
String value = null;
if (null != artifactForInstance.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER))) {
value = artifactForInstance.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)).getValueString();
} else if (null != artifactForInstance.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM))) {
value = artifactForInstance.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM)).getValueString();
} else if (null != artifactForInstance.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO))) {
value = artifactForInstance.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO)).getValueString();
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID()) {
makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID, CorrelationAttributeInstance.USBID_TYPE_ID);
makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID);
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_WIFI_NETWORK.getTypeID()) {
makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SSID, CorrelationAttributeInstance.SSID_TYPE_ID);
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_WIFI_NETWORK_ADAPTER.getTypeID()
|| artifactTypeID == ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING.getTypeID()
|| artifactTypeID == ARTIFACT_TYPE.TSK_BLUETOOTH_ADAPTER.getTypeID()) {
makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID);
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_DEVICE_INFO.getTypeID()) {
makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMEI, CorrelationAttributeInstance.IMEI_TYPE_ID);
makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID);
makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID);
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_SIM_ATTACHED.getTypeID()) {
makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID);
makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID);
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS.getTypeID()) {
makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, CorrelationAttributeInstance.PHONE_TYPE_ID);
makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, CorrelationAttributeInstance.EMAIL_TYPE_ID);
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) {
makeCorrAttrFromAcctArtifact(correlationAttrs, sourceArtifact);
}
// Remove all non-numeric symbols to semi-normalize phone numbers, preserving leading "+" character
}
} catch (CentralRepoException ex) {
logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", artifact), ex); // NON-NLS
return correlationAttrs;
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Error getting querying case database (%s)", artifact), ex); // NON-NLS
return correlationAttrs;
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Error getting current case", ex); // NON-NLS
return correlationAttrs;
}
return correlationAttrs;
}
/**
* Gets the associated artifact of a "meta-artifact" such as an interesting
* artifact hit artifact.
*
* @param artifact An artifact.
*
* @return The associated artifact if the input artifact is a
* "meta-artifact", otherwise the input artifact.
*
* @throws NoCurrentCaseException If there is no open case.
* @throws TskCoreException If there is an error querying thew case
* database.
*/
private static BlackboardArtifact getCorrAttrSourceArtifact(BlackboardArtifact artifact) throws NoCurrentCaseException, TskCoreException {
BlackboardArtifact sourceArtifact = null;
if (BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() == artifact.getArtifactTypeID()) {
BlackboardAttribute assocArtifactAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
if (assocArtifactAttr != null) {
sourceArtifact = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboardArtifact(assocArtifactAttr.getValueLong());
}
} else {
sourceArtifact = artifact;
}
return sourceArtifact;
}
/**
* Makes a correlation attribute instance from a phone number attribute of an
* artifact.
*
* @param artifact An artifact with a phone number attribute.
*
* @return The correlation instance artifact or null, if the phone number is
* not a valid correlation attribute.
*
* @throws TskCoreException If there is an error querying the case
* database.
* @throws CentralRepoException If there is an error querying the central
* repository.
*/
private static CorrelationAttributeInstance makeCorrAttrFromArtifactPhoneAttr(BlackboardArtifact artifact) throws TskCoreException, CentralRepoException {
CorrelationAttributeInstance corrAttr = null;
/*
* Extract the phone number from the artifact attribute.
*/
String value = null;
if (null != artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER))) {
value = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)).getValueString();
} else if (null != artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM))) {
value = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM)).getValueString();
} else if (null != artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO))) {
value = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO)).getValueString();
}
/*
* Normalize the phone number.
*/
if (value != null) {
String newValue = value.replaceAll("\\D", "");
if (value.startsWith("+")) {
newValue = "+" + newValue;
}
value = newValue;
// Only add the correlation attribute if the resulting phone number large enough to be of use
// (these 3-5 digit numbers can be valid, but are not useful for correlation)
/*
* Validate the phone number. Three to five digit phone numbers may
* be valid, but they are too short to use as correlation
* attributes.
*/
if (value.length() > 5) {
CorrelationAttributeInstance inst = makeCorrelationAttributeInstanceUsingTypeValue(artifactForInstance, CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.PHONE_TYPE_ID), value);
if (inst != null) {
eamArtifacts.add(inst);
corrAttr = makeCorrAttr(artifact, CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.PHONE_TYPE_ID), value);
}
}
}
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID()) {
addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID, CorrelationAttributeInstance.USBID_TYPE_ID);
addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID);
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_WIFI_NETWORK.getTypeID()) {
addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SSID, CorrelationAttributeInstance.SSID_TYPE_ID);
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_WIFI_NETWORK_ADAPTER.getTypeID()
|| artifactTypeID == ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING.getTypeID()
|| artifactTypeID == ARTIFACT_TYPE.TSK_BLUETOOTH_ADAPTER.getTypeID()) {
addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID);
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_DEVICE_INFO.getTypeID()) {
addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMEI, CorrelationAttributeInstance.IMEI_TYPE_ID);
addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID);
addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID);
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_SIM_ATTACHED.getTypeID()) {
addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID);
addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID);
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS.getTypeID()) {
addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, CorrelationAttributeInstance.PHONE_TYPE_ID);
addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, CorrelationAttributeInstance.EMAIL_TYPE_ID);
}
}
} catch (CentralRepoException ex) {
logger.log(Level.SEVERE, "Error getting defined correlation types.", ex); // NON-NLS
return eamArtifacts;
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting attribute while getting type from BlackboardArtifact.", ex); // NON-NLS
return null;
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
return null;
}
return eamArtifacts;
return corrAttr;
}
/**
* Add a CorrelationAttributeInstance of the specified type to the provided
* list if the artifactForInstance has an Attribute of the given type with a
* non empty value.
* Makes a correlation attribute instance for an account artifact.
*
* @param eamArtifacts the list of CorrelationAttributeInstance objects
* which should be added to
* @param artifact the blackboard artifactForInstance which we are
* creating a CorrelationAttributeInstance for
* @param bbAttributeType the type of BlackboardAttribute we expect to exist
* for a CorrelationAttributeInstance of this type
* generated from this Blackboard Artifact
* @param typeId the integer type id of the
* CorrelationAttributeInstance type
* IMPORTANT: The correlation attribute instance is NOT added to the central
* repository by this method.
*
* @throws CentralRepoException
* @throws TskCoreException
* TODO (Jira-6088): The methods in this low-level, utility class should
* throw exceptions instead of logging them. The reason for this is that the
* clients of the utility class, not the utility class itself, should be in
* charge of error handling policy, per the Autopsy Coding Standard. Note
* that clients of several of these methods currently cannot determine
* whether receiving a null return value is an error or not, plus null
* checking is easy to forget, while catching exceptions is enforced.
*
* @param corrAttrInstances A list of correlation attribute instances.
* @param acctArtifact An account artifact.
*
* @return The correlation attribute instance.
*/
private static void addCorrelationAttributeToList(List<CorrelationAttributeInstance> eamArtifacts, BlackboardArtifact artifact, ATTRIBUTE_TYPE bbAttributeType, int typeId) throws CentralRepoException, TskCoreException {
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(bbAttributeType));
private static void makeCorrAttrFromAcctArtifact(List<CorrelationAttributeInstance> corrAttrInstances, BlackboardArtifact acctArtifact) {
// RAMAN TODO: Convert TSK_ACCOUNT_TYPE attribute to correlation attribute type
// RAMAN TODO: Extract TSK_ID as value
// CorrelationAttributeInstance corrAttr = makeCorrAttr(acctArtifact, corrType, corrAttrValue);
// if (corrAttr != null) {
// corrAttrInstances.add(corrAttr);
// }
}
/**
* Makes a correlation attribute instance from a specified attribute of an
* artifact. The correlation attribute instance is added to an input list.
*
* @param corrAttrInstances A list of correlation attribute instances.
* @param artifact An artifact.
* @param artAttrType The type of the atrribute of the artifact that
* is to be made into a correlatin attribute
* instance.
* @param typeId The type ID for the desired correlation
* attribute instance.
*
* @throws CentralRepoException If there is an error querying the central
* repository.
* @throws TskCoreException If there is an error querying the case
* database.
*/
private static void makeCorrAttrFromArtifactAttr(List<CorrelationAttributeInstance> corrAttrInstances, BlackboardArtifact artifact, ATTRIBUTE_TYPE artAttrType, int typeId) throws CentralRepoException, TskCoreException {
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(artAttrType));
if (attribute != null) {
String value = attribute.getValueString();
if ((null != value) && (value.isEmpty() == false)) {
CorrelationAttributeInstance inst = makeCorrelationAttributeInstanceUsingTypeValue(artifact, CentralRepository.getInstance().getCorrelationTypeById(typeId), value);
CorrelationAttributeInstance inst = makeCorrAttr(artifact, CentralRepository.getInstance().getCorrelationTypeById(typeId), value);
if (inst != null) {
eamArtifacts.add(inst);
corrAttrInstances.add(inst);
}
}
}
}
/**
* Uses the determined type and vallue, then looks up instance details to
* create proper CorrelationAttributeInstance.
* Makes a correlation attribute instance of a given type from an artifact.
*
* @param bbArtifact the blackboard artifactForInstance
* @param correlationType the given type
* @param value the artifactForInstance value
* @param artifact The artifact.
* @param correlationType the correlation attribute type.
* @param value The correlation attribute value.
*
* @return CorrelationAttributeInstance from details, or null if validation
* failed or another error occurred
* TODO (Jira-6088): The methods in this low-level, utility class should
* throw exceptions instead of logging them. The reason for this is that the
* clients of the utility class, not the utility class itself, should be in
* charge of error handling policy, per the Autopsy Coding Standard. Note
* that clients of several of these methods currently cannot determine
* whether receiving a null return value is an error or not, plus null
* checking is easy to forget, while catching exceptions is enforced.
*
* @return The correlation attribute instance or null, if an error occurred.
*/
private static CorrelationAttributeInstance makeCorrelationAttributeInstanceUsingTypeValue(BlackboardArtifact bbArtifact, CorrelationAttributeInstance.Type correlationType, String value) {
private static CorrelationAttributeInstance makeCorrAttr(BlackboardArtifact artifact, CorrelationAttributeInstance.Type correlationType, String value) {
try {
Case currentCase = Case.getCurrentCaseThrows();
AbstractFile bbSourceFile = currentCase.getSleuthkitCase().getAbstractFileById(bbArtifact.getObjectID());
AbstractFile bbSourceFile = currentCase.getSleuthkitCase().getAbstractFileById(artifact.getObjectID());
if (null == bbSourceFile) {
logger.log(Level.SEVERE, "Error creating artifact instance. Abstract File was null."); // NON-NLS
return null;
}
// make an instance for the BB source file
CorrelationCase correlationCase = CentralRepository.getInstance().getCase(Case.getCurrentCaseThrows());
return new CorrelationAttributeInstance(
correlationType,
@ -212,31 +316,34 @@ public class CorrelationAttributeUtil {
bbSourceFile.getId());
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting AbstractFile for artifact: " + bbArtifact.toString(), ex); // NON-NLS
logger.log(Level.SEVERE, String.format("Error getting querying case database (%s)", artifact), ex); // NON-NLS
return null;
} catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
logger.log(Level.WARNING, "Error creating artifact instance for artifact: " + bbArtifact.toString(), ex); // NON-NLS
logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", artifact), ex); // NON-NLS
return null;
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Case is closed.", ex); // NON-NLS
logger.log(Level.SEVERE, "Error getting current case", ex); // NON-NLS
return null;
}
}
/**
* Retrieve CorrelationAttribute from the given Content.
* Gets the correlation attribute instance for a file.
*
* @param content The content object
* @param file The file.
*
* @return The new CorrelationAttribute, or null if retrieval failed.
* TODO (Jira-6088): The methods in this low-level, utility class should
* throw exceptions instead of logging them. The reason for this is that the
* clients of the utility class, not the utility class itself, should be in
* charge of error handling policy, per the Autopsy Coding Standard. Note
* that clients of several of these methods currently cannot determine
* whether receiving a null return value is an error or not, plus null
* checking is easy to forget, while catching exceptions is enforced.
*
* @return The correlation attribute instance or null, if no such
* correlation attribute instance was found or an error occurred.
*/
public static CorrelationAttributeInstance getInstanceFromContent(Content content) {
if (!(content instanceof AbstractFile)) {
return null;
}
final AbstractFile file = (AbstractFile) content;
public static CorrelationAttributeInstance getCorrAttrForFile(AbstractFile file) {
if (!isSupportedAbstractFileType(file)) {
return null;
@ -254,11 +361,14 @@ public class CorrelationAttributeUtil {
return null;
}
correlationDataSource = CorrelationDataSource.fromTSKDataSource(correlationCase, file.getDataSource());
} catch (TskCoreException | CentralRepoException ex) {
logger.log(Level.SEVERE, "Error retrieving correlation attribute.", ex);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Error getting querying case database (%s)", file), ex); // NON-NLS
return null;
} catch (CentralRepoException ex) {
logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", file), ex); // NON-NLS
return null;
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Case is closed.", ex);
logger.log(Level.SEVERE, "Error getting current case", ex); // NON-NLS
return null;
}
@ -266,20 +376,22 @@ public class CorrelationAttributeUtil {
try {
correlationAttributeInstance = CentralRepository.getInstance().getCorrelationAttributeInstance(type, correlationCase, correlationDataSource, file.getId());
} catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
logger.log(Level.WARNING, String.format(
"Correlation attribute could not be retrieved for '%s' (id=%d): ",
content.getName(), content.getId()), ex);
logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", file), ex); // NON-NLS
return null;
}
//if there was no correlation attribute found for the item using object_id then check for attributes added with schema 1,1 which lack object_id
/*
* If no correlation attribute instance was found when querying by file
* object ID, try searching by file path instead. This is necessary
* because file object IDs were not stored in the central repository in
* early versions of its schema.
*/
if (correlationAttributeInstance == null && file.getMd5Hash() != null) {
String filePath = (file.getParentPath() + file.getName()).toLowerCase();
try {
correlationAttributeInstance = CentralRepository.getInstance().getCorrelationAttributeInstance(type, correlationCase, correlationDataSource, file.getMd5Hash(), filePath);
} catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
logger.log(Level.WARNING, String.format(
"Correlation attribute could not be retrieved for '%s' (id=%d): ",
content.getName(), content.getId()), ex);
logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", file), ex); // NON-NLS
return null;
}
}
@ -288,32 +400,31 @@ public class CorrelationAttributeUtil {
}
/**
* Create an EamArtifact from the given Content. Will return null if an
* artifactForInstance can not be created - this is not necessarily an error
* case, it just means an artifactForInstance can't be made. If creation
* fails due to an error (and not that the file is the wrong type or it has
* no hash), the error will be logged before returning.
* Makes a correlation attribute instance for a file.
*
* Does not add the artifactForInstance to the database.
* IMPORTANT: The correlation attribute instance is NOT added to the central
* repository by this method.
*
* @param content The content object
* TODO (Jira-6088): The methods in this low-level, utility class should
* throw exceptions instead of logging them. The reason for this is that the
* clients of the utility class, not the utility class itself, should be in
* charge of error handling policy, per the Autopsy Coding Standard. Note
* that clients of several of these methods currently cannot determine
* whether receiving a null return value is an error or not, plus null
* checking is easy to forget, while catching exceptions is enforced.
*
* @return The new EamArtifact or null if creation failed
* @param file The file.
*
* @return The correlation attribute instance or null, if an error occurred.
*/
public static CorrelationAttributeInstance makeInstanceFromContent(Content content) {
public static CorrelationAttributeInstance makeCorrAttrFromFile(AbstractFile file) {
if (!(content instanceof AbstractFile)) {
if (!isSupportedAbstractFileType(file)) {
return null;
}
final AbstractFile af = (AbstractFile) content;
if (!isSupportedAbstractFileType(af)) {
return null;
}
// We need a hash to make the artifactForInstance
String md5 = af.getMd5Hash();
// We need a hash to make the correlation artifact instance.
String md5 = file.getMd5Hash();
if (md5 == null || md5.isEmpty() || HashUtility.isNoDataMd5(md5)) {
return null;
}
@ -324,31 +435,33 @@ public class CorrelationAttributeUtil {
CorrelationCase correlationCase = CentralRepository.getInstance().getCase(Case.getCurrentCaseThrows());
return new CorrelationAttributeInstance(
filesType,
af.getMd5Hash(),
file.getMd5Hash(),
correlationCase,
CorrelationDataSource.fromTSKDataSource(correlationCase, af.getDataSource()),
af.getParentPath() + af.getName(),
CorrelationDataSource.fromTSKDataSource(correlationCase, file.getDataSource()),
file.getParentPath() + file.getName(),
"",
TskData.FileKnown.UNKNOWN,
af.getId());
file.getId());
} catch (TskCoreException | CentralRepoException | CorrelationAttributeNormalizationException ex) {
logger.log(Level.SEVERE, "Error making correlation attribute.", ex);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Error querying case database (%s)", file), ex); // NON-NLS
return null;
} catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", file), ex); // NON-NLS
return null;
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Case is closed.", ex);
logger.log(Level.SEVERE, "Error getting current case", ex); // NON-NLS
return null;
}
}
/**
* Check whether the given abstract file should be processed for the central
* repository.
* Checks whether or not a file is of a type that can be added to the
* central repository as a correlation attribute instance.
*
* @param file The file to test
* @param file A file.
*
* @return true if the file should be added to the central repo, false
* otherwise
* @return True or false.
*/
public static boolean isSupportedAbstractFileType(AbstractFile file) {
if (file == null) {
@ -375,9 +488,9 @@ public class CorrelationAttributeUtil {
}
/**
* Constructs a new EamArtifactUtil
* Prevent instantiation of this utility class.
*/
private CorrelationAttributeUtil() {
//empty constructor
}
}

View File

@ -0,0 +1,87 @@
/*
* Central Repository
*
* 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.centralrepository.datamodel;
/**
* This class abstracts a persona.
*
* An examiner may create a persona from an account.
*
*/
class Persona {
/**
* Defines level of confidence in assigning a persona to an account.
*/
public enum Confidence {
UNKNOWN(1, "Unknown"),
LOW(2, "Low confidence"),
MEDIUM(3, "Medium confidence"),
HIGH(4, "High confidence"),
DERIVED(5, "Derived directly");
private final String name;
private final int level_id;
Confidence(int level, String name) {
this.name = name;
this.level_id = level;
}
@Override
public String toString() {
return name;
}
public int getLevel() {
return this.level_id;
}
}
/**
* Defines status of a persona.
*/
public enum PersonaStatus {
UNKNOWN(1, "Unknown"),
ACTIVE(2, "Active"),
MERGED(3, "Merged"),
SPLIT(4, "Split"),
DELETED(5, "Deleted");
private final String description;
private final int status_id;
PersonaStatus(int status, String description) {
this.status_id = status;
this.description = description;
}
@Override
public String toString() {
return description;
}
public int getStatus() {
return this.status_id;
}
}
}

View File

@ -1373,6 +1373,9 @@ abstract class RdbmsCentralRepo implements CentralRepository {
}
synchronized (bulkArtifacts) {
if (bulkArtifacts.get(CentralRepoDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType())) == null) {
bulkArtifacts.put(CentralRepoDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType()), new ArrayList<>());
}
bulkArtifacts.get(CentralRepoDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType())).add(eamArtifact);
bulkArtifactsCount++;
@ -2845,6 +2848,7 @@ abstract class RdbmsCentralRepo implements CentralRepository {
typeId = newCorrelationTypeKnownId(newType);
}
typeCache.put(newType.getId(), newType);
return typeId;
}
@ -3105,6 +3109,45 @@ abstract class RdbmsCentralRepo implements CentralRepository {
}
}
/**
* Returns a list of all correlation types. It uses the cache to build the
* list. If the cache is empty, it reads from the database and loads up the
* cache.
*
* @return List of correlation types.
* @throws CentralRepoException
*/
@Override
public List<CorrelationAttributeInstance.Type> getCorrelationTypes() throws CentralRepoException {
if (typeCache.size() == 0) {
getCorrelationTypesFromCr();
}
return new ArrayList<>(typeCache.asMap().values());
}
/**
* Gets a Correlation type with the specified name.
*
* @param correlationtypeName Correlation type name
* @return Correlation type matching the given name, null if none matches.
*
* @throws CentralRepoException
*/
public CorrelationAttributeInstance.Type getCorrelationTypeByName(String correlationtypeName) throws CentralRepoException {
List<CorrelationAttributeInstance.Type> correlationTypesList = getCorrelationTypes();
CorrelationAttributeInstance.Type correlationType
= correlationTypesList.stream()
.filter(x -> correlationtypeName.equalsIgnoreCase(x.getDisplayName()))
.findAny()
.orElse(null);
return null;
}
/**
* Get the EamArtifact.Type that has the given Type.Id from the central repo
*
@ -3142,6 +3185,30 @@ abstract class RdbmsCentralRepo implements CentralRepository {
}
}
/**
* Reads the correlation types from the database and loads them up in the cache.
*
* @throws CentralRepoException If there is an error.
*/
private void getCorrelationTypesFromCr() throws CentralRepoException {
// clear out the cache
typeCache.invalidateAll();
String sql = "SELECT * FROM correlation_types";
try ( Connection conn = connect();
PreparedStatement preparedStatement = conn.prepareStatement(sql);
ResultSet resultSet = preparedStatement.executeQuery();) {
while (resultSet.next()) {
CorrelationAttributeInstance.Type aType = getCorrelationTypeFromResultSet(resultSet);
typeCache.put(aType.getId(), aType);
}
} catch (SQLException ex) {
throw new CentralRepoException("Error getting correlation types.", ex); // NON-NLS
}
}
/**
* Convert a ResultSet to a EamCase object
*

View File

@ -19,12 +19,17 @@
package org.sleuthkit.autopsy.centralrepository.datamodel;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.centralrepository.datamodel.Persona.Confidence;
import org.sleuthkit.autopsy.centralrepository.datamodel.Persona.PersonaStatus;
import static org.sleuthkit.autopsy.centralrepository.datamodel.RdbmsCentralRepo.SOFTWARE_CR_DB_SCHEMA_VERSION;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Account;
/**
* Creates the CR schema and populates it with initial data.
@ -87,16 +92,14 @@ public class RdbmsCentralRepoFactory {
// NOTE: the db_info table currenly only has 1 row, so having an index
// provides no benefit.
Connection conn = null;
Statement stmt = null;
try {
conn = this.getEphemeralConnection();
try (Connection conn = this.getEphemeralConnection();) {
if (null == conn) {
LOGGER.log(Level.SEVERE, "Cannot initialize CR database, don't have a valid connection."); // NON-NLS
return false;
}
stmt = conn.createStatement();
try (Statement stmt = conn.createStatement();) {
// these setting PRAGMAs are SQLIte spcific
if (selectedPlatform == CentralRepoPlatforms.SQLITE) {
@ -131,12 +134,16 @@ public class RdbmsCentralRepoFactory {
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')");
stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')");
// Create account_types and accounts tab;es which are referred by X_instances tables
stmt.execute(getCreateAccountTypesTableStatement(selectedPlatform));
stmt.execute(getCreateAccountsTableStatement(selectedPlatform));
// Create a separate instance and reference table for each artifact type
List<CorrelationAttributeInstance.Type> DEFAULT_CORRELATION_TYPES = CorrelationAttributeInstance.getDefaultCorrelationTypes();
List<CorrelationAttributeInstance.Type> defaultCorrelationTypes = CorrelationAttributeInstance.getDefaultCorrelationTypes();
String reference_type_dbname;
String instance_type_dbname;
for (CorrelationAttributeInstance.Type type : DEFAULT_CORRELATION_TYPES) {
for (CorrelationAttributeInstance.Type type : defaultCorrelationTypes) {
reference_type_dbname = CentralRepoDbUtil.correlationTypeToReferenceTableName(type);
instance_type_dbname = CentralRepoDbUtil.correlationTypeToInstanceTableName(type);
@ -154,22 +161,19 @@ public class RdbmsCentralRepoFactory {
stmt.execute(String.format(getReferenceTypeValueKnownstatusIndexTemplate(), reference_type_dbname, reference_type_dbname));
}
}
createPersonaTables(stmt);
} catch (SQLException ex) {
LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS
return false;
} catch (CentralRepoException ex) {
LOGGER.log(Level.SEVERE, "Error getting default correlation types. Likely due to one or more Type's with an invalid db table name."); // NON-NLS
return false;
} finally {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException ex2) {
LOGGER.log(Level.SEVERE, "Error closing statement.", ex2);
}
} catch (SQLException ex) {
LOGGER.log(Level.SEVERE, "Error connecting to database.", ex); // NON-NLS
return false;
}
CentralRepoDbUtil.closeConnection(conn);
}
return true;
}
@ -179,13 +183,22 @@ public class RdbmsCentralRepoFactory {
* @return True if success, False otherwise.
*/
public boolean insertDefaultDatabaseContent() {
Connection conn = this.getEphemeralConnection();
boolean result;
try (Connection conn = this.getEphemeralConnection();) {
if (null == conn) {
return false;
}
boolean result = CentralRepoDbUtil.insertDefaultCorrelationTypes(conn) && CentralRepoDbUtil.insertDefaultOrganization(conn);
CentralRepoDbUtil.closeConnection(conn);
result = CentralRepoDbUtil.insertDefaultCorrelationTypes(conn)
&& CentralRepoDbUtil.insertDefaultOrganization(conn)
&& insertDefaultPersonaTablesContent(conn);
} catch (SQLException ex) {
LOGGER.log(Level.SEVERE, String.format("Failed to populate default data in CR tables."), ex);
return false;
}
return result;
}
@ -353,12 +366,14 @@ public class RdbmsCentralRepoFactory {
+ getNumericPrimaryKeyClause("id", selectedPlatform)
+ "case_id integer NOT NULL,"
+ "data_source_id integer NOT NULL,"
+ "account_id " + getBigIntType(selectedPlatform) + " DEFAULT NULL,"
+ "value text NOT NULL,"
+ "file_path text NOT NULL,"
+ "known_status integer NOT NULL,"
+ "comment text,"
+ "file_obj_id " + getBigIntType(selectedPlatform) + " ,"
+ "CONSTRAINT %s_multi_unique UNIQUE(data_source_id, value, file_path)" + getOnConflictIgnoreClause(selectedPlatform) + ","
+ "foreign key (account_id) references accounts(id),"
+ "foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,"
+ "foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL)";
}
@ -413,7 +428,7 @@ public class RdbmsCentralRepoFactory {
/**
* Get the template for creating an index on the value column of an instance
* table. %s will exist in the template where the name of the new table will
* be addedd.
* be added.
*
* @return a String which is a template for adding an index to the value
* column of a _instances table
@ -426,7 +441,7 @@ public class RdbmsCentralRepoFactory {
/**
* Get the template for creating an index on the known_status column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
* table will be added.
*
* @return a String which is a template for adding an index to the
* known_status column of a _instances table
@ -439,7 +454,7 @@ public class RdbmsCentralRepoFactory {
/**
* Get the template for creating an index on the file_obj_id column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
* table will be added.
*
* @return a String which is a template for adding an index to the
* file_obj_id column of a _instances table
@ -525,7 +540,16 @@ public class RdbmsCentralRepoFactory {
}
}
private static String getOnConflictDoNothingClause(CentralRepoPlatforms selectedPlatform) {
switch (selectedPlatform) {
case POSTGRESQL:
return "ON CONFLICT DO NOTHING";
case SQLITE:
return "";
default:
return "";
}
}
/**
* Returns an ephemeral connection to the CR database.
*
@ -541,4 +565,301 @@ public class RdbmsCentralRepoFactory {
return null;
}
}
/**
* Creates the tables for Persona.
*
* @return True if success, False otherwise.
*/
private boolean createPersonaTables(Statement stmt) throws SQLException {
stmt.execute(getCreateConfidenceTableStatement(selectedPlatform));
stmt.execute(getCreateExaminersTableStatement(selectedPlatform));
stmt.execute(getCreatePersonaStatusTableStatement(selectedPlatform));
stmt.execute(getCreateAliasesTableStatement(selectedPlatform));
stmt.execute(getCreatePersonasTableStatement(selectedPlatform));
stmt.execute(getCreatePersonaAliasTableStatement(selectedPlatform));
stmt.execute(getCreatePersonaMetadataTableStatement(selectedPlatform));
stmt.execute(getCreatePersonaAccountsTableStatement(selectedPlatform));
return true;
}
/**
* Get the SQL string for creating a new account_types table in a central
* repository.
*
* @return SQL string for creating account_types table
*/
static String getCreateAccountTypesTableStatement(CentralRepoPlatforms selectedPlatform) {
return "CREATE TABLE IF NOT EXISTS account_types ("
+ getNumericPrimaryKeyClause("id", selectedPlatform)
+ "type_name TEXT NOT NULL,"
+ "display_name TEXT NOT NULL,"
+ "correlation_type_id " + getBigIntType(selectedPlatform) + " ,"
+ "CONSTRAINT type_name_unique UNIQUE (type_name),"
+ "FOREIGN KEY (correlation_type_id) REFERENCES correlation_types(id)"
+ ")";
}
/**
* Get the SQL String for creating a new confidence table in a central
* repository.
*
* @return SQL string for creating confidence table
*/
static String getCreateConfidenceTableStatement(CentralRepoPlatforms selectedPlatform) {
return "CREATE TABLE IF NOT EXISTS confidence ("
+ getNumericPrimaryKeyClause("id", selectedPlatform)
+ "confidence_id integer NOT NULL,"
+ "description TEXT,"
+ "CONSTRAINT level_unique UNIQUE (confidence_id)"
+ ")";
}
/**
* Get the SQL String for creating a new examiners table in a central
* repository.
*
* @return SQL string for creating examiners table
*/
static String getCreateExaminersTableStatement(CentralRepoPlatforms selectedPlatform) {
return "CREATE TABLE IF NOT EXISTS examiners ("
+ getNumericPrimaryKeyClause("id", selectedPlatform)
+ "login_name TEXT NOT NULL,"
+ "display_name TEXT,"
+ "CONSTRAINT login_name_unique UNIQUE(login_name)"
+ ")";
}
/**
* Get the SQL String for creating a new persona_status table in a central
* repository.
*
* @return SQL string for creating persona_status table
*/
static String getCreatePersonaStatusTableStatement(CentralRepoPlatforms selectedPlatform) {
return "CREATE TABLE IF NOT EXISTS persona_status ("
+ getNumericPrimaryKeyClause("id", selectedPlatform)
+ "status_id integer NOT NULL,"
+ "status TEXT NOT NULL,"
+ "CONSTRAINT status_unique UNIQUE(status_id)"
+ ")";
}
/**
* Get the SQL String for creating a new aliases table in a central
* repository.
*
* @return SQL string for creating aliases table
*/
static String getCreateAliasesTableStatement(CentralRepoPlatforms selectedPlatform) {
return "CREATE TABLE IF NOT EXISTS aliases ("
+ getNumericPrimaryKeyClause("id", selectedPlatform)
+ "alias TEXT NOT NULL,"
+ "CONSTRAINT alias_unique UNIQUE(alias)"
+ ")";
}
/**
* Get the SQL String for creating a new accounts table in a central
* repository.
*
* @return SQL string for creating accounts table
*/
static String getCreateAccountsTableStatement(CentralRepoPlatforms selectedPlatform) {
return "CREATE TABLE IF NOT EXISTS accounts ("
+ getNumericPrimaryKeyClause("id", selectedPlatform)
+ "account_type_id integer NOT NULL,"
+ "account_unique_identifier TEXT NOT NULL,"
+ "CONSTRAINT account_unique UNIQUE(account_type_id, account_unique_identifier),"
+ "FOREIGN KEY (account_type_id) REFERENCES account_types(id)"
+ ")";
}
/**
* Get the SQL String for creating a new personas table in a central
* repository.
*
* @return SQL string for creating personas table
*/
static String getCreatePersonasTableStatement(CentralRepoPlatforms selectedPlatform) {
return "CREATE TABLE IF NOT EXISTS personas ("
+ getNumericPrimaryKeyClause("id", selectedPlatform)
+ "uuid TEXT NOT NULL,"
+ "comment TEXT NOT NULL,"
+ "name TEXT NOT NULL,"
+ "created_date " + getBigIntType(selectedPlatform) + " ,"
+ "modified_date " + getBigIntType(selectedPlatform) + " ,"
+ "status_id integer NOT NULL,"
+ "CONSTRAINT uuid_unique UNIQUE(uuid),"
+ "FOREIGN KEY (status_id) REFERENCES persona_status(status_id)"
+ ")";
}
/**
* Get the SQL String for creating a new persona_alias table in a central
* repository.
*
* @return SQL string for creating persona_alias table
*/
static String getCreatePersonaAliasTableStatement(CentralRepoPlatforms selectedPlatform) {
return "CREATE TABLE IF NOT EXISTS persona_alias ("
+ getNumericPrimaryKeyClause("id", selectedPlatform)
+ "persona_id " + getBigIntType(selectedPlatform) + " ,"
+ "alias_id " + getBigIntType(selectedPlatform) + " ,"
+ "justification TEXT NOT NULL,"
+ "confidence_id integer NOT NULL,"
+ "date_added " + getBigIntType(selectedPlatform) + " ,"
+ "examiner_id integer NOT NULL,"
+ "FOREIGN KEY (persona_id) REFERENCES personas(id),"
+ "FOREIGN KEY (alias_id) REFERENCES aliases(id),"
+ "FOREIGN KEY (confidence_id) REFERENCES confidence(confidence_id),"
+ "FOREIGN KEY (examiner_id) REFERENCES examiners(id)"
+ ")";
}
/**
* Get the SQL String for creating a new persona_metadata table in a central
* repository.
*
* @return SQL string for creating persona_metadata table
*/
static String getCreatePersonaMetadataTableStatement(CentralRepoPlatforms selectedPlatform) {
return "CREATE TABLE IF NOT EXISTS persona_metadata ("
+ getNumericPrimaryKeyClause("id", selectedPlatform)
+ "persona_id " + getBigIntType(selectedPlatform) + " ,"
+ "name TEXT NOT NULL,"
+ "value TEXT NOT NULL,"
+ "justification TEXT NOT NULL,"
+ "confidence_id integer NOT NULL,"
+ "date_added " + getBigIntType(selectedPlatform) + " ,"
+ "examiner_id integer NOT NULL,"
+ "CONSTRAINT unique_metadata UNIQUE(persona_id, name),"
+ "FOREIGN KEY (persona_id) REFERENCES personas(id),"
+ "FOREIGN KEY (confidence_id) REFERENCES confidence(confidence_id),"
+ "FOREIGN KEY (examiner_id) REFERENCES examiners(id)"
+ ")";
}
/**
* Get the SQL String for creating a new persona_accounts table in a central
* repository.
*
* @return SQL string for creating persona_accounts table
*/
static String getCreatePersonaAccountsTableStatement(CentralRepoPlatforms selectedPlatform) {
return "CREATE TABLE IF NOT EXISTS persona_accounts ("
+ getNumericPrimaryKeyClause("id", selectedPlatform)
+ "persona_id " + getBigIntType(selectedPlatform) + " ,"
+ "account_id " + getBigIntType(selectedPlatform) + " ,"
+ "justification TEXT NOT NULL,"
+ "confidence_id integer NOT NULL,"
+ "date_added " + getBigIntType(selectedPlatform) + " ,"
+ "examiner_id integer NOT NULL,"
+ "FOREIGN KEY (persona_id) REFERENCES personas(id),"
+ "FOREIGN KEY (account_id) REFERENCES accounts(id),"
+ "FOREIGN KEY (confidence_id) REFERENCES confidence(confidence_id),"
+ "FOREIGN KEY (examiner_id) REFERENCES examiners(id)"
+ ")";
}
/**
* Inserts the default content in persona related tables.
*
* @param conn Database connection to use.
*
* @return True if success, false otherwise.
*/
private boolean insertDefaultPersonaTablesContent(Connection conn) {
Statement stmt = null;
try {
stmt = conn.createStatement();
// populate the confidence table
for (Confidence confidence : Persona.Confidence.values()) {
String sqlString = "INSERT INTO confidence (confidence_id, description) VALUES ( " + confidence.getLevel() + ", '" + confidence.toString() + "')" //NON-NLS
+ getOnConflictDoNothingClause(selectedPlatform);
stmt.execute(sqlString);
}
// populate the persona_status table
for (PersonaStatus status : Persona.PersonaStatus.values()) {
String sqlString = "INSERT INTO persona_status (status_id, status) VALUES ( " + status.getStatus() + ", '" + status.toString() + "')" //NON-NLS
+ getOnConflictDoNothingClause(selectedPlatform);
stmt.execute(sqlString);
}
// Populate the account_types table
for (Account.Type type : Account.Type.PREDEFINED_ACCOUNT_TYPES) {
int correlationTypeId = getCorrelationTypeIdForAccountType(conn, type);
if (correlationTypeId > 0) {
String sqlString = String.format("INSERT INTO account_types (type_name, display_name, correlation_type_id) VALUES ('%s', '%s', %d)" + getOnConflictDoNothingClause(selectedPlatform),
type.getTypeName(), type.getDisplayName(), correlationTypeId);
stmt.execute(sqlString);
}
}
} catch (SQLException ex) {
LOGGER.log(Level.SEVERE, String.format("Failed to populate default data in Persona tables."), ex);
return false;
} finally {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException ex2) {
LOGGER.log(Level.SEVERE, "Error closing statement.", ex2);
}
}
}
return true;
}
/**
* Returns the correlation type id for the given account type,
* from the correlation_types table.
*
* @param conn Connection to use for database query.
* @param accountType Account type to look for.
* '
* @return correlation type id.
*/
private int getCorrelationTypeIdForAccountType(Connection conn, Account.Type accountType) {
int typeId = -1;
if (accountType == Account.Type.EMAIL) {
typeId = CorrelationAttributeInstance.EMAIL_TYPE_ID;
} else if (accountType == Account.Type.PHONE) {
typeId = CorrelationAttributeInstance.PHONE_TYPE_ID;
} else {
String querySql = "SELECT * FROM correlation_types WHERE display_name=?";
try ( PreparedStatement preparedStatementQuery = conn.prepareStatement(querySql)) {
preparedStatementQuery.setString(1, accountType.getDisplayName());
try (ResultSet resultSet = preparedStatementQuery.executeQuery();) {
if (resultSet.next()) {
typeId = resultSet.getInt("id");
}
}
} catch (SQLException ex) {
LOGGER.log(Level.SEVERE, String.format("Failed to get correlation typeId for account type %s.", accountType.getTypeName()), ex);
}
}
return typeId;
}
}

View File

@ -7,3 +7,6 @@ IngestEventsListener.prevCount.text=Number of previous {0}: {1}
IngestEventsListener.prevExists.text=Previously Seen Devices (Central Repository)
IngestEventsListener.prevTaggedSet.text=Previously Tagged As Notable (Central Repository)
Installer.centralRepoUpgradeFailed.title=Central repository disabled
Installer.initialCreateSqlite.messageDesc=It will store information about all hashes and identifiers that you process. You can use this to ignore previously seen files and make connections between cases.
Installer.initialCreateSqlite.messageHeader=The Central Repository is not enabled. Would you like to?
Installer.initialCreateSqlite.title=Enable Central Repository?

View File

@ -1,7 +1,7 @@
/*
* Central Repository
*
* Copyright 2015-2018 Basis Technology Corp.
* Copyright 2017-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -52,7 +52,6 @@ import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskDataException;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
/**
@ -197,7 +196,7 @@ final class CaseEventListener implements PropertyChangeListener {
}
}
final CorrelationAttributeInstance eamArtifact = CorrelationAttributeUtil.makeInstanceFromContent(af);
final CorrelationAttributeInstance eamArtifact = CorrelationAttributeUtil.makeCorrAttrFromFile(af);
if (eamArtifact != null) {
// send update to Central Repository db
@ -297,7 +296,7 @@ final class CaseEventListener implements PropertyChangeListener {
return;
}
List<CorrelationAttributeInstance> convertedArtifacts = CorrelationAttributeUtil.makeInstancesFromBlackboardArtifact(bbArtifact, true);
List<CorrelationAttributeInstance> convertedArtifacts = CorrelationAttributeUtil.makeCorrAttrsFromArtifact(bbArtifact);
for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) {
eamArtifact.setComment(comment);
try {
@ -370,7 +369,7 @@ final class CaseEventListener implements PropertyChangeListener {
if (!hasTagWithConflictingKnownStatus) {
//Get the correlation atttributes that correspond to the current BlackboardArtifactTag if their status should be changed
//with the initial set of correlation attributes this should be a single correlation attribute
List<CorrelationAttributeInstance> convertedArtifacts = CorrelationAttributeUtil.makeInstancesFromBlackboardArtifact(bbTag.getArtifact(), true);
List<CorrelationAttributeInstance> convertedArtifacts = CorrelationAttributeUtil.makeCorrAttrsFromArtifact(bbTag.getArtifact());
for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) {
CentralRepository.getInstance().setAttributeInstanceKnownStatus(eamArtifact, tagName.getKnownStatus());
}
@ -406,12 +405,15 @@ final class CaseEventListener implements PropertyChangeListener {
}
//if the file will have no tags with a status which would prevent the current status from being changed
if (!hasTagWithConflictingKnownStatus) {
final CorrelationAttributeInstance eamArtifact = CorrelationAttributeUtil.makeInstanceFromContent(contentTag.getContent());
Content taggedContent = contentTag.getContent();
if (taggedContent instanceof AbstractFile) {
final CorrelationAttributeInstance eamArtifact = CorrelationAttributeUtil.makeCorrAttrFromFile((AbstractFile)taggedContent);
if (eamArtifact != null) {
CentralRepository.getInstance().setAttributeInstanceKnownStatus(eamArtifact, tagName.getKnownStatus());
}
}
}
}
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Cannot update known status in central repository for tag: " + modifiedTagName, ex); //NON-NLS
} catch (CentralRepoException ex) {
@ -513,7 +515,7 @@ final class CaseEventListener implements PropertyChangeListener {
Content dataSource = dataSourceNameChangedEvent.getDataSource();
String newName = (String) event.getNewValue();
if (! StringUtils.isEmpty(newName)) {
if (!StringUtils.isEmpty(newName)) {
if (!CentralRepository.isEnabled()) {
return;

View File

@ -1,7 +1,7 @@
/*
* Central Repository
*
* Copyright 2015-2019 Basis Technology Corp.
* Copyright 2017-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -456,7 +456,7 @@ public class IngestEventsListener {
for (BlackboardArtifact bbArtifact : bbArtifacts) {
// eamArtifact will be null OR a EamArtifact containing one EamArtifactInstance.
List<CorrelationAttributeInstance> convertedArtifacts = CorrelationAttributeUtil.makeInstancesFromBlackboardArtifact(bbArtifact, true);
List<CorrelationAttributeInstance> convertedArtifacts = CorrelationAttributeUtil.makeCorrAttrsFromArtifact(bbArtifact);
for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) {
try {
// Only do something with this artifact if it's unique within the job

View File

@ -2,7 +2,7 @@
*
* Autopsy Forensic Browser
*
* Copyright 2018-2019 Basis Technology Corp.
* Copyright 2018-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -123,8 +123,7 @@ final public class CommonAttributeCaseSearchResults {
if (currentCaseDataSourceMap == null) { //there are no results
return filteredCaseNameToDataSourcesTree;
}
CorrelationAttributeInstance.Type attributeType = CorrelationAttributeInstance
.getDefaultCorrelationTypes()
CorrelationAttributeInstance.Type attributeType = CentralRepository.getInstance().getCorrelationTypes()
.stream()
.filter(filterType -> filterType.getId() == resultTypeId)
.findFirst().get();

View File

@ -128,13 +128,12 @@ final public class CommonAttributeCountSearchResults {
return;
}
CorrelationAttributeInstance.Type attributeType = CorrelationAttributeInstance
.getDefaultCorrelationTypes()
CentralRepository eamDb = CentralRepository.getInstance();
CorrelationAttributeInstance.Type attributeType = eamDb.getCorrelationTypes()
.stream()
.filter(filterType -> filterType.getId() == this.resultTypeId)
.findFirst().get();
CentralRepository eamDb = CentralRepository.getInstance();
Map<Integer, List<CommonAttributeValue>> itemsToRemove = new HashMap<>();
//Call countUniqueDataSources once to reduce the number of DB queries needed to get

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2018 Basis Technology Corp.
* Copyright 2018-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -255,7 +255,7 @@ final class CommonAttributePanel extends javax.swing.JDialog implements Observer
filterByDocuments = interCasePanel.documentsCheckboxIsSelected();
}
if (corType == null) {
corType = CorrelationAttributeInstance.getDefaultCorrelationTypes().get(0);
corType = CentralRepository.getInstance().getCorrelationTypes().get(0);
}
if (caseId == InterCasePanel.NO_CASE_SELECTED) {
builder = new AllInterCaseCommonAttributeSearcher(filterByMedia, filterByDocuments, corType, percentageThreshold);
@ -366,7 +366,7 @@ final class CommonAttributePanel extends javax.swing.JDialog implements Observer
filterByDocuments = interCasePanel.documentsCheckboxIsSelected();
}
if (corType == null) {
corType = CorrelationAttributeInstance.getDefaultCorrelationTypes().get(0);
corType = CentralRepository.getInstance().getCorrelationTypes().get(0);
}
if (caseId == InterCasePanel.NO_CASE_SELECTED) {
builder = new AllInterCaseCommonAttributeSearcher(filterByMedia, filterByDocuments, corType, percentageThreshold);

View File

@ -2,7 +2,7 @@
*
* Autopsy Forensic Browser
*
* Copyright 2018-2019 Basis Technology Corp.
* Copyright 2018-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -31,6 +31,7 @@ import java.util.logging.Level;
import javax.swing.ComboBoxModel;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
@ -117,7 +118,7 @@ public final class InterCasePanel extends javax.swing.JPanel {
void setupCorrelationTypeFilter() {
this.correlationTypeFilters = new HashMap<>();
try {
List<CorrelationAttributeInstance.Type> types = CorrelationAttributeInstance.getDefaultCorrelationTypes();
List<CorrelationAttributeInstance.Type> types = CentralRepository.getInstance().getCorrelationTypes();
for (CorrelationAttributeInstance.Type type : types) {
correlationTypeFilters.put(type.getDisplayName(), type);
this.correlationTypeComboBox.addItem(type.getDisplayName());

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Copyright 2019-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -111,7 +111,7 @@ final class CorrelationCaseChildNodeFactory extends ChildFactory<CorrelationCase
private CorrelationAttributeInstance.Type getCorrelationType(Account.Type accountType) throws CentralRepoException {
if (correlationTypeMap == null) {
correlationTypeMap = new HashMap<>();
List<CorrelationAttributeInstance.Type> correcationTypeList = CorrelationAttributeInstance.getDefaultCorrelationTypes();
List<CorrelationAttributeInstance.Type> correcationTypeList = CentralRepository.getInstance().getCorrelationTypes();
correcationTypeList.forEach((type) -> {
correlationTypeMap.put(type.getId(), type);
});

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2018 Basis Technology Corp.
* Copyright 2018-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -198,7 +198,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
startSection(html, "Central Repository Comments");
List<CorrelationAttributeInstance> instancesList = new ArrayList<>();
if (artifact != null) {
instancesList.addAll(CorrelationAttributeUtil.makeInstancesFromBlackboardArtifact(artifact, false));
instancesList.addAll(CorrelationAttributeUtil.makeCorrAttrsFromArtifact(artifact));
}
try {
List<CorrelationAttributeInstance.Type> artifactTypes = CentralRepository.getInstance().getDefinedCorrelationTypes();

View File

@ -3,7 +3,13 @@ Installer.closing.confirmationDialog.title=Ingest is Running
# {0} - exception message
Installer.closing.messageBox.caseCloseExceptionMessage=Error closing case: {0}
OpenIDE-Module-Display-Category=Infrastructure
OpenIDE-Module-Long-Description=This is the core Autopsy module.\n\nThe module contains the core components needed for the bare application to run; the RCP platform, windowing GUI, sleuthkit bindings, datamodel / storage, explorer, result viewers, content viewers, ingest framework, reporting, and core tools, such as the file search.\n\nThe framework included in the module contains APIs for developing modules for ingest, viewers and reporting. The modules can be deployed as Plugins using the Autopsy plugin installer.\nThis module should not be uninstalled - without it, Autopsy will not run.\n\nFor more information, see http://www.sleuthkit.org/autopsy/
OpenIDE-Module-Long-Description=\
This is the core Autopsy module.\n\n\
The module contains the core components needed for the bare application to run; the RCP platform, windowing GUI, sleuthkit bindings, datamodel / storage, explorer, result viewers, content viewers, ingest framework, reporting, and core tools, such as the file search.\n\n\
The framework included in the module contains APIs for developing modules for ingest, viewers and reporting. \
The modules can be deployed as Plugins using the Autopsy plugin installer.\n\
This module should not be uninstalled - without it, Autopsy will not run.\n\n\
For more information, see http://www.sleuthkit.org/autopsy/
OpenIDE-Module-Name=Autopsy-Core
OpenIDE-Module-Short-Description=Autopsy Core Module
org_sleuthkit_autopsy_core_update_center=http://sleuthkit.org/autopsy/updates.xml

View File

@ -63,9 +63,9 @@ DataContentViewerHex.totalPageLabel.text_1=100
DataContentViewerHex.pageLabel2.text=Page
# Product Information panel
LBL_Description=<div style="font-size: 12pt; font-family: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif;">\n <b>Product Version:</b> {0} ({9}) <br><b>Sleuth Kit Version:</b> {7} <br><b>Netbeans RCP Build:</b> {8} <br> <b>Java:</b> {1}; {2}<br> <b>System:</b> {3}; {4}; {5}<br><b>Userdir:</b> {6}</div>
LBL_Description=<div style=\"font-size: 12pt; font-family: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif;\">\n <b>Product Version:</b> {0} ({9}) <br><b>Sleuth Kit Version:</b> {7} <br><b>Netbeans RCP Build:</b> {8} <br> <b>Java:</b> {1}; {2}<br> <b>System:</b> {3}; {4}; {5}<br><b>Userdir:</b> {6}</div>
Format_OperatingSystem_Value={0} version {1} running on {2}
LBL_Copyright=<div style="font-size: 12pt; font-family: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif; ">Autopsy&trade; is a digital forensics platform based on The Sleuth Kit&trade; and other tools. <br><ul><li>General Information: <a style="color: #1E2A60;" href="http://www.sleuthkit.org">http://www.sleuthkit.org</a>.</li><li>Training: <a style="color: #1E2A60;" href="http://www.basistech.com/autopsy-training">http://www.basistech.com/autopsy-training</a></li><li>Commercial Support: <a style="color: #1E2A60;" href="http://www.basistech.com/digital-forensics/autopsy/support/">http://www.basistech.com/digital-forensics/autopsy/support/</a></li></ul>Copyright &copy; 2003-2018. </div>
LBL_Copyright=<div style\="font-size: 12pt; font-family: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif; ">Autopsy&trade; is a digital forensics platform based on The Sleuth Kit&trade; and other tools. <br><ul><li>General Information: <a style\="color: \#1E2A60;" href\="http://www.sleuthkit.org">http://www.sleuthkit.org</a>.</li><li>Training: <a style\="color: \#1E2A60;" href\="http://www.basistech.com/autopsy-training">http://www.basistech.com/autopsy-training</a></li><li>Commercial Support: <a style\="color: \#1E2A60;" href\="http://www.basistech.com/digital-forensics/autopsy/support/">http://www.basistech.com/digital-forensics/autopsy/support/</a></li></ul>Copyright &copy; 2003-2018. </div>
SortChooser.dialogTitle=Choose Sort Criteria
ThumbnailViewChildren.progress.cancelling=(Cancelling)
# {0} - file name
@ -95,7 +95,7 @@ DataResultViewerThumbnail.pageNextButton.text=
DataResultViewerThumbnail.imagesLabel.text=Images:
DataResultViewerThumbnail.imagesRangeLabel.text=-
DataResultViewerThumbnail.pageNumLabel.text=-
DataResultViewerThumbnail.filePathLabel.text=\
DataResultViewerThumbnail.filePathLabel.text=\ \ \
DataResultViewerThumbnail.goToPageLabel.text=Go to Page:
DataResultViewerThumbnail.goToPageField.text=
AdvancedConfigurationDialog.cancelButton.text=Cancel

View File

@ -30,7 +30,9 @@ PlatformUtil.getProcVmUsed.sigarNotInit.msg=Cannot get virt mem used, sigar not
PlatformUtil.getProcVmUsed.gen.msg=Cannot get virt mem used, {0}
PlatformUtil.getJvmMemInfo.usageText=JVM heap usage: {0}, JVM non-heap usage: {1}
PlatformUtil.getPhysicalMemInfo.usageText=Physical memory usage (max, total, free): {0}, {1}, {2}
PlatformUtil.getAllMemUsageInfo.usageText={0}\n{1}\nProcess Virtual Memory: {2}
PlatformUtil.getAllMemUsageInfo.usageText={0}\n\
{1}\n\
Process Virtual Memory: {2}
# {0} - file name
ReadImageTask.mesageText=Reading image: {0}
StringExtract.illegalStateException.cannotInit.msg=Unicode table not properly initialized, cannot instantiate StringExtract

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2020 Basis Technology Corp.
* Copyright 2012-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -549,7 +549,7 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
protected CorrelationAttributeInstance getCorrelationAttributeInstance() {
CorrelationAttributeInstance attribute = null;
if (CentralRepository.isEnabled() && !UserPreferences.getHideSCOColumns()) {
attribute = CorrelationAttributeUtil.getInstanceFromContent(content);
attribute = CorrelationAttributeUtil.getCorrAttrForFile(content);
}
return attribute;
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2020 Basis Technology Corp.
* Copyright 2012-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -605,8 +605,8 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
@Override
protected final CorrelationAttributeInstance getCorrelationAttributeInstance() {
CorrelationAttributeInstance correlationAttribute = null;
if (CentralRepository.isEnabled()) {
correlationAttribute = CorrelationAttributeUtil.getInstanceFromContent(associated);
if (CentralRepository.isEnabled() && associated instanceof AbstractFile) {
correlationAttribute = CorrelationAttributeUtil.getCorrAttrForFile((AbstractFile)associated);
}
return correlationAttribute;
}

View File

@ -97,7 +97,7 @@ class GetSCOTask implements Runnable {
logger.log(Level.WARNING, "Unable to get correlation type or value to determine value for O column for artifact", ex);
}
} else {
List<CorrelationAttributeInstance> listOfPossibleAttributes = CorrelationAttributeUtil.makeInstancesFromBlackboardArtifact(bbArtifact, false);
List<CorrelationAttributeInstance> listOfPossibleAttributes = CorrelationAttributeUtil.makeCorrAttrsFromArtifact(bbArtifact);
if (listOfPossibleAttributes.size() > 1) {
//Don't display anything if there is more than 1 correlation property for an artifact but let the user know
description = Bundle.GetSCOTask_occurrences_multipleProperties();

View File

@ -65,8 +65,6 @@ FileSearchPanel.stepTwoLabel.text=Step 2: Filter which images to show
FileSearchPanel.stepThreeLabel.text=Step 3: Choose display settings
DiscoveryTopComponent.stepOneLabel.text=Step 1: Pick File Type
DiscoveryTopComponent.documentsButton.text=Documents
DocumentPanel.countLabel.toolTipText=
DocumentPanel.fileSizeLabel.toolTipText=
DocumentPanel.documentType.text=
DocumentPanel.isDeletedLabel.toolTipText=
ImageThumbnailPanel.isDeletedLabel.toolTipText=

View File

@ -14,8 +14,8 @@ DiscoveryUiUtility.megaBytes.text=MB
# {1} - units
DiscoveryUiUtility.sizeLabel.text=Size: {0} {1}
DiscoveryUiUtility.terraBytes.text=TB
# {0} - extension
DocumentPanel.documentType.extension.text=Extension: {0}
# {0} - otherInstanceCount
DocumentPanel.nameLabel.more.text=\ and {0} more
DocumentWrapper.previewInitialValue=Preview not generated yet.
FileGroup.groupSortingAlgorithm.groupName.text=Group Name
FileGroup.groupSortingAlgorithm.groupSize.text=Group Size
@ -24,6 +24,8 @@ FileGroup.groupSortingAlgorithm.groupSize.text=Group Size
FileSearch.DataSourceGroupKey.datasourceAndID={0}(ID: {1})
# {0} - Data source ID
FileSearch.DataSourceGroupKey.idOnly=Data source (ID: {0})
FileSearch.documentSummary.noBytes=No bytes read for document, unable to display preview.
FileSearch.documentSummary.noPreview=No preview available.
FileSearch.FileTagGroupKey.noSets=None
# {0} - file name
FileSearch.genVideoThumb.progress.text=extracting temporary file {0}
@ -173,9 +175,9 @@ FileSorter.SortingMethod.fullPath.displayName=Full Path
FileSorter.SortingMethod.keywordlist.displayName=Keyword List Names
GroupsListPanel.noResults.message.text=No results were found for the selected filters.
GroupsListPanel.noResults.title.text=No results found
# {0} - numberOfInstances
ImageThumbnailPanel.countLabel.text=Number of Instances: {0}
ImageThumbnailPanel.isDeleted.text=All instances of file are deleted.
# {0} - otherInstanceCount
ImageThumbnailPanel.nameLabel.more.text=\ and {0} more
OpenFileDiscoveryAction.resultsIncomplete.text=Results may be incomplete
ResultFile.score.interestingResult.description=At least one instance of the file has an interesting result associated with it.
ResultFile.score.notableFile.description=At least one instance of the file was recognized as notable.
@ -185,8 +187,7 @@ ResultFile.score.taggedFile.description=At least one instance of the file has be
# {1} - totalPages
ResultsPanel.currentPage.displayValue=Page: {0} of {1}
ResultsPanel.currentPageLabel.text=Page: -
ResultsPanel.documentPreviewWorker.noBytes=No bytes read for document, unable to display preview.
ResultsPanel.documentPreviewWorker.noPreview=No preview available.
ResultsPanel.documentPreview.text=Document preview creation cancelled.
# {0} - selectedPage
# {1} - maxPage
ResultsPanel.invalidPageNumber.message=The selected page number {0} does not exist. Please select a value from 1 to {1}.
@ -209,19 +210,18 @@ FileSearchPanel.stepTwoLabel.text=Step 2: Filter which images to show
FileSearchPanel.stepThreeLabel.text=Step 3: Choose display settings
DiscoveryTopComponent.stepOneLabel.text=Step 1: Pick File Type
DiscoveryTopComponent.documentsButton.text=Documents
DocumentPanel.countLabel.toolTipText=
DocumentPanel.fileSizeLabel.toolTipText=
DocumentPanel.documentType.text=
DocumentPanel.isDeletedLabel.toolTipText=
ImageThumbnailPanel.isDeletedLabel.toolTipText=
ResultsPanel.unableToCreate.text=Unable to create summary.
ResultsPanel.viewFileInDir.name=View File in Directory
VideoThumbnailPanel.bytes.text=bytes
# {0} - numberOfInstances
VideoThumbnailPanel.countLabel.text=Number of Instances: {0}
VideoThumbnailPanel.deleted.text=All instances of file are deleted.
VideoThumbnailPanel.gigaBytes.text=GB
VideoThumbnailPanel.kiloBytes.text=KB
VideoThumbnailPanel.megaBytes.text=MB
# {0} - otherInstanceCount
VideoThumbnailPanel.nameLabel.more.text=\ and {0} more
# {0} - fileSize
# {1} - units
VideoThumbnailPanel.sizeLabel.text=Size: {0} {1}

View File

@ -27,15 +27,14 @@
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="countLabel" min="-2" pref="530" max="-2" attributes="0"/>
<EmptySpace pref="81" max="32767" attributes="0"/>
<Component id="fileSizeLabel" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="isDeletedLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="scoreLabel" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="fileSizeLabel" alignment="1" max="32767" attributes="0"/>
<Component id="previewScrollPane" max="32767" attributes="0"/>
<Component id="documentType" alignment="0" max="32767" attributes="0"/>
<Component id="previewScrollPane" pref="649" max="32767" attributes="0"/>
<Component id="nameLabel" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -45,16 +44,14 @@
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="documentType" min="-2" pref="16" max="-2" attributes="0"/>
<Component id="nameLabel" min="-2" pref="16" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="previewScrollPane" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="fileSizeLabel" min="-2" pref="16" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="scoreLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="isDeletedLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="countLabel" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="fileSizeLabel" min="-2" pref="16" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -62,22 +59,6 @@
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="countLabel">
<Properties>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filequery/Bundle.properties" key="DocumentPanel.countLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[159, 12]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[159, 12]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[159, 12]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="isDeletedLabel">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
@ -121,12 +102,7 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="documentType">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filequery/Bundle.properties" key="DocumentPanel.documentType.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Component class="javax.swing.JLabel" name="nameLabel">
</Component>
<Container class="javax.swing.JScrollPane" name="previewScrollPane">
<Properties>

View File

@ -52,21 +52,15 @@ public class DocumentPanel extends javax.swing.JPanel implements ListCellRendere
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
countLabel = new javax.swing.JLabel();
isDeletedLabel = new javax.swing.JLabel();
scoreLabel = new javax.swing.JLabel();
fileSizeLabel = new javax.swing.JLabel();
documentType = new javax.swing.JLabel();
nameLabel = new javax.swing.JLabel();
javax.swing.JScrollPane previewScrollPane = new javax.swing.JScrollPane();
previewTextArea = new javax.swing.JTextArea();
setBorder(javax.swing.BorderFactory.createEtchedBorder());
countLabel.setToolTipText(org.openide.util.NbBundle.getMessage(DocumentPanel.class, "DocumentPanel.countLabel.toolTipText")); // NOI18N
countLabel.setMaximumSize(new java.awt.Dimension(159, 12));
countLabel.setMinimumSize(new java.awt.Dimension(159, 12));
countLabel.setPreferredSize(new java.awt.Dimension(159, 12));
isDeletedLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/file-icon-deleted.png"))); // NOI18N
isDeletedLabel.setToolTipText(org.openide.util.NbBundle.getMessage(DocumentPanel.class, "DocumentPanel.isDeletedLabel.toolTipText")); // NOI18N
isDeletedLabel.setMaximumSize(new Dimension(org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize()));
@ -81,8 +75,6 @@ public class DocumentPanel extends javax.swing.JPanel implements ListCellRendere
fileSizeLabel.setToolTipText(org.openide.util.NbBundle.getMessage(DocumentPanel.class, "DocumentPanel.fileSizeLabel.toolTipText")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(documentType, org.openide.util.NbBundle.getMessage(DocumentPanel.class, "DocumentPanel.documentType.text")); // NOI18N
previewScrollPane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
previewTextArea.setEditable(false);
@ -104,57 +96,55 @@ public class DocumentPanel extends javax.swing.JPanel implements ListCellRendere
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(countLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 530, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 81, Short.MAX_VALUE)
.addComponent(fileSizeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(isDeletedLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(fileSizeLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(previewScrollPane)
.addComponent(documentType, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(previewScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 649, Short.MAX_VALUE)
.addComponent(nameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(documentType, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(nameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(previewScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fileSizeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(isDeletedLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(countLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(fileSizeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel countLabel;
private javax.swing.JLabel documentType;
private javax.swing.JLabel fileSizeLabel;
private javax.swing.JLabel isDeletedLabel;
private javax.swing.JLabel nameLabel;
private javax.swing.JTextArea previewTextArea;
private javax.swing.JLabel scoreLabel;
// End of variables declaration//GEN-END:variables
@Messages({"# {0} - extension",
"DocumentPanel.documentType.extension.text=Extension: {0}"})
@Messages({"# {0} - otherInstanceCount",
"DocumentPanel.nameLabel.more.text= and {0} more"})
@Override
public Component getListCellRendererComponent(JList<? extends DocumentWrapper> list, DocumentWrapper value, int index, boolean isSelected, boolean cellHasFocus) {
fileSizeLabel.setText(DiscoveryUiUtils.getFileSizeString(value.getResultFile().getFirstInstance().getSize()));
countLabel.setText(Bundle.ImageThumbnailPanel_countLabel_text(value.getResultFile().getAllInstances().size()));
documentType.setText(Bundle.DocumentPanel_documentType_extension_text(value.getResultFile().getFirstInstance().getNameExtension())); //WJS-TODO fill this in with a document type instead of just DOCUMENT
String nameText = value.getResultFile().getFirstInstance().getParentPath() + value.getResultFile().getFirstInstance().getName();
if (value.getResultFile().getAllInstances().size() > 1) {
nameText += Bundle.DocumentPanel_nameLabel_more_text(value.getResultFile().getAllInstances().size() - 1);
}
nameLabel.setText(nameText);
previewTextArea.setText(value.getPreview());
previewTextArea.setCaretPosition(0);
DiscoveryUiUtils.setDeletedIcon(value.getResultFile().isDeleted(), isDeletedLabel);
DiscoveryUiUtils.setScoreIcon(value.getResultFile(), scoreLabel);
setBackground(isSelected ? SELECTION_COLOR : list.getBackground());
return this;
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Copyright 2019-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -25,11 +25,13 @@ import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Paths;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@ -43,9 +45,11 @@ import java.util.logging.Level;
import javax.imageio.ImageIO;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.netbeans.api.progress.ProgressHandle;
import org.opencv.core.Mat;
import org.opencv.highgui.VideoCapture;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
@ -71,6 +75,9 @@ import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.textextractors.TextExtractor;
import org.sleuthkit.autopsy.textextractors.TextExtractorFactory;
import org.sleuthkit.autopsy.textsummarizer.TextSummarizer;
/**
* Main class to perform the file search.
@ -84,6 +91,8 @@ class FileSearch {
private static final Cache<SearchKey, Map<GroupKey, List<ResultFile>>> searchCache = CacheBuilder.newBuilder()
.maximumSize(MAXIMUM_CACHE_SIZE)
.build();
private static final int PREVIEW_SIZE = 256;
private static volatile TextSummarizer summarizerToUse = null;
/**
* Run the file search and returns the SearchResults object for debugging.
@ -239,6 +248,78 @@ class FileSearch {
return page;
}
/**
* Get a summary for the specified AbstractFile. If no TextSummarizers exist
* get the beginning of the file.
*
* @param file The AbstractFile to summarize.
*
* @return The summary or beginning of the specified file as a String.
*/
@NbBundle.Messages({"FileSearch.documentSummary.noPreview=No preview available.",
"FileSearch.documentSummary.noBytes=No bytes read for document, unable to display preview."})
static String summarize(AbstractFile file) {
String summary = null;
TextSummarizer localSummarizer = summarizerToUse;
if (localSummarizer == null) {
synchronized (searchCache) {
if (localSummarizer == null) {
localSummarizer = getLocalSummarizer();
}
}
}
if (localSummarizer != null) {
try {
//a summary of length 40 seems to fit without vertical scroll bars
summary = localSummarizer.summarize(file, 40);
} catch (IOException ex) {
return Bundle.FileSearch_documentSummary_noPreview();
}
}
if (StringUtils.isBlank(summary)) {
//no summarizer was found or summary was empty just grab the beginning of the file
summary = getFirstLines(file);
}
return summary;
}
/**
* Get the beginning of text from the specified AbstractFile.
*
* @param file The AbstractFile to get text from.
*
* @return The beginning of text from the specified AbstractFile.
*/
private static String getFirstLines(AbstractFile file) {
try (Reader reader = TextExtractorFactory.getExtractor(file, null).getReader()) {
char[] cbuf = new char[PREVIEW_SIZE];
reader.read(cbuf, 0, PREVIEW_SIZE);
return new String(cbuf);
} catch (IOException ex) {
return Bundle.FileSearch_documentSummary_noBytes();
} catch (TextExtractorFactory.NoTextExtractorFound | TextExtractor.InitReaderException ex) {
return Bundle.FileSearch_documentSummary_noPreview();
}
}
/**
* Get the first TextSummarizer found by a lookup of TextSummarizers.
*
* @return The first TextSummarizer found by a lookup of TextSummarizers.
*
* @throws IOException
*/
private static TextSummarizer getLocalSummarizer() {
Collection<? extends TextSummarizer> summarizers
= Lookup.getDefault().lookupAll(TextSummarizer.class
);
if (!summarizers.isEmpty()) {
summarizerToUse = summarizers.iterator().next();
return summarizerToUse;
}
return null;
}
/**
* Run the file search. Caching new results for access at later time.
*
@ -597,7 +678,6 @@ class FileSearch {
int framePos = Integer.valueOf(FilenameUtils.getBaseName(fileName).substring(2));
framePositions[thumbnailNumber] = framePos;
thumbnailNumber++;
}
thumbnailWrapper.setThumbnails(videoThumbnails, framePositions);
}

View File

@ -20,36 +20,36 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="thumbnailPanel" pref="201" max="32767" attributes="0"/>
<Component id="fileSizeLabel" alignment="0" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Component id="countLabel" max="-2" attributes="0"/>
<Component id="fileSizeLabel" min="-2" pref="163" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="isDeletedLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="scoreLabel" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="103" groupAlignment="1" max="-2" attributes="0">
<Component id="nameLabel" alignment="0" max="32767" attributes="0"/>
<Component id="thumbnailPanel" alignment="0" pref="201" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="nameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="thumbnailPanel" min="-2" pref="178" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="fileSizeLabel" min="-2" pref="16" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="scoreLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="isDeletedLabel" min="-2" max="-2" attributes="0"/>
<Component id="countLabel" alignment="1" min="-2" max="-2" attributes="0"/>
<Component id="fileSizeLabel" min="-2" pref="16" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -82,7 +82,7 @@
<Property name="toolTipText" type="java.lang.String" value=""/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="countLabel">
<Component class="javax.swing.JLabel" name="nameLabel">
<Properties>
<Property name="toolTipText" type="java.lang.String" value=""/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">

View File

@ -36,6 +36,7 @@ public class ImageThumbnailPanel extends javax.swing.JPanel implements ListCellR
private static final long serialVersionUID = 1L;
private static final Color SELECTION_COLOR = new Color(0, 120, 215);
private static final int MAX_NAME_STRING = 30;
/**
* Creates new form ImageThumbnailPanel
@ -56,7 +57,7 @@ public class ImageThumbnailPanel extends javax.swing.JPanel implements ListCellR
javax.swing.JPanel thumbnailPanel = new javax.swing.JPanel();
thumbnailLabel = new javax.swing.JLabel();
fileSizeLabel = new javax.swing.JLabel();
countLabel = new javax.swing.JLabel();
nameLabel = new javax.swing.JLabel();
isDeletedLabel = new javax.swing.JLabel();
scoreLabel = new javax.swing.JLabel();
@ -68,22 +69,22 @@ public class ImageThumbnailPanel extends javax.swing.JPanel implements ListCellR
fileSizeLabel.setToolTipText("");
countLabel.setToolTipText("");
countLabel.setMaximumSize(new java.awt.Dimension(159, 12));
countLabel.setMinimumSize(new java.awt.Dimension(159, 12));
countLabel.setPreferredSize(new java.awt.Dimension(159, 12));
nameLabel.setToolTipText("");
nameLabel.setMaximumSize(new java.awt.Dimension(159, 12));
nameLabel.setMinimumSize(new java.awt.Dimension(159, 12));
nameLabel.setPreferredSize(new java.awt.Dimension(159, 12));
isDeletedLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/file-icon-deleted.png"))); // NOI18N
isDeletedLabel.setToolTipText(org.openide.util.NbBundle.getMessage(ImageThumbnailPanel.class, "ImageThumbnailPanel.isDeletedLabel.toolTipText")); // NOI18N
isDeletedLabel.setMaximumSize(new Dimension(DiscoveryUiUtils.getIconSize(),DiscoveryUiUtils.getIconSize()));
isDeletedLabel.setMinimumSize(new Dimension(DiscoveryUiUtils.getIconSize(),DiscoveryUiUtils.getIconSize()));
isDeletedLabel.setPreferredSize(new Dimension(DiscoveryUiUtils.getIconSize(),DiscoveryUiUtils.getIconSize()));
isDeletedLabel.setMaximumSize(new Dimension(org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize()));
isDeletedLabel.setMinimumSize(new Dimension(org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize()));
isDeletedLabel.setPreferredSize(new Dimension(org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize()));
scoreLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/red-circle-exclamation.png"))); // NOI18N
scoreLabel.setToolTipText("");
scoreLabel.setMaximumSize(new Dimension(DiscoveryUiUtils.getIconSize(),DiscoveryUiUtils.getIconSize()));
scoreLabel.setMinimumSize(new Dimension(DiscoveryUiUtils.getIconSize(),DiscoveryUiUtils.getIconSize()));
scoreLabel.setPreferredSize(new Dimension(DiscoveryUiUtils.getIconSize(),DiscoveryUiUtils.getIconSize()));
scoreLabel.setMaximumSize(new Dimension(org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize()));
scoreLabel.setMinimumSize(new Dimension(org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize()));
scoreLabel.setPreferredSize(new Dimension(org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize()));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
@ -92,50 +93,57 @@ public class ImageThumbnailPanel extends javax.swing.JPanel implements ListCellR
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(thumbnailPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 201, Short.MAX_VALUE)
.addComponent(fileSizeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addComponent(countLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(fileSizeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 163, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(isDeletedLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(nameLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(thumbnailPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 201, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(nameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(thumbnailPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 178, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(fileSizeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(isDeletedLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(countLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(fileSizeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel countLabel;
private javax.swing.JLabel fileSizeLabel;
private javax.swing.JLabel isDeletedLabel;
private javax.swing.JLabel nameLabel;
private javax.swing.JLabel scoreLabel;
private javax.swing.JLabel thumbnailLabel;
// End of variables declaration//GEN-END:variables
@NbBundle.Messages({
"# {0} - numberOfInstances",
"ImageThumbnailPanel.countLabel.text=Number of Instances: {0}",
"# {0} - otherInstanceCount",
"ImageThumbnailPanel.nameLabel.more.text= and {0} more",
"ImageThumbnailPanel.isDeleted.text=All instances of file are deleted."})
@Override
public Component getListCellRendererComponent(JList<? extends ImageThumbnailWrapper> list, ImageThumbnailWrapper value, int index, boolean isSelected, boolean cellHasFocus) {
fileSizeLabel.setText(DiscoveryUiUtils.getFileSizeString(value.getResultFile().getFirstInstance().getSize()));
countLabel.setText(Bundle.ImageThumbnailPanel_countLabel_text(value.getResultFile().getAllInstances().size()));
String nameText = value.getResultFile().getFirstInstance().getParentPath() + value.getResultFile().getFirstInstance().getName();
if (value.getResultFile().getAllInstances().size() > 1) {
nameText += Bundle.ImageThumbnailPanel_nameLabel_more_text(value.getResultFile().getAllInstances().size() - 1);
}
if (nameText.length() > MAX_NAME_STRING) {
nameText = "..." + nameText.substring(nameText.length() - (MAX_NAME_STRING - 3));
}
nameLabel.setText(nameText);
thumbnailLabel.setIcon(new ImageIcon(value.getThumbnail()));
DiscoveryUiUtils.setDeletedIcon(value.getResultFile().isDeleted(), isDeletedLabel);
DiscoveryUiUtils.setScoreIcon(value.getResultFile(), scoreLabel);
@ -163,5 +171,4 @@ public class ImageThumbnailPanel extends javax.swing.JPanel implements ListCellR
return null;
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy
*
* Copyright 2019 Basis Technology Corp.
* Copyright 2019-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -28,6 +28,8 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
@ -38,14 +40,12 @@ import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.event.ListSelectionListener;
import org.apache.commons.lang3.StringUtils;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.actions.AddContentTagAction;
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
import org.sleuthkit.autopsy.coreutils.ImageUtils;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.StringExtract;
import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
@ -702,6 +702,13 @@ public class ResultsPanel extends javax.swing.JPanel {
@Override
protected void done() {
try {
get();
} catch (InterruptedException | ExecutionException ex) {
logger.log(Level.WARNING, "Video Worker Exception for file: " + thumbnailWrapper.getResultFile().getFirstInstance().getId(), ex);
} catch (CancellationException ignored) {
//we want to do nothing in response to this since we allow it to be cancelled
}
videoThumbnailViewer.repaint();
}
}
@ -736,6 +743,13 @@ public class ResultsPanel extends javax.swing.JPanel {
@Override
protected void done() {
try {
get();
} catch (InterruptedException | ExecutionException ex) {
logger.log(Level.WARNING, "Image Worker Exception for file: " + thumbnailWrapper.getResultFile().getFirstInstance().getId(), ex);
} catch (CancellationException ignored) {
//we want to do nothing in response to this since we allow it to be cancelled
}
imageThumbnailViewer.repaint();
}
@ -748,7 +762,6 @@ public class ResultsPanel extends javax.swing.JPanel {
private class DocumentPreviewWorker extends SwingWorker<Void, Void> {
private final DocumentWrapper documentWrapper;
private static final int PREVIEW_SIZE = 256;
/**
* Construct a new DocumentPreviewWorker.
@ -761,55 +774,29 @@ public class ResultsPanel extends javax.swing.JPanel {
documentPreviewViewer.addDocument(documentWrapper);
}
@Messages({"ResultsPanel.unableToCreate.text=Unable to create summary."})
@Override
protected Void doInBackground() throws Exception {
String preview = createPreview(documentWrapper.getResultFile().getFirstInstance());
if (preview != null) {
documentWrapper.setPreview(preview);
String preview = FileSearch.summarize(documentWrapper.getResultFile().getFirstInstance());
if (preview == null) {
preview = Bundle.ResultsPanel_unableToCreate_text();
}
documentWrapper.setPreview(preview);
return null;
}
/**
* Create the string that will be used as the preview for the specified
* AbstractFile.
*
* @param file The AbstractFile to create the preview for.
*
* @return The String which is the preview for the specified
* AbstractFile.
*/
@Messages({"ResultsPanel.documentPreviewWorker.noPreview=No preview available.",
"ResultsPanel.documentPreviewWorker.noBytes=No bytes read for document, unable to display preview."})
private String createPreview(AbstractFile file) {
byte[] data = new byte[PREVIEW_SIZE];
int bytesRead = 0;
if (file.getSize() > 0) {
try {
int length = PREVIEW_SIZE > file.getSize() ? (int) file.getSize() : PREVIEW_SIZE; //if the size is less than the int it can be cast to an int
bytesRead = file.read(data, 0, length); // read the data
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error while trying to show the String content.", ex); //NON-NLS
}
}
String text;
if (bytesRead > 0) {
StringExtract stringExtract = new StringExtract();
final StringExtract.StringExtractUnicodeTable.SCRIPT selScript = StringExtract.StringExtractUnicodeTable.SCRIPT.LATIN_1;
stringExtract.setEnabledScript(selScript);
StringExtract.StringExtractResult res = stringExtract.extract(data, bytesRead, 0);
text = res.getText();
if (StringUtils.isBlank(text)) {
text = Bundle.ResultsPanel_documentPreviewWorker_noPreview();
}
} else {
text = Bundle.ResultsPanel_documentPreviewWorker_noBytes();
}
return text;
}
@Messages({"ResultsPanel.documentPreview.text=Document preview creation cancelled."})
@Override
protected void done() {
try {
get();
} catch (InterruptedException | ExecutionException ex) {
documentWrapper.setPreview(ex.getMessage());
logger.log(Level.WARNING, "Document Worker Exception", ex);
} catch (CancellationException ignored) {
documentWrapper.setPreview(Bundle.ResultsPanel_documentPreview_text());
//we want to do nothing in response to this since we allow it to be cancelled
}
documentPreviewViewer.repaint();
}

View File

@ -24,38 +24,36 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="imagePanel" alignment="0" pref="776" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="fileSizeLabel" min="-2" pref="248" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="countLabel" min="-2" pref="124" max="-2" attributes="0"/>
<Component id="fileSizeLabel" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="deletedLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="scoreLabel" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="nameLabel" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="nameLabel" min="-2" pref="14" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="imagePanel" min="-2" pref="140" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="fileSizeLabel" min="-2" pref="19" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="deletedLabel" min="-2" max="-2" attributes="0"/>
<Component id="fileSizeLabel" min="-2" pref="14" max="-2" attributes="0"/>
<Component id="scoreLabel" min="-2" max="-2" attributes="0"/>
<Component id="countLabel" alignment="1" min="-2" pref="19" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -67,7 +65,7 @@
</Container>
<Component class="javax.swing.JLabel" name="fileSizeLabel">
</Component>
<Component class="javax.swing.JLabel" name="countLabel">
<Component class="javax.swing.JLabel" name="nameLabel">
</Component>
<Component class="javax.swing.JLabel" name="scoreLabel">
<Properties>

View File

@ -100,7 +100,7 @@ final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRe
imagePanel = new javax.swing.JPanel();
fileSizeLabel = new javax.swing.JLabel();
countLabel = new javax.swing.JLabel();
nameLabel = new javax.swing.JLabel();
scoreLabel = new javax.swing.JLabel();
deletedLabel = new javax.swing.JLabel();
@ -109,14 +109,14 @@ final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRe
imagePanel.setLayout(new java.awt.GridBagLayout());
scoreLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/red-circle-exclamation.png"))); // NOI18N
scoreLabel.setMaximumSize(new Dimension(DiscoveryUiUtils.getIconSize(),DiscoveryUiUtils.getIconSize()));
scoreLabel.setMinimumSize(new Dimension(DiscoveryUiUtils.getIconSize(),DiscoveryUiUtils.getIconSize()));
scoreLabel.setPreferredSize(new Dimension(DiscoveryUiUtils.getIconSize(),DiscoveryUiUtils.getIconSize()));
scoreLabel.setMaximumSize(new Dimension(org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize()));
scoreLabel.setMinimumSize(new Dimension(org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize()));
scoreLabel.setPreferredSize(new Dimension(org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize()));
deletedLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/file-icon-deleted.png"))); // NOI18N
deletedLabel.setMaximumSize(new Dimension(DiscoveryUiUtils.getIconSize(),DiscoveryUiUtils.getIconSize()));
deletedLabel.setMinimumSize(new Dimension(DiscoveryUiUtils.getIconSize(),DiscoveryUiUtils.getIconSize()));
deletedLabel.setPreferredSize(new Dimension(DiscoveryUiUtils.getIconSize(),DiscoveryUiUtils.getIconSize()));
deletedLabel.setMaximumSize(new Dimension(org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize()));
deletedLabel.setMinimumSize(new Dimension(org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize()));
deletedLabel.setPreferredSize(new Dimension(org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize(),org.sleuthkit.autopsy.filequery.DiscoveryUiUtils.getIconSize()));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
@ -127,48 +127,51 @@ final class VideoThumbnailPanel extends javax.swing.JPanel implements ListCellRe
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(imagePanel, javax.swing.GroupLayout.DEFAULT_SIZE, 776, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(fileSizeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 248, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(countLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(fileSizeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(deletedLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(nameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(nameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(imagePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 140, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(fileSizeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(deletedLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(countLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(fileSizeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(scoreLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel countLabel;
private javax.swing.JLabel deletedLabel;
private javax.swing.JLabel fileSizeLabel;
private javax.swing.JPanel imagePanel;
private javax.swing.JLabel nameLabel;
private javax.swing.JLabel scoreLabel;
// End of variables declaration//GEN-END:variables
@Messages({
"# {0} - numberOfInstances",
"VideoThumbnailPanel.countLabel.text=Number of Instances: {0}",
"# {0} - otherInstanceCount",
"VideoThumbnailPanel.nameLabel.more.text= and {0} more",
"VideoThumbnailPanel.deleted.text=All instances of file are deleted."})
@Override
public Component getListCellRendererComponent(JList<? extends VideoThumbnailsWrapper> list, VideoThumbnailsWrapper value, int index, boolean isSelected, boolean cellHasFocus) {
fileSizeLabel.setText(getFileSizeString(value.getResultFile().getFirstInstance().getSize()));
countLabel.setText(Bundle.VideoThumbnailPanel_countLabel_text(value.getResultFile().getAllInstances().size()));
String nameText = value.getResultFile().getFirstInstance().getParentPath() + value.getResultFile().getFirstInstance().getName();
if (value.getResultFile().getAllInstances().size() > 1) {
nameText += Bundle.VideoThumbnailPanel_nameLabel_more_text(value.getResultFile().getAllInstances().size() - 1);
}
nameLabel.setText(nameText);
addThumbnails(value);
imagePanel.setBackground(isSelected ? SELECTION_COLOR : list.getBackground());
DiscoveryUiUtils.setDeletedIcon(value.getResultFile().isDeleted(), deletedLabel);

View File

@ -14,7 +14,7 @@ KnownStatusSearchPanel.knownCheckBox.text=Known Status:
KnownStatusSearchPanel.knownBadOptionCheckBox.text=Notable
KnownStatusSearchPanel.knownOptionCheckBox.text=Known (NSRL or other)
KnownStatusSearchPanel.unknownOptionCheckBox.text=Unknown
DateSearchFilter.noneSelectedMsg.text=At least one date type must be selected!
DateSearchFilter.noneSelectedMsg.text=At least one date type must be selected\!
DateSearchPanel.dateCheckBox.text=Date:
DateSearchPanel.jLabel4.text=Timezone:
DateSearchPanel.jLabel3.text=*The date format is mm/dd/yyyy
@ -57,7 +57,7 @@ FileSearchPanel.search.results.details=Large number of matches may impact perfor
FileSearchPanel.search.exception.noFilterSelected.msg=At least one filter must be selected.
FileSearchPanel.search.validationErr.msg=Validation Error: {0}
FileSearchPanel.emptyWhereClause.text=Invalid options, nothing to show.
KnownStatusSearchFilter.noneSelectedMsg.text=At least one known status must be selected!
KnownStatusSearchFilter.noneSelectedMsg.text=At least one known status must be selected\!
NameSearchFilter.emptyNameMsg.text=Must enter something for name search.
SizeSearchPanel.sizeCompareComboBox.equalTo=equal to
SizeSearchPanel.sizeCompareComboBox.greaterThan=greater than

View File

@ -30,6 +30,8 @@ GeoTopComponent_no_waypoints_returned_mgs=Applied filter failed to find waypoint
GeoTopComponent_no_waypoints_returned_Title=No Waypoints Found
GLTopComponent_initilzation_error=An error occurred during waypoint initilization. Geolocation data maybe incomplete.
GLTopComponent_name=Geolocation
GLTopComponent_No_dataSource_message=There are no data sources with Geolocation artifacts found.
GLTopComponent_No_dataSource_Title=No Geolocation artifacts found
HidingPane_default_title=Filters
MapPanel_connection_failure_message=Failed to connect to new geolocation map tile source.
MapPanel_connection_failure_message_title=Connection Failure

View File

@ -52,6 +52,7 @@ class GeoFilterPanel extends javax.swing.JPanel {
private final CheckBoxListPanel<DataSource> checkboxPanel;
// Make sure to update if
@SuppressWarnings("deprecation")
private static final BlackboardArtifact.ARTIFACT_TYPE[] GPS_ARTIFACT_TYPES = {
BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK,
BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION,

View File

@ -140,7 +140,7 @@ IngestJob.cancelReason.outOfDiskSpace.text=Out of disk space
IngestJob.cancelReason.servicesDown.text=Services Down
IngestJob.cancelReason.caseClosed.text=Case closed
IngestJobSettingsPanel.globalSettingsButton.text=Global Settings
gest=
gest
IngestJobSettingsPanel.globalSettingsButton.actionCommand=Advanced
IngestJobSettingsPanel.globalSettingsButton.text=Global Settings
IngestJobSettingsPanel.pastJobsButton.text=History

View File

@ -1,6 +1,6 @@
DATExtractor_process_message=Processing DJI DAT file: %s
DATFileExtractor_Extractor_Name=DAT File Extractor
DroneIngestModule_Description=Description
DroneIngestModule_Name=Drone
DroneIngestModule_Description=Analyzes files generated by drones.
DroneIngestModule_Name=Drone Analyzer
# {0} - AbstractFileName
DroneIngestModule_process_start=Started {0}

View File

@ -11,7 +11,12 @@ ExtractArchiveWithPasswordAction.progress.text=Unpacking contents of archive: {0
ExtractArchiveWithPasswordAction.prompt.text=Enter Password
ExtractArchiveWithPasswordAction.prompt.title=Enter Password
OpenIDE-Module-Display-Category=Ingest Module
OpenIDE-Module-Long-Description=Embedded File Extraction Ingest Module\n\nThe Embedded File Extraction Ingest Module processes document files (such as doc, docx, ppt, pptx, xls, xlsx) and archive files (such as zip and others archive types supported by the 7zip extractor).\nContents of these files are extracted and the derived files are added back to the current ingest to be processed by the configured ingest modules.\nIf the derived file happens to be an archive file, it will be re-processed by the 7zip extractor - the extractor will process archive files N-levels deep.\n\nThe extracted files are navigable in the directory tree.\n\nThe module is supported on Windows, Linux and Mac operating systems.
OpenIDE-Module-Long-Description=\
Embedded File Extraction Ingest Module\n\nThe Embedded File Extraction Ingest Module processes document files (such as doc, docx, ppt, pptx, xls, xlsx) and archive files (such as zip and others archive types supported by the 7zip extractor).\n\
Contents of these files are extracted and the derived files are added back to the current ingest to be processed by the configured ingest modules.\n\
If the derived file happens to be an archive file, it will be re-processed by the 7zip extractor - the extractor will process archive files N-levels deep.\n\n\
The extracted files are navigable in the directory tree.\n\n\
The module is supported on Windows, Linux and Mac operating systems.
OpenIDE-Module-Name=Embedded File Extraction
OpenIDE-Module-Short-Description=Embedded File Extraction Ingest Module
EmbeddedFileExtractorIngestModule.SevenZipContentReadStream.seek.exception.invalidOrigin=Invalid seek origin: {0}
@ -23,7 +28,6 @@ EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnMsg=Possib
EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnDetails=Compression ratio is {0}, skipping items in {1}.
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.warnMsg.zipBomb=Possible ZIP bomb detected: {0}
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.warnDetails.zipBomb=The archive is {0} levels deep, skipping processing of {1}
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.unknownPath.msg=Unknown item path in archive: {0}, will use: {1}
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.notEnoughDiskSpace.msg=Not enough disk space to unpack archive item: {0}, {1}
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.notEnoughDiskSpace.details=The archive item is too large to unpack, skipping unpacking this item.
EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.errUnpacking.msg=Error unpacking {0}

View File

@ -2,7 +2,9 @@ CannotRunFileTypeDetection=Cannot run file type detection.
ExifParserFileIngestModule.indexError.message=Failed to post EXIF Metadata artifact(s).
ExifParserFileIngestModule.userContent.description=EXIF metadata exists for this file.
OpenIDE-Module-Display-Category=Ingest Module
OpenIDE-Module-Long-Description=Exif metadata ingest module. \n\nThe ingest module analyzes image files, extracts Exif information and posts the Exif data as results.
OpenIDE-Module-Long-Description=\
Exif metadata ingest module. \n\n\
The ingest module analyzes image files, extracts Exif information and posts the Exif data as results.
OpenIDE-Module-Name=ExifParser
OpenIDE-Module-Short-Description=Exif metadata ingest module
ExifParserFileIngestModule.moduleName.text=Exif Parser

View File

@ -36,27 +36,27 @@ FileExtMismatchSettingsPanel.jLabel1.text=File Types:
FileExtMismatchSettingsPanel.newExtButton.text=New Extension
FileExtMismatchSettingsPanel.newMimePrompt.message=Add a new MIME file type:
FileExtMismatchSettingsPanel.newMimePrompt.title=New MIME
FileExtMismatchSettingsPanel.newMimePrompt.emptyMime.message=MIME type text is empty!
FileExtMismatchSettingsPanel.newMimePrompt.emptyMime.message=MIME type text is empty\!
FileExtMismatchSettingsPanel.newMimePrompt.emptyMime.title=Empty type
FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotSupported.message=MIME type not supported!
FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotSupported.message=MIME type not supported\!
FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotSupported.title=Type not supported
FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeExists.message=MIME type already exists!
FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeExists.message=MIME type already exists\!
FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeExists.title=Type already exists
FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotDetectable.message=MIME type is not detectable by this module.
FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotDetectable.title=Type not detectable
FileExtMismatchSettingsPanel.removeTypeButton.noneSelected.message=No MIME type selected!
FileExtMismatchSettingsPanel.removeTypeButton.noneSelected.message=No MIME type selected\!
FileExtMismatchSettingsPanel.removeTypeButton.noneSelected.title=No type selected
FileExtMismatchSettingsPanel.newExtPrompt.message=Add an allowed extension:
FileExtMismatchSettingsPanel.newExtPrompt.title=New allowed extension
FileExtMismatchSettingsPanel.newExtPrompt.empty.message=Extension text is empty!
FileExtMismatchSettingsPanel.newExtPrompt.empty.message=Extension text is empty\!
FileExtMismatchSettingsPanel.newExtPrompt.empty.title=Extension text empty
FileExtMismatchSettingsPanel.newExtPrompt.noMimeType.message=No MIME type selected!
FileExtMismatchSettingsPanel.newExtPrompt.noMimeType.message=No MIME type selected\!
FileExtMismatchSettingsPanel.newExtPrompt.noMimeType.title=No MIME type selected
FileExtMismatchSettingsPanel.newExtPrompt.extExists.message=Extension already exists!
FileExtMismatchSettingsPanel.newExtPrompt.extExists.message=Extension already exists\!
FileExtMismatchSettingsPanel.newExtPrompt.extExists.title=Extension already exists
FileExtMismatchSettingsPanel.removeExtButton.noneSelected.message=No extension selected!
FileExtMismatchSettingsPanel.removeExtButton.noneSelected.message=No extension selected\!
FileExtMismatchSettingsPanel.removeExtButton.noneSelected.title=No extension selected
FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.message=No MIME type selected!
FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.message=No MIME type selected\!
FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.title=No MIME type selected
FileExtMismatchSettingsPanel.removeTypeButton.toolTipText=
FileExtMismatchModuleSettingsPanel.checkAllRadioButton.text=Check all file types

View File

@ -49,7 +49,10 @@ ImportCentralRepoDbProgressDialog.errorParsingFile.message=Error parsing hash se
ImportCentralRepoDbProgressDialog.linesProcessed.message=\ hashes processed
ImportCentralRepoDbProgressDialog.title.text=Central Repository Import Progress
OpenIDE-Module-Display-Category=Ingest Module
OpenIDE-Module-Long-Description=Hash Set ingest module. \n\nThe ingest module analyzes files in the disk image and marks them as "known" (based on NSRL hashset lookup for "known" files) and "bad / interesting" (based on one or more hash sets supplied by the user).\n\nThe module also contains additional non-ingest tools that are integrated in the GUI, such as file lookup by hash and hash set configuration.
OpenIDE-Module-Long-Description=\
Hash Set ingest module. \n\n\
The ingest module analyzes files in the disk image and marks them as "known" (based on NSRL hashset lookup for "known" files) and "bad / interesting" (based on one or more hash sets supplied by the user).\n\n\
The module also contains additional non-ingest tools that are integrated in the GUI, such as file lookup by hash and hash set configuration.
OpenIDE-Module-Name=HashDatabases
OptionsCategory_Name_HashDatabase=Hash Sets
OptionsCategory_Keywords_HashDatabase=Hash Sets
@ -178,7 +181,10 @@ HashDbSearchThread.name.searching=Searching
HashDbSearchThread.noMoreFilesWithMD5Msg=No other files with the same MD5 hash were found.
ModalNoButtons.indexingDbsTitle=Indexing hash sets
ModalNoButtons.indexingDbTitle=Indexing hash set
ModalNoButtons.exitHashDbIndexingMsg=You are about to exit out of indexing your hash sets. \nThe generated index will be left unusable. If you choose to continue,\nplease delete the corresponding -md5.idx file in the hash folder.\nExit indexing?
ModalNoButtons.exitHashDbIndexingMsg=You are about to exit out of indexing your hash sets. \n\
The generated index will be left unusable. If you choose to continue,\n\
please delete the corresponding -md5.idx file in the hash folder.\n\
Exit indexing?
ModalNoButtons.dlgTitle.unfinishedIndexing=Unfinished Indexing
ModalNoButtons.indexThis.currentlyIndexing1Db=Currently indexing 1 hash set
ModalNoButtons.indexThese.currentlyIndexing1OfNDbs=Currently indexing 1 of {0}

View File

@ -83,8 +83,8 @@ FilesSetRulePanel.nameTextField.text=
FilesSetRulePanel.ruleNameLabel.text=Rule Name (Optional):
FilesSetRulePanel.messages.emptyNameCondition=You must specify a name pattern for this rule.
FilesSetRulePanel.messages.invalidNameRegex=The name regular expression is not valid:\n\n{0}
FilesSetRulePanel.messages.invalidCharInName=The name cannot contain \\, /, :, *, ?, ", <, or > unless it is a regular expression.
FilesSetRulePanel.messages.invalidCharInPath=The path cannot contain \\, :, *, ?, ", <, or > unless it is a regular expression.
FilesSetRulePanel.messages.invalidCharInName=The name cannot contain \\, /, :, *, ?, \", <, or > unless it is a regular expression.
FilesSetRulePanel.messages.invalidCharInPath=The path cannot contain \\, :, *, ?, \", <, or > unless it is a regular expression.
FilesSetRulePanel.messages.invalidPathRegex=The path regular expression is not valid:\n\n{0}
FilesSetDefsPanel.doFileSetsDialog.duplicateRuleSet.text=Rule set with name {0} already exists.
FilesSetRulePanel.pathSeparatorInfoLabel.text=Folder must be in parent path. Use '/' to give consecutive names

View File

@ -21,7 +21,7 @@ PhotoRecIngestModule.complete.totalParsetime=Total Parsing Time:
PhotoRecIngestModule.complete.photoRecResults=PhotoRec Results
PhotoRecIngestModule.NotEnoughDiskSpace.detail.msg=PhotoRec error processing {0} with {1} Not enough space on primary disk to save unallocated space.
PhotoRecIngestModule.cancelledByUser=PhotoRec cancelled by user.
PhotoRecIngestModule.error.exitValue=PhotoRec carver returned error exit value = {0} when scanning {1}
PhotoRecIngestModule.error.exitValue=PhotoRec carver returned error exit value \= {0} when scanning {1}
PhotoRecIngestModule.error.msg=Error processing {0} with PhotoRec carver.
PhotoRecIngestModule.complete.numberOfErrors=Number of Errors while Carving:
PhotoRecCarverIngestJobSettingsPanel.detectionSettingsLabel.text=PhotoRec Settings

View File

@ -5,8 +5,8 @@ ReportHTML.getName.text=HTML Report
ReportHTML.getDesc.text=A report about results and tagged items in HTML format.
ReportHTML.writeIndex.title=for case {0}
ReportHTML.writeIndex.noFrames.msg=Your browser is not compatible with our frame setup.
ReportHTML.writeIndex.noFrames.seeNav=Please see <a href="content\nav.html">the navigation page</a> for artifact links,
ReportHTML.writeIndex.seeSum=and <a href="contentsummary.html">the summary page</a> for a case summary.
ReportHTML.writeIndex.noFrames.seeNav=Please see <a href\="content\nav.html">the navigation page</a> for artifact links,
ReportHTML.writeIndex.seeSum=and <a href\="content\summary.html">the summary page</a> for a case summary.
ReportHTML.writeNav.title=Report Navigation
ReportHTML.writeNav.h1=Report Navigation
ReportHTML.writeNav.summary=Case Summary
@ -16,7 +16,7 @@ ReportHTML.writeSum.caseNumber=Case Number:
ReportHTML.writeSum.caseNumImages=Number of Images:
ReportHTML.writeSum.examiner=Examiner:
ReportHTML.writeSum.title=Case Summary
ReportHTML.writeSum.warningMsg=<span>Warning, this report was run before ingest services completed!</span>
ReportHTML.writeSum.warningMsg=<span>Warning, this report was run before ingest services completed\!</span>
#
# autopsy/test/scripts/regression.py._html_report_diff() uses reportGenOn.text, caseName, caseNum,
# examiner as a regex signature to skip report.html and summary.html

View File

@ -0,0 +1,48 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019-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.textsummarizer;
import java.io.IOException;
import org.sleuthkit.datamodel.AbstractFile;
/**
* Interface for implementation of summarizers for documents.
*/
public interface TextSummarizer {
/**
* Get the name of the TextSummarizer for identification purposes.
*
* @return The name of the TextSummarizer.
*/
String getName();
/**
* Summarize the provided abstract file into a summary with a size no
* greater than the size specified.
*
* @param file The AbstractFile to summarize.
* @param summarySize The size of the summary to create.
*
* @return The summary as a string.
*
* @throws IOException
*/
String summarize(AbstractFile file, int summarySize) throws IOException;
}

View File

@ -2,7 +2,7 @@
*
* Autopsy Forensic Browser
*
* Copyright 2018-2019 Basis Technology Corp.
* Copyright 2018-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -62,6 +62,7 @@ import org.sleuthkit.autopsy.modules.photoreccarver.PhotoRecCarverIngestModuleFa
import org.sleuthkit.autopsy.modules.vmextractor.VMExtractorIngestModuleFactory;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
import org.sleuthkit.autopsy.centralrepository.datamodel.RdbmsCentralRepoFactory;
/**
* Utilities for testing intercase correlation feature.
@ -220,7 +221,7 @@ class InterCaseTestUtils {
this.kitchenShink = new IngestJobSettings(InterCaseTestUtils.class.getCanonicalName(), IngestType.ALL_MODULES, kitchenSink);
try {
Collection<CorrelationAttributeInstance.Type> types = CorrelationAttributeInstance.getDefaultCorrelationTypes();
Collection<CorrelationAttributeInstance.Type> types = CentralRepository.getInstance().getCorrelationTypes();
//TODO use ids instead of strings
FILE_TYPE = types.stream().filter(type -> type.getDisplayName().equals("Files")).findAny().get();
@ -248,7 +249,7 @@ class InterCaseTestUtils {
CentralRepository.getInstance().shutdownConnections();
}
FileUtils.deleteDirectory(CENTRAL_REPO_DIRECTORY_PATH.toFile());
} catch (IOException | CentralRepoExceptionex) {
} catch (IOException | CentralRepoException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex.getMessage());
}
@ -297,8 +298,10 @@ class InterCaseTestUtils {
crSettings.createDbDirectory();
}
crSettings.initializeDatabaseSchema();
crSettings.insertDefaultDatabaseContent();
RdbmsCentralRepoFactory centralRepoSchemaFactory = new RdbmsCentralRepoFactory(CentralRepoPlatforms.SQLITE, crSettings);
centralRepoSchemaFactory.initializeDatabaseSchema();
centralRepoSchemaFactory.insertDefaultDatabaseContent();
crSettings.saveSettings();
CentralRepoPlatforms.setSelectedPlatform(CentralRepoPlatforms.SQLITE.name());
CentralRepoPlatforms.saveSelectedPlatform();

View File

@ -1,7 +1,6 @@
cannotBuildXmlParser=Unable to build XML parser:
cannotLoadSEUQA=Unable to load Search Engine URL Query Analyzer settings file, SEUQAMappings.xml:
cannotParseXml=Unable to parse XML file:
Chrome.getBookmark.errMsg.errAnalyzeFile={0}: Error while trying to analyze file: {1}
ChromeCacheExtract_adding_artifacts_msg=Chrome Cache: Adding %d artifacts for analysis.
ChromeCacheExtract_adding_extracted_files_msg=Chrome Cache: Adding %d extracted files for analysis.
ChromeCacheExtract_loading_files_msg=Chrome Cache: Loading files from %s.
@ -14,9 +13,9 @@ ChromeCacheExtractor.progressMsg={0}: Extracting cache entry {1} of {2} entries
DataSourceUsage_AndroidMedia=Android Media Card
DataSourceUsage_DJU_Drone_DAT=DJI Internal SD Card
DataSourceUsage_FlashDrive=Flash Drive
# {0} - OS name
DataSourceUsageAnalyzer.customVolume.label=OS Drive ({0})
DataSourceUsageAnalyzer.parentModuleName=Recent Activity
Extract.dbConn.errMsg.failedToQueryDb={0}: Failed to query database.
Extract.indexError.message=Failed to index artifact for keyword search.
Extract.noOpenCase.errMsg=No open case available.
ExtractEdge_getHistory_containerFileNotFound=Error while trying to analyze Edge history
@ -25,11 +24,6 @@ ExtractEdge_process_errMsg_errGettingWebCacheFiles=Error trying to retrieving Ed
ExtractEdge_process_errMsg_spartanFail=Failure processing Microsoft Edge spartan.edb file
ExtractEdge_process_errMsg_unableFindESEViewer=Unable to find ESEDatabaseViewer
ExtractEdge_process_errMsg_webcacheFail=Failure processing Microsoft Edge WebCacheV01.dat file
ExtractIE.getBookmark.ere.noSpace=RecentActivity
ExtractIE.getBookmark.errMsg.errPostingBookmarks=Error posting Internet Explorer Bookmark artifacts.
ExtractIE.getCookie.errMsg.errPostingCookies=Error posting Internet Explorer Cookie artifacts.
ExtractIE.getHistory.errMsg.errPostingHistory=Error posting Internet Explorer History artifacts.
Extractor.errPostingArtifacts=Error posting {0} artifacts to the blackboard.
ExtractOs.androidOs.label=Android
ExtractOs.androidVolume.label=OS Drive (Android)
ExtractOs.debianLinuxOs.label=Linux (Debian)
@ -96,7 +90,7 @@ Chrome.getLogin.errMsg.errAnalyzingFiles={0}: Error while trying to analyze file
Chrome.getAutofill.errMsg.errGettingFiles=Error when trying to get Chrome Web Data files.
Chrome.getAutofill.errMsg.errAnalyzingFiles={0}: Error while trying to analyze file:{1}
ExtractIE.moduleName.text=Internet Explorer
ExtractIE.getBookmark.errMsg.errGettingBookmarks=Error getting Internet Explorer Bookmarks.
ExtractIE.getBookmark.errMsg.errGettingBookmarks={0}: Error getting Internet Explorer Bookmarks.
ExtractIE.parentModuleName.noSpace=RecentActivity
ExtractIE.parentModuleName=Recent Activity
ExtractIE.getURLFromIEBmkFile.errMsg={0}: Error parsing IE bookmark File {1}
@ -198,6 +192,7 @@ RecentDocumentsByLnk.parentModuleName.noSpace=RecentActivity
RecentDocumentsByLnk.parentModuleName=Recent Activity
RegRipperFullNotFound=Full version RegRipper executable not found.
RegRipperNotFound=Autopsy RegRipper executable not found.
# {0} - file name
SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}.
SearchEngineURLQueryAnalyzer.moduleName.text=Search Engine
SearchEngineURLQueryAnalyzer.engineName.none=NONE

View File

@ -1,5 +1,5 @@
#Updated by build script
#Tue, 12 Nov 2019 17:21:46 -0500
#Thu, 27 Feb 2020 08:01:10 -0500
LBL_splash_window_title=Starting Autopsy
SPLASH_HEIGHT=314
SPLASH_WIDTH=538
@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18
SplashRunningTextColor=0x0
SplashRunningTextFontSize=19
currentVersion=Autopsy 4.13.0
currentVersion=Autopsy 4.14.0

View File

@ -1,4 +1,4 @@
#Updated by build script
#Tue, 12 Nov 2019 17:21:46 -0500
CTL_MainWindow_Title=Autopsy 4.13.0
CTL_MainWindow_Title_No_Project=Autopsy 4.13.0
#Thu, 27 Feb 2020 08:01:10 -0500
CTL_MainWindow_Title=Autopsy 4.14.0
CTL_MainWindow_Title_No_Project=Autopsy 4.14.0