6225 resolve merge conflicts

This commit is contained in:
William Schaefer 2020-04-12 23:04:33 -04:00
commit c8eef33009
50 changed files with 727 additions and 300 deletions

View File

@ -2,7 +2,7 @@ Manifest-Version: 1.0
OpenIDE-Module: org.sleuthkit.autopsy.core/10
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/core/Bundle.properties
OpenIDE-Module-Layer: org/sleuthkit/autopsy/core/layer.xml
OpenIDE-Module-Implementation-Version: 30
OpenIDE-Module-Implementation-Version: 31
OpenIDE-Module-Requires: org.openide.windows.WindowManager
AutoUpdate-Show-In-Client: true
AutoUpdate-Essential-Module: true

View File

@ -126,5 +126,5 @@ nbm.homepage=http://www.sleuthkit.org/
nbm.module.author=Brian Carrier
nbm.needs.restart=true
source.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0-sources.jar
spec.version.base=10.18
spec.version.base=10.19

View File

@ -251,7 +251,7 @@
<compile-dependency/>
<run-dependency>
<release-version>3</release-version>
<specification-version>1.3</specification-version>
<specification-version>1.4</specification-version>
</run-dependency>
</dependency>
</module-dependencies>

View File

@ -50,7 +50,7 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.casemodule.CaseCloseAction")
@ActionRegistration(displayName = "#CTL_CaseCloseAct", lazy = false)
@ActionReferences(value = {
@ActionReference(path = "Toolbars/Case", position = 106)})
@ActionReference(path = "Toolbars/Case", position = 107)})
public final class CaseCloseAction extends CallableSystemAction implements Presenter.Toolbar {
private static final long serialVersionUID = 1L;

View File

@ -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.makeCorrAttrsFromArtifact(bbArtifact));
ret.addAll(CorrelationAttributeUtil.makeCorrAttrsForCorrelation(bbArtifact));
}
// we can correlate based on the MD5 if it is enabled

View File

@ -19,7 +19,9 @@
package org.sleuthkit.autopsy.centralrepository.datamodel;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
@ -32,6 +34,7 @@ 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.CommunicationsUtils;
import org.sleuthkit.datamodel.HashUtility;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
@ -59,25 +62,60 @@ public class CorrelationAttributeUtil {
return Bundle.CorrelationAttributeUtil_emailaddresses_text();
}
// Defines which artifact types act as the sources for CR data.
// Most notably, does not include KEYWORD HIT, CALLLOGS, MESSAGES, CONTACTS
// TSK_INTERESTING_ARTIFACT_HIT (See JIRA-6129 for more details on the
// interesting artifact hit).
// IMPORTANT: This set should be updated for new artifacts types that need to
// be inserted into the CR.
private static final Set<Integer> SOURCE_TYPES_FOR_CR_INSERT = new HashSet<Integer>() {{
add(ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID());
add(ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID());
add(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID());
add(ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID());
add(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID());
add(ARTIFACT_TYPE.TSK_WIFI_NETWORK.getTypeID());
add(ARTIFACT_TYPE.TSK_WIFI_NETWORK_ADAPTER.getTypeID());
add(ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING.getTypeID());
add(ARTIFACT_TYPE.TSK_BLUETOOTH_ADAPTER.getTypeID());
add(ARTIFACT_TYPE.TSK_DEVICE_INFO.getTypeID());
add(ARTIFACT_TYPE.TSK_SIM_ATTACHED.getTypeID());
add(ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS.getTypeID());
add(ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID());
}};
/**
* Makes zero to many correlation attribute instances from the attributes of
* an artifact.
*
* IMPORTANT: The correlation attribute instances are NOT added to the
* central repository by this method.
*
* @param artifact An artifact.
* artifacts that have correlatable data. The intention of this method is to
* use the results to save to the CR, not to correlate with them. If you
* want to correlate, please use makeCorrAttrsForCorrelation. An artifact that can
* have correlatable data != An artifact that should be the source of data
* in the CR, so results may be un-necessarily incomplete.
*
* @param artifact An artifact.
*
* @return A list, possibly empty, of correlation attribute instances for
* the artifact.
* the artifact.
*/
public static List<CorrelationAttributeInstance> makeCorrAttrsFromArtifact(BlackboardArtifact artifact) {
return makeCorrAttrsFromArtifact(artifact, true );
public static List<CorrelationAttributeInstance> makeCorrAttrsToSave(BlackboardArtifact artifact) {
if(SOURCE_TYPES_FOR_CR_INSERT.contains(artifact.getArtifactTypeID())) {
// Restrict the correlation attributes to use for saving.
// The artifacts which are suitable for saving are a subset of the
// artifacts that are suitable for correlating.
return makeCorrAttrsForCorrelation(artifact);
}
// Return an empty collection.
return new ArrayList<>();
}
/**
* Makes zero to many correlation attribute instances from the attributes of
* an artifact.
* artifacts that have correlatable data. The intention of this method is to
* use the results to correlate with, not to save. If you
* want to save, please use makeCorrAttrsToSave. An artifact that can
* have correlatable data != An artifact that should be the source of data
* in the CR, so results may be too lenient.
*
* IMPORTANT: The correlation attribute instances are NOT added to the
* central repository by this method.
@ -91,26 +129,22 @@ public class CorrelationAttributeUtil {
* checking is easy to forget, while catching exceptions is enforced.
*
* @param artifact An artifact.
* @param resolveSourceArtifact A flag to indicate whether to resolve the
* source artifact, if the given artifact is
* of type TSK_INTERESTING_ARTIFACT_HIT.
*
* @return A list, possibly empty, of correlation attribute instances for
* the artifact.
*/
public static List<CorrelationAttributeInstance> makeCorrAttrsFromArtifact(BlackboardArtifact artifact, boolean resolveSourceArtifact) {
public static List<CorrelationAttributeInstance> makeCorrAttrsForCorrelation(BlackboardArtifact artifact) {
List<CorrelationAttributeInstance> correlationAttrs = new ArrayList<>();
// If the artifact is of type TSK_INTERESTING_ARTIFACT_HIT, and the caller
// has not indicated to resolve the source artifact, then return an empty list.
if ((artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) && (resolveSourceArtifact == false) ) {
return correlationAttrs;
}
try {
BlackboardArtifact sourceArtifact = getCorrAttrSourceArtifact(artifact);
if (sourceArtifact != null) {
int artifactTypeID = sourceArtifact.getArtifactTypeID();
if (artifactTypeID == ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID()
if (artifactTypeID == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
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()) {
@ -143,6 +177,11 @@ public class CorrelationAttributeUtil {
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) {
makeCorrAttrFromAcctArtifact(correlationAttrs, sourceArtifact);
} else if (artifactTypeID == ARTIFACT_TYPE.TSK_CONTACT.getTypeID()
|| artifactTypeID == ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()
|| artifactTypeID == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) {
makeCorrAttrsFromCommunicationArtifacts(correlationAttrs, sourceArtifact);
}
}
} catch (CentralRepoException ex) {
@ -158,6 +197,47 @@ public class CorrelationAttributeUtil {
return correlationAttrs;
}
/**
* Makes a correlation attribute instance from a phone number attribute of an
* artifact.
*
* @param corrAttrInstances Correlation attributes will be added to this.
* @param artifact An artifact with a phone number 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 void makeCorrAttrsFromCommunicationArtifacts(List<CorrelationAttributeInstance> corrAttrInstances, 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) {
if(CommunicationsUtils.isValidPhoneNumber(value)) {
value = CommunicationsUtils.normalizePhoneNum(value);
corrAttr = makeCorrAttr(artifact, CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.PHONE_TYPE_ID), value);
if(corrAttr != null) {
corrAttrInstances.add(corrAttr);
}
}
}
}
/**
* Gets the associated artifact of a "meta-artifact" such as an interesting
* artifact hit artifact.
@ -186,33 +266,29 @@ public class CorrelationAttributeUtil {
/**
* Makes a correlation attribute instance for an account artifact.
*
*
* Also creates an account in the CR DB if it doesn't exist.
*
* IMPORTANT: The correlation attribute instance is NOT added to the central
* repository by this method.
*
* 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 makeCorrAttrFromAcctArtifact(List<CorrelationAttributeInstance> corrAttrInstances, BlackboardArtifact acctArtifact) throws TskCoreException, CentralRepoException {
// Get the account type from the artifact
BlackboardAttribute accountTypeAttribute = acctArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE));
String accountTypeStr = accountTypeAttribute.getValueString();
// @@TODO Vik-6136: CR currently does not know of custom account types.
// Ensure there is a predefined account type for this account.
Account.Type predefinedAccountType = Account.Type.PREDEFINED_ACCOUNT_TYPES.stream().filter(type -> type.getTypeName().equalsIgnoreCase(accountTypeStr)).findAny().orElse(null);
// do not create any correlation attribute instance for a Device account
if (Account.Type.DEVICE.getTypeName().equalsIgnoreCase(accountTypeStr) == false) {
if (Account.Type.DEVICE.getTypeName().equalsIgnoreCase(accountTypeStr) == false && predefinedAccountType != null) {
// Get the corresponding CentralRepoAccountType from the database.
CentralRepoAccountType crAccountType = CentralRepository.getInstance().getAccountTypeByName(accountTypeStr);
@ -441,10 +517,10 @@ public class CorrelationAttributeUtil {
file.getId());
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Error querying case database (%s)", file), ex); // NON-NLS
logger.log(Level.SEVERE, String.format("Error 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
logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", file), ex); // NON-NLS
return null;
} catch (CorrelationAttributeNormalizationException ex) {
logger.log(Level.WARNING, String.format("Error creating correlation attribute instance (%s)", file), ex); // NON-NLS

View File

@ -296,7 +296,7 @@ final class CaseEventListener implements PropertyChangeListener {
return;
}
List<CorrelationAttributeInstance> convertedArtifacts = CorrelationAttributeUtil.makeCorrAttrsFromArtifact(bbArtifact);
List<CorrelationAttributeInstance> convertedArtifacts = CorrelationAttributeUtil.makeCorrAttrsForCorrelation(bbArtifact);
for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) {
eamArtifact.setComment(comment);
try {
@ -369,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.makeCorrAttrsFromArtifact(bbTag.getArtifact());
List<CorrelationAttributeInstance> convertedArtifacts = CorrelationAttributeUtil.makeCorrAttrsForCorrelation(bbTag.getArtifact());
for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) {
CentralRepository.getInstance().setAttributeInstanceKnownStatus(eamArtifact, tagName.getKnownStatus());
}

View File

@ -455,11 +455,8 @@ public class IngestEventsListener {
List<CorrelationAttributeInstance> eamArtifacts = new ArrayList<>();
for (BlackboardArtifact bbArtifact : bbArtifacts) {
// If the incoming artifact is of type TSK_INTERESTING_ARTIFACT_HIT,
// do not resolve to the source artifact, as correlation attributes
// for the source artifact would have already been created,
// when the event for that source artifact was received.
List<CorrelationAttributeInstance> convertedArtifacts = CorrelationAttributeUtil.makeCorrAttrsFromArtifact(bbArtifact, false);
// makeCorrAttrToSave will filter out artifacts which should not be sources of CR data.
List<CorrelationAttributeInstance> convertedArtifacts = CorrelationAttributeUtil.makeCorrAttrsToSave(bbArtifact);
for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) {
try {
// Only do something with this artifact if it's unique within the job

View File

@ -84,3 +84,6 @@ ManageCasesDialog.closeButton.text=Close
ManageCasesDialog.notesLabel.text=Notes:
ManageCasesDialog.dataSourcesLabel.text=Data Sources:
ManageCasesDialog.caseInfoLabel.text=Case Info:
GlobalSettingsPanel.bnTestConfigure.text=Test
GlobalSettingsPanel.testStatusLabel.toolTipText=
GlobalSettingsPanel.testStatusLabel.text=

View File

@ -12,15 +12,15 @@ EamDbSettingsDialog.fcDatabasePath.title=Select location for central_repository.
EamDbSettingsDialog.lbDatabaseType.text=Database Type :
EamDbSettingsDialog.lbSingleUserSqLite.text=SQLite should only be used by one examiner at a time.
EamDbSettingsDialog.okButton.connectionErrorMsg.text=Failed to connect to central repository database.
EamDbSettingsDialog.okButton.corruptDatabaseExists.message=Database exists but is not the right format. Manually delete it or choose a different path (if applicable).
EamDbSettingsDialog.okButton.corruptDatabaseExists.title=Error Loading Database
EamDbSettingsDialog.okButton.createDbDialog.message=Database does not exist, would you like to create it?
EamDbSettingsDialog.okButton.createDbDialog.title=Database Does Not Exist
EamDbSettingsDialog.okButton.createDbError.title=Unable to Create Database
EamDbSettingsDialog.okButton.createPostgresDbError.message=Unable to create Postgres Database, please ensure address, port, and login credentials are correct for Postgres server and try again.
EamDbSettingsDialog.okButton.createSQLiteDbError.message=Unable to create SQLite Database, please ensure location exists and you have write permissions and try again.
EamDbSettingsDialog.okButton.databaseConnectionFailed.message=Unable to connect to database. Please check your settings and try again.
EamDbSettingsDialog.okButton.databaseConnectionFailed.title=Database Connection Failed
EamDbSettingsDialog.okButton.corruptDatabaseExists.message=Central Repository Database exists but is not the right format. Manually delete it or choose a different path (if applicable).
EamDbSettingsDialog.okButton.corruptDatabaseExists.title=Error Loading Central Repository Database
EamDbSettingsDialog.okButton.createDbDialog.message=Central Repository Database does not exist, would you like to create it?
EamDbSettingsDialog.okButton.createDbDialog.title=Central Repository Database Does Not Exist
EamDbSettingsDialog.okButton.createDbError.title=Unable to Create Central Repository Database
EamDbSettingsDialog.okButton.createPostgresDbError.message=Unable to create Postgres Central Repository Database, please ensure address, port, and login credentials are correct for Postgres server and try again.
EamDbSettingsDialog.okButton.createSQLiteDbError.message=Unable to create SQLite Central Repository Database, please ensure location exists and you have write permissions and try again.
EamDbSettingsDialog.okButton.databaseConnectionFailed.message=Unable to connect to Central Repository Database. Please check your settings and try again.
EamDbSettingsDialog.okButton.databaseConnectionFailed.title=Central Repository Database Connection Failed
EamDbSettingsDialog.okButton.errorMsg.text=Please restart Autopsy to begin using the new database platform.
EamDbSettingsDialog.okButton.errorTitle.text=Restart Required.
EamDbSettingsDialog.textPrompt.dbName=Database Name
@ -33,12 +33,16 @@ EamDbSettingsDialog.validation.finished=Click OK to save your database settings
EamDbSettingsDialog.validation.incompleteFields=Fill in all values for the selected database.
EamOptionsController.moduleErr=Error processing value changes.
EamOptionsController.moduleErr.msg=Value change processing failed.
GlobalSettingsPanel.askForCentralRepoDbChoice.customPostgrestChoice.text=Configure PostgreSQL
GlobalSettingsPanel.askForCentralRepoDbChoice.disableChoice.text=Disable Central Repository
GlobalSettingsPanel.askForCentralRepoDbChoice.sqliteChoice.text=Use SQLite
GlobalSettingsPanel.onMultiUserChange.disabledMu.description=The Central Repository will be reconfigured to use a local SQLite database.
GlobalSettingsPanel.onMultiUserChange.disabledMu.description2=Press Configure PostgreSQL to change to a PostgreSQL database.
GlobalSettingsPanel.onMultiUserChange.disabledMu.title=Central Repository Change Necessary
GlobalSettingsPanel.onMultiUserChange.enable.description=Do you want to update the Central Repository to use this PostgreSQL database?
GlobalSettingsPanel.onMultiUserChange.enable.description2=The Central Repository stores hash values and accounts from past cases.
GlobalSettingsPanel.onMultiUserChange.enable.title=Use with Central Repository?
GlobalSettingsPanel.testCurrentConfiguration.dbDoesNotExist.message=Database does not exist.
GlobalSettingsPanel.validationErrMsg.ingestRunning=You cannot change settings while ingest is running.
GlobalSettingsPanel.validationerrMsg.mustConfigure=Configure the database to enable this module.
ManageCasesDialog.title.text=Manage Cases
@ -147,3 +151,6 @@ ManageCasesDialog.closeButton.text=Close
ManageCasesDialog.notesLabel.text=Notes:
ManageCasesDialog.dataSourcesLabel.text=Data Sources:
ManageCasesDialog.caseInfoLabel.text=Case Info:
GlobalSettingsPanel.bnTestConfigure.text=Test
GlobalSettingsPanel.testStatusLabel.toolTipText=
GlobalSettingsPanel.testStatusLabel.text=

View File

@ -143,3 +143,5 @@ ManageCasesDialog.closeButton.text=\u9589\u3058\u308b
ManageCasesDialog.notesLabel.text=\u5099\u8003:
ManageCasesDialog.dataSourcesLabel.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9:
ManageCasesDialog.caseInfoLabel.text=\u30b1\u30fc\u30b9\u60c5\u5831:
GlobalSettingsPanel.bnTestConfigure.text=\u69cb\u6210
GlobalSettingsPanel.testStatusLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5b9f\u884c\u4e2d\u306f\u30bb\u30f3\u30c8\u30e9\u30eb\u30fb\u30ec\u30dd\u30b8\u30c8\u30ea\u30fc\u8a2d\u5b9a\u3092\u5909\u66f4\u3067\u304d\u307e\u305b\u3093!

View File

@ -87,7 +87,6 @@ public class EamDbSettingsDialog extends JDialog {
private final Collection<JTextField> textBoxes;
private final TextBoxChangedListener textBoxChangedListener;
private final CentralRepoDbManager manager = new CentralRepoDbManager();
private final boolean isMultiUserSelectable = CentralRepoDbManager.isPostgresMultiuserAllowed();
private final DbChoiceRenderer DB_CHOICE_RENDERER = new DbChoiceRenderer();
public EamDbSettingsDialog() {
@ -95,7 +94,7 @@ public class EamDbSettingsDialog extends JDialog {
}
private boolean isDbChoiceSelectable(CentralRepoDbChoice item) {
return (item != CentralRepoDbChoice.POSTGRESQL_MULTIUSER || isMultiUserSelectable);
return (item != CentralRepoDbChoice.POSTGRESQL_MULTIUSER || manager.isPostgresMultiuserAllowed());
}
@ -159,15 +158,15 @@ public class EamDbSettingsDialog extends JDialog {
* @param dialog If non-null value, validates settings and updates 'okay' button enabled state.
* @return Whether or not the ultimate status after prompts is okay to continue.
*/
@NbBundle.Messages({"EamDbSettingsDialog.okButton.corruptDatabaseExists.title=Error Loading Database",
"EamDbSettingsDialog.okButton.corruptDatabaseExists.message=Database exists but is not the right format. Manually delete it or choose a different path (if applicable).",
"EamDbSettingsDialog.okButton.createDbDialog.title=Database Does Not Exist",
"EamDbSettingsDialog.okButton.createDbDialog.message=Database does not exist, would you like to create it?",
"EamDbSettingsDialog.okButton.databaseConnectionFailed.title=Database Connection Failed",
"EamDbSettingsDialog.okButton.databaseConnectionFailed.message=Unable to connect to database. Please check your settings and try again.",
"EamDbSettingsDialog.okButton.createSQLiteDbError.message=Unable to create SQLite Database, please ensure location exists and you have write permissions and try again.",
"EamDbSettingsDialog.okButton.createPostgresDbError.message=Unable to create Postgres Database, please ensure address, port, and login credentials are correct for Postgres server and try again.",
"EamDbSettingsDialog.okButton.createDbError.title=Unable to Create Database"})
@NbBundle.Messages({"EamDbSettingsDialog.okButton.corruptDatabaseExists.title=Error Loading Central Repository Database",
"EamDbSettingsDialog.okButton.corruptDatabaseExists.message=Central Repository Database exists but is not the right format. Manually delete it or choose a different path (if applicable).",
"EamDbSettingsDialog.okButton.createDbDialog.title=Central Repository Database Does Not Exist",
"EamDbSettingsDialog.okButton.createDbDialog.message=Central Repository Database does not exist, would you like to create it?",
"EamDbSettingsDialog.okButton.databaseConnectionFailed.title=Central Repository Database Connection Failed",
"EamDbSettingsDialog.okButton.databaseConnectionFailed.message=Unable to connect to Central Repository Database. Please check your settings and try again.",
"EamDbSettingsDialog.okButton.createSQLiteDbError.message=Unable to create SQLite Central Repository Database, please ensure location exists and you have write permissions and try again.",
"EamDbSettingsDialog.okButton.createPostgresDbError.message=Unable to create Postgres Central Repository Database, please ensure address, port, and login credentials are correct for Postgres server and try again.",
"EamDbSettingsDialog.okButton.createDbError.title=Unable to Create Central Repository Database"})
private static boolean promptTestStatusWarnings(CentralRepoDbManager manager, EamDbSettingsDialog dialog) {
if (manager.getStatus() == DatabaseTestResult.CONNECTION_FAILED) {
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
@ -181,31 +180,43 @@ public class EamDbSettingsDialog extends JDialog {
Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_title(),
JOptionPane.WARNING_MESSAGE);
} else if (manager.getStatus() == DatabaseTestResult.DB_DOES_NOT_EXIST) {
//database doesn't exist. do you want to create?
if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(),
Bundle.EamDbSettingsDialog_okButton_createDbDialog_message(),
Bundle.EamDbSettingsDialog_okButton_createDbDialog_title(),
JOptionPane.YES_NO_OPTION)) {
onUserPromptCreateDb(manager, dialog);
}
promptCreateDatabase(manager, dialog);
}
return (manager.getStatus() == DatabaseTestResult.TESTED_OK);
}
/**
* When a new database needs to be created on user selecting cr, this code will be ran when user selects create cr.
* @param manager The manager handling the database creation.
* @param dialog The dialog that prompted database creation.
/**
* This method prompts the user whether or not they would like to create a database in the instance that
* it doesn't exist.
* @param manager The manager to use when setting up the database.
* @param dialog If non-null value, validates settings and updates 'okay'
* button enabled state.
*
* @return Whether or not the ultimate status after prompts is okay.
*/
private static void onUserPromptCreateDb(CentralRepoDbManager manager, EamDbSettingsDialog dialog) {
try {
manager.createDb();
} catch (CentralRepoException e) {
onPromptStatusError(manager);
public static boolean promptCreateDatabase(CentralRepoDbManager manager, EamDbSettingsDialog dialog) {
//database doesn't exist. do you want to create?
if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(),
Bundle.EamDbSettingsDialog_okButton_createDbDialog_message(),
Bundle.EamDbSettingsDialog_okButton_createDbDialog_title(),
JOptionPane.YES_NO_OPTION)) {
try {
manager.createDb();
} catch (CentralRepoException e) {
onPromptStatusError(manager);
return false;
}
if (dialog != null) {
dialog.valid();
}
return true;
}
if (dialog != null)
dialog.valid();
return manager.testStatus() == DatabaseTestResult.TESTED_OK;
}
@ -604,8 +615,8 @@ public class EamDbSettingsDialog extends JDialog {
"EamDbSettingsDialog.okButton.errorMsg.text=Please restart Autopsy to begin using the new database platform.",
"EamDbSettingsDialog.okButton.connectionErrorMsg.text=Failed to connect to central repository database."})
private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed
testStatusAndCreate(this, manager, this);
dispose();
if (testStatusAndCreate(this, manager, this))
dispose();
}//GEN-LAST:event_bnOkActionPerformed
@ -659,6 +670,7 @@ public class EamDbSettingsDialog extends JDialog {
return true;
}
/**
* This method returns if changes to the central repository configuration were
* successfully applied.
@ -887,7 +899,6 @@ public class EamDbSettingsDialog extends JDialog {
@Override
public void changedUpdate(DocumentEvent e) {
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
manager.clearStatus();
updateFullDbPath();
valid();
@ -895,7 +906,6 @@ public class EamDbSettingsDialog extends JDialog {
@Override
public void insertUpdate(DocumentEvent e) {
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
manager.clearStatus();
updateFullDbPath();
valid();
@ -903,7 +913,6 @@ public class EamDbSettingsDialog extends JDialog {
@Override
public void removeUpdate(DocumentEvent e) {
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
manager.clearStatus();
updateFullDbPath();
valid();

View File

@ -61,7 +61,7 @@
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="pnDatabaseConfiguration" alignment="0" max="32767" attributes="0"/>
<Component id="pnCorrelationProperties" alignment="0" pref="1010" max="32767" attributes="0"/>
<Component id="pnCorrelationProperties" alignment="0" pref="1016" max="32767" attributes="0"/>
<Component id="organizationPanel" alignment="1" max="32767" attributes="0"/>
<Component id="casesPanel" alignment="0" max="32767" attributes="0"/>
<Group type="102" attributes="0">
@ -137,10 +137,6 @@
<Group type="102" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="bnDbConfigure" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="lbDbPlatformTypeLabel" max="32767" attributes="0"/>
@ -149,11 +145,22 @@
</Group>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="lbDbNameValue" alignment="0" pref="936" max="32767" attributes="0"/>
<Component id="lbDbNameValue" alignment="0" max="32767" attributes="0"/>
<Component id="lbDbPlatformValue" max="32767" attributes="0"/>
<Component id="lbDbLocationValue" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="lbDbLocationValue" pref="255" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="681" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<Group type="102" attributes="0">
<Component id="bnDbConfigure" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="bnTestConfigure" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="testStatusLabel" min="-2" pref="675" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
@ -177,7 +184,13 @@
<Component id="lbDbLocationValue" min="-2" pref="14" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
<Component id="bnDbConfigure" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="testStatusLabel" alignment="0" max="32767" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="bnDbConfigure" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="bnTestConfigure" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
</Group>
</Group>
@ -221,6 +234,40 @@
</Component>
<Component class="javax.swing.JLabel" name="lbDbLocationValue">
</Component>
<Component class="javax.swing.JButton" name="bnTestConfigure">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.bnTestConfigure.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnTestConfigureActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="testStatusLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="testStatusLabel" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="ff" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.testStatusLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.testStatusLabel.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="[387, 16]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[387, 16]"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="pnCorrelationProperties">
@ -256,7 +303,7 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="correlationPropertiesScrollPane" pref="28" max="32767" attributes="0"/>
<Component id="correlationPropertiesScrollPane" pref="24" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="bnManageTypes" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>

View File

@ -18,7 +18,6 @@
*/
package org.sleuthkit.autopsy.centralrepository.optionspanel;
import java.awt.Cursor;
import java.awt.EventQueue;
import org.sleuthkit.autopsy.coreutils.Logger;
import java.beans.PropertyChangeEvent;
@ -43,7 +42,13 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbUtil;
import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresCentralRepoSettings;
import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteCentralRepoSettings;
import java.awt.Component;
import java.beans.PropertyChangeSupport;
import java.util.logging.Level;
import javax.swing.ImageIcon;
import org.openide.util.ImageUtilities;
import org.sleuthkit.autopsy.centralrepository.datamodel.DatabaseTestResult;
/**
* Main settings panel for the Central Repository
@ -54,25 +59,57 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(GlobalSettingsPanel.class.getName());
private static final Set<IngestManager.IngestJobEvent> INGEST_JOB_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestJobEvent.STARTED, IngestManager.IngestJobEvent.CANCELLED, IngestManager.IngestJobEvent.COMPLETED);
private final IngestJobEventPropertyChangeListener ingestJobEventListener;
// this allows property change events to be fired at a static level but listened to by instances
private static final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(GlobalSettingsPanel.class);
// tracks the last known instance property change listener so that only one GlobalSettingsPanel is listening for events
private static PropertyChangeListener lastRegistered = null;
private final IngestJobEventPropertyChangeListener ingestJobEventListener;
private final ImageIcon goodIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/good.png", false));
private final ImageIcon badIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/bad.png", false));
/**
* Creates new form EamOptionsPanel
*/
public GlobalSettingsPanel() {
ingestJobEventListener = new IngestJobEventPropertyChangeListener();
// listen for change events in currently saved choice
CentralRepoDbManager.addPropertyChangeListener((PropertyChangeEvent evt) -> ingestStateUpdated(Case.isCaseOpen()));
initComponents();
customizeComponents();
setupSettingsChangeListeners();
addIngestJobEventsListener();
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent evt) -> {
//disable when case is open, enable when case is closed
ingestStateUpdated(evt.getNewValue() != null);
});
}
/**
* Sets up this instance's listener for the GlobalSettingsPanel's changes.
*/
private void setupSettingsChangeListeners() {
// listen for change events in currently saved choice
if (lastRegistered != null) {
CentralRepoDbManager.removePropertyChangeListener(lastRegistered);
GlobalSettingsPanel.propertyChangeSupport.removePropertyChangeListener(lastRegistered);
}
lastRegistered = this::onSettingsChange;
CentralRepoDbManager.addPropertyChangeListener(lastRegistered);
GlobalSettingsPanel.propertyChangeSupport.addPropertyChangeListener(lastRegistered);
}
private void onSettingsChange(PropertyChangeEvent evt) {
ingestStateUpdated(Case.isCaseOpen());
clearStatus();
}
private void customizeComponents() {
setName(NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.pnCorrelationProperties.border.title"));
}
@ -121,24 +158,23 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
public static void onMultiUserChange(Component parent, boolean muPreviouslySelected, boolean muCurrentlySelected) {
boolean crEnabled = CentralRepoDbUtil.allowUseOfCentralRepository();
boolean crMultiUser = CentralRepoDbManager.getSavedDbChoice() == CentralRepoDbChoice.POSTGRESQL_MULTIUSER;
boolean crDisabledDueToFailure = CentralRepoDbManager.isDisabledDueToFailure();
if (!muPreviouslySelected && muCurrentlySelected) {
SwingUtilities.invokeLater(() -> {
if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(parent,
"<html><body>"
+ "<div style='width: 400px;'>"
+ "<p>" + NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.onMultiUserChange.enable.description") + "</p>"
+ "<p style='margin-top: 10px'>" + NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.onMultiUserChange.enable.description2") + "</p>"
+ "<p>" + Bundle.GlobalSettingsPanel_onMultiUserChange_enable_description() + "</p>"
+ "<p style='margin-top: 10px'>" + Bundle.GlobalSettingsPanel_onMultiUserChange_enable_description2() + "</p>"
+ "</div>"
+ "</body></html>",
NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.onMultiUserChange.enable.title"),
Bundle.GlobalSettingsPanel_onMultiUserChange_enable_title(),
JOptionPane.YES_NO_OPTION)) {
// setup database for CR
CentralRepoDbUtil.setUseCentralRepo(true);
CentralRepoDbManager.saveDbChoice(CentralRepoDbChoice.POSTGRESQL_MULTIUSER);
handleDbChange(parent);
checkStatusAndCreateDb(parent);
}
});
} // moving from selected to not selected && 'PostgreSQL using multi-user settings' is selected
@ -148,12 +184,23 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
});
} // changing multi-user settings connection && 'PostgreSQL using multi-user settings' is selected &&
// central repo either enabled or was disabled due to error
else if (muPreviouslySelected && muCurrentlySelected && crMultiUser && (crEnabled || crDisabledDueToFailure)) {
// test databse for CR change
CentralRepoDbUtil.setUseCentralRepo(true);
handleDbChange(parent);
else if (muPreviouslySelected && muCurrentlySelected && crEnabled && crMultiUser) {
GlobalSettingsPanel.propertyChangeSupport.firePropertyChange("multiuserSettingsChanged", null, null);
checkStatusAndCreateDb(parent);
}
}
/**
* Checks the status of current connectivity for CR and reports any issues. Will also prompt user to create
* database if cr database is absent.
* @param parent the parent component to which the dialogs will be associated.
*/
private static void checkStatusAndCreateDb(Component parent) {
SwingUtilities.invokeLater(() -> {
EamDbSettingsDialog.testStatusAndCreate(parent, new CentralRepoDbManager());
});
}
/**
* This method is called when a user must select a new database other than
@ -165,28 +212,27 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
@NbBundle.Messages({
"GlobalSettingsPanel.onMultiUserChange.disabledMu.title=Central Repository Change Necessary",
"GlobalSettingsPanel.onMultiUserChange.disabledMu.description=The Central Repository will be reconfigured to use a local SQLite database.",
"GlobalSettingsPanel.onMultiUserChange.disabledMu.description2=Press Configure PostgreSQL to change to a PostgreSQL database."
"GlobalSettingsPanel.onMultiUserChange.disabledMu.description2=Press Configure PostgreSQL to change to a PostgreSQL database.",
"GlobalSettingsPanel.askForCentralRepoDbChoice.sqliteChoice.text=Use SQLite",
"GlobalSettingsPanel.askForCentralRepoDbChoice.customPostgrestChoice.text=Configure PostgreSQL",
"GlobalSettingsPanel.askForCentralRepoDbChoice.disableChoice.text=Disable Central Repository"
})
private static void askForCentralRepoDbChoice(Component parent) {
// disable central repository until user makes choice
CentralRepoDbUtil.setUseCentralRepo(false);
CentralRepoDbManager.saveDbChoice(CentralRepoDbChoice.DISABLED, false);
Object[] options = {
"Use SQLite",
"Configure PostgreSQL",
"Disable Central Repository"
Bundle.GlobalSettingsPanel_askForCentralRepoDbChoice_sqliteChoice_text(),
Bundle.GlobalSettingsPanel_askForCentralRepoDbChoice_customPostgrestChoice_text(),
Bundle.GlobalSettingsPanel_askForCentralRepoDbChoice_disableChoice_text()
};
int result = JOptionPane.showOptionDialog(
parent,
"<html><body>"
+ "<div style='width: 400px;'>"
+ "<p>" + NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.onMultiUserChange.disabledMu.description") + "</p>"
+ "<p style='margin-top: 10px'>" + NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.onMultiUserChange.disabledMu.description2") + "</p>"
+ "<p>" + Bundle.GlobalSettingsPanel_onMultiUserChange_disabledMu_description() + "</p>"
+ "<p style='margin-top: 10px'>" + Bundle.GlobalSettingsPanel_onMultiUserChange_disabledMu_description2() + "</p>"
+ "</div>"
+ "</body></html>",
NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.onMultiUserChange.disabledMu.title"),
Bundle.GlobalSettingsPanel_onMultiUserChange_disabledMu_title(),
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE,
null,
@ -200,13 +246,55 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
invokeCrChoice(parent, CentralRepoDbChoice.POSTGRESQL_CUSTOM);
}
}
@NbBundle.Messages({
"GlobalSettingsPanel.testCurrentConfiguration.dbDoesNotExist.message=Database does not exist.",
})
private boolean testCurrentConfiguration() {
if (CentralRepoDbManager.getSavedDbChoice() == null ||
CentralRepoDbManager.getSavedDbChoice() == CentralRepoDbChoice.DISABLED ||
!CentralRepoDbUtil.allowUseOfCentralRepository())
return false;
CentralRepoDbManager manager = new CentralRepoDbManager();
DatabaseTestResult testResult = manager.testStatus();
// if database doesn't exist, prompt user to create database
if (testResult == DatabaseTestResult.DB_DOES_NOT_EXIST) {
boolean success = EamDbSettingsDialog.promptCreateDatabase(manager, null);
if (success)
testResult = DatabaseTestResult.TESTED_OK;
}
// display to the user the status
switch (testResult) {
case TESTED_OK: return showStatusOkay();
case DB_DOES_NOT_EXIST: return showStatusFail(Bundle.GlobalSettingsPanel_testCurrentConfiguration_dbDoesNotExist_message());
case SCHEMA_INVALID: return showStatusFail(Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_message());
case CONNECTION_FAILED:
default:
return showStatusFail(Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_message());
}
}
private static void handleDbChange(Component parent) {
SwingUtilities.invokeLater(() -> {
if (!EamDbSettingsDialog.testStatusAndCreate(parent, new CentralRepoDbManager())) {
CentralRepoDbManager.disableDueToFailure();
}
});
private boolean showStatusOkay() {
return setStatus(goodIcon, " ");
}
private boolean showStatusFail(String message) {
return setStatus(badIcon, message);
}
private void clearStatus() {
setStatus(null, " ");
}
private boolean setStatus(ImageIcon icon, String text) {
synchronized (testStatusLabel) {
testStatusLabel.setIcon(icon);
testStatusLabel.setText(text);
return true;
}
}
/**
@ -230,6 +318,8 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
lbDbPlatformValue = new javax.swing.JLabel();
lbDbNameValue = new javax.swing.JLabel();
lbDbLocationValue = new javax.swing.JLabel();
bnTestConfigure = new javax.swing.JButton();
testStatusLabel = new javax.swing.JLabel();
pnCorrelationProperties = new javax.swing.JPanel();
bnManageTypes = new javax.swing.JButton();
correlationPropertiesScrollPane = new javax.swing.JScrollPane();
@ -278,6 +368,20 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
}
});
org.openide.awt.Mnemonics.setLocalizedText(bnTestConfigure, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnTestConfigure.text")); // NOI18N
bnTestConfigure.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnTestConfigureActionPerformed(evt);
}
});
testStatusLabel.setFont(testStatusLabel.getFont().deriveFont(testStatusLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
testStatusLabel.setForeground(new java.awt.Color(255, 0, 0));
org.openide.awt.Mnemonics.setLocalizedText(testStatusLabel, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.testStatusLabel.text")); // NOI18N
testStatusLabel.setToolTipText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.testStatusLabel.toolTipText")); // NOI18N
testStatusLabel.setMaximumSize(new java.awt.Dimension(387, 16));
testStatusLabel.setPreferredSize(new java.awt.Dimension(387, 16));
javax.swing.GroupLayout pnDatabaseConfigurationLayout = new javax.swing.GroupLayout(pnDatabaseConfiguration);
pnDatabaseConfiguration.setLayout(pnDatabaseConfigurationLayout);
pnDatabaseConfigurationLayout.setHorizontalGroup(
@ -285,9 +389,6 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
.addGroup(pnDatabaseConfigurationLayout.createSequentialGroup()
.addContainerGap()
.addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnDatabaseConfigurationLayout.createSequentialGroup()
.addComponent(bnDbConfigure)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(pnDatabaseConfigurationLayout.createSequentialGroup()
.addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(lbDbPlatformTypeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
@ -295,9 +396,18 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
.addComponent(lbDbLocationLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lbDbNameValue, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 936, Short.MAX_VALUE)
.addComponent(lbDbNameValue, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lbDbPlatformValue, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lbDbLocationValue, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, pnDatabaseConfigurationLayout.createSequentialGroup()
.addComponent(lbDbLocationValue, javax.swing.GroupLayout.DEFAULT_SIZE, 255, Short.MAX_VALUE)
.addGap(681, 681, 681))))
.addGroup(pnDatabaseConfigurationLayout.createSequentialGroup()
.addComponent(bnDbConfigure)
.addGap(18, 18, 18)
.addComponent(bnTestConfigure)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(testStatusLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 675, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
);
pnDatabaseConfigurationLayout.setVerticalGroup(
pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -315,7 +425,11 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
.addComponent(lbDbLocationLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(lbDbLocationValue, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(bnDbConfigure)
.addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(testStatusLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(pnDatabaseConfigurationLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(bnDbConfigure)
.addComponent(bnTestConfigure)))
.addGap(8, 8, 8))
);
@ -359,7 +473,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
pnCorrelationPropertiesLayout.setVerticalGroup(
pnCorrelationPropertiesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnCorrelationPropertiesLayout.createSequentialGroup()
.addComponent(correlationPropertiesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE)
.addComponent(correlationPropertiesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 24, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnManageTypes)
.addGap(8, 8, 8))
@ -472,7 +586,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(pnCorrelationProperties, javax.swing.GroupLayout.DEFAULT_SIZE, 1010, Short.MAX_VALUE)
.addComponent(pnCorrelationProperties, javax.swing.GroupLayout.DEFAULT_SIZE, 1016, Short.MAX_VALUE)
.addComponent(organizationPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(casesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createSequentialGroup()
@ -532,7 +646,6 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
boolean changed = invokeCrChoice(this, null);
if (changed) {
load(); // reload db settings content and update buttons
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}
}//GEN-LAST:event_bnDbConfigureActionPerformed
@ -549,20 +662,14 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
private void cbUseCentralRepoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbUseCentralRepoActionPerformed
//if saved setting is disabled checkbox should be disabled already
store();
// if moving to using CR, multi-user mode is disabled and selection is multiuser settings, set to disabled
if (cbUseCentralRepo.isSelected()
&& !CentralRepoDbManager.isPostgresMultiuserAllowed()
&& CentralRepoDbManager.getSavedDbChoice() == CentralRepoDbChoice.POSTGRESQL_MULTIUSER) {
CentralRepoDbManager.saveDbChoice(CentralRepoDbChoice.DISABLED);
}
load();
this.ingestStateUpdated(Case.isCaseOpen());
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_cbUseCentralRepoActionPerformed
private void bnTestConfigureActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnTestConfigureActionPerformed
testCurrentConfiguration();
}//GEN-LAST:event_bnTestConfigureActionPerformed
@Override
@Messages({"GlobalSettingsPanel.validationerrMsg.mustConfigure=Configure the database to enable this module."})
public void load() {
@ -691,6 +798,8 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
enableDatabaseConfigureButton(cbUseCentralRepo.isSelected() && !caseIsOpen);
}
/**
* Enable the Configure button
@ -702,8 +811,10 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
private void enableDatabaseConfigureButton(Boolean enable) {
boolean ingestRunning = IngestManager.getInstance().isIngestRunning();
ingestRunningWarningLabel.setVisible(ingestRunning);
pnDatabaseConfiguration.setEnabled(enable && !ingestRunning);
bnDbConfigure.setEnabled(enable && !ingestRunning);
bnTestConfigure.setEnabled(enable && !ingestRunning);
lbDbLocationLabel.setEnabled(enable && !ingestRunning);
lbDbLocationValue.setEnabled(enable && !ingestRunning);
lbDbNameLabel.setEnabled(enable && !ingestRunning);
@ -738,6 +849,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton bnDbConfigure;
private javax.swing.JButton bnManageTypes;
private javax.swing.JButton bnTestConfigure;
private javax.swing.JPanel casesPanel;
private javax.swing.JScrollPane casesScrollPane;
private javax.swing.JTextArea casesTextArea;
@ -762,5 +874,6 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
private javax.swing.JPanel pnDatabaseConfiguration;
private javax.swing.JButton showCasesButton;
private javax.swing.JTextField tbOops;
private javax.swing.JLabel testStatusLabel;
// End of variables declaration//GEN-END:variables
}

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.commonpropertiessearch;
import org.sleuthkit.autopsy.guiutils.DataSourceComboBoxModel;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -119,6 +120,13 @@ public final class InterCasePanel extends javax.swing.JPanel {
this.correlationTypeFilters = new HashMap<>();
try {
List<CorrelationAttributeInstance.Type> types = CentralRepository.getInstance().getDefinedCorrelationTypes();
Collections.sort(types, new Comparator<CorrelationAttributeInstance.Type>() {
//The types should be sorted so that the File type is the first item in the combo box.
@Override
public int compare(CorrelationAttributeInstance.Type type1, CorrelationAttributeInstance.Type type2) {
return Integer.compare(type1.getId(), type2.getId());
}
});
for (CorrelationAttributeInstance.Type type : types) {
correlationTypeFilters.put(type.getDisplayName(), type);
this.correlationTypeComboBox.addItem(type.getDisplayName());
@ -295,7 +303,7 @@ public final class InterCasePanel extends javax.swing.JPanel {
private void correlationTypeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_correlationTypeComboBoxActionPerformed
boolean enableFileTypesFilter = this.correlationTypeComboBox.getSelectedItem().equals("Files");
boolean enableFileTypesFilter = this.correlationTypeComboBox.getSelectedItem().equals("Files");
categoriesLabel.setEnabled(enableFileTypesFilter);
allFileCategoriesRadioButton.setEnabled(enableFileTypesFilter);
selectedFileCategoriesButton.setEnabled(enableFileTypesFilter);
@ -329,8 +337,8 @@ public final class InterCasePanel extends javax.swing.JPanel {
// End of variables declaration//GEN-END:variables
/**
* Get the map of cases which was used to populate the combo box on
* this panel.
* Get the map of cases which was used to populate the combo box on this
* panel.
*
* @return an unmodifiable copy of the map of cases
*/
@ -339,8 +347,8 @@ public final class InterCasePanel extends javax.swing.JPanel {
}
/**
* Set the datamodel for the combo box which displays the cases in
* the central repository
* Set the datamodel for the combo box which displays the cases in the
* central repository
*
* @param dataSourceComboBoxModel the DataSourceComboBoxModel to use
*/

View File

@ -247,6 +247,8 @@ public class MessageViewer extends JPanel implements RelationshipsViewer {
*/
private void showMessagesPane() {
switchCard("messages");
Outline outline = rootTablePane.getOutlineView().getOutline();
outline.clearSelection();
}
/**

View File

@ -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.makeCorrAttrsFromArtifact(artifact));
instancesList.addAll(CorrelationAttributeUtil.makeCorrAttrsForCorrelation(artifact));
}
try {
List<CorrelationAttributeInstance.Type> artifactTypes = CentralRepository.getInstance().getDefinedCorrelationTypes();

View File

@ -77,9 +77,9 @@ DataResultViewerThumbnail.switchPage.done.errMsg=Error making thumbnails: {0}
AboutWindowPanel.actVerboseLogging.text=Activate verbose logging
OptionsCategory_Name_Multi_User_Settings=Multi-User
OptionsCategory_Keywords_Multi_User_Options=Multi-User Settings
MultiUserSettingsPanel.lbSolrSettings.text=Solr Settings
MultiUserSettingsPanel.lbSolrSettings.text=Solr Server Settings
MultiUserSettingsPanel.cbEnableMultiUser.text=Enable multi-user cases
MultiUserSettingsPanel.lbDatabaseSettings.text=Database Settings
MultiUserSettingsPanel.lbDatabaseSettings.text=Database Server Settings
MultiUserSettingsPanel.validationErrMsg.incomplete=Fill in all values
MultiUserSettingsPanel.nonWindowsOs.msg=Multi-user cases are only available on Windows platforms
MultiUserSettingsPanel.validationErrMsg.invalidDatabasePort=Invalid database port number
@ -107,7 +107,7 @@ MultiUserSettingsPanel.tbSolrHostname.toolTipText=Hostname or IP Address
MultiUserSettingsPanel.tbSolrPort.toolTipText=Port Number
MultiUserSettingsPanel.lbTestMessageService.text=
MultiUserSettingsPanel.bnTestMessageService.text=Test
MultiUserSettingsPanel.lbMessageServiceSettings.text=ActiveMQ Message Service Settings
MultiUserSettingsPanel.lbMessageServiceSettings.text=ActiveMQ Message Server Settings
MultiUserSettingsPanel.tbMsgPort.toolTipText=Port Number
MultiUserSettingsPanel.tbMsgPort.text=
MultiUserSettingsPanel.tbMsgUsername.toolTipText=User Name (optional)

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.makeCorrAttrsFromArtifact(bbArtifact);
List<CorrelationAttributeInstance> listOfPossibleAttributes = CorrelationAttributeUtil.makeCorrAttrsForCorrelation(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

@ -23,6 +23,10 @@ import com.google.common.cache.CacheBuilder;
import com.google.common.io.Files;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Paths;
@ -79,6 +83,9 @@ import org.sleuthkit.autopsy.textextractors.TextExtractor;
import org.sleuthkit.autopsy.textextractors.TextExtractorFactory;
import org.sleuthkit.autopsy.textsummarizer.TextSummarizer;
import org.sleuthkit.autopsy.textsummarizer.TextSummary;
import org.sleuthkit.autopsy.texttranslation.NoServiceProviderException;
import org.sleuthkit.autopsy.texttranslation.TextTranslationService;
import org.sleuthkit.autopsy.texttranslation.TranslationException;
/**
* Main class to perform the file search.
@ -304,9 +311,113 @@ class FileSearch {
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error getting children for file: " + file.getId(), ex);
}
image = image == null ? image : image.getScaledInstance(ImageUtils.ICON_SIZE_MEDIUM, ImageUtils.ICON_SIZE_MEDIUM,
image = image == null ? image : image.getScaledInstance(ImageUtils.ICON_SIZE_MEDIUM, ImageUtils.ICON_SIZE_MEDIUM,
Image.SCALE_SMOOTH);
return new TextSummary(getFirstLines(file), image, countOfImages);
String summaryText = null;
if (file.getMd5Hash() != null) {
try {
summaryText = getSavedSummary(Paths.get(Case.getCurrentCaseThrows().getCacheDirectory(), "summaries", file.getMd5Hash() + "-default-" + PREVIEW_SIZE + "-translated.txt").toString());
} catch (NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to retrieve saved summary. No case is open.", ex);
}
}
if (StringUtils.isBlank(summaryText)) {
String firstLines = getFirstLines(file);
String translatedFirstLines = getTranslatedVersion(firstLines);
if (!StringUtils.isBlank(translatedFirstLines)) {
summaryText = translatedFirstLines;
if (file.getMd5Hash() != null) {
try {
saveSummary(summaryText, Paths.get(Case.getCurrentCaseThrows().getCacheDirectory(), "summaries", file.getMd5Hash() + "-default-" + PREVIEW_SIZE + "-translated.txt").toString());
} catch (NoCurrentCaseException ex) {
logger.log(Level.WARNING, "Unable to save translated summary. No case is open.", ex);
}
}
} else {
summaryText = firstLines;
}
}
return new TextSummary(summaryText, image, countOfImages);
}
/**
* Provide an English version of the specified String if it is not English,
* translation is enabled, and it can be translated.
*
* @param documentString The String to provide an English version of.
*
* @return The English version of the provided String, or null if no
* translation occurred.
*/
private static String getTranslatedVersion(String documentString) {
try {
TextTranslationService translatorInstance = TextTranslationService.getInstance();
if (translatorInstance.hasProvider()) {
String translatedResult = translatorInstance.translate(documentString);
if (translatedResult.isEmpty() == false) {
return translatedResult;
}
}
} catch (NoServiceProviderException | TranslationException ex) {
logger.log(Level.INFO, "Error translating string for summary", ex);
}
return null;
}
/**
* Find and load a saved summary from the case folder for the specified
* file.
*
* @param summarySavePath The full path for the saved summary file.
*
* @return The summary found given the specified path, null if no summary
* was found.
*/
private static String getSavedSummary(String summarySavePath) {
if (summarySavePath == null) {
return null;
}
File savedFile = new File(summarySavePath);
if (savedFile.exists()) {
try (BufferedReader bReader = new BufferedReader(new FileReader(savedFile))) {
// pass the path to the file as a parameter
StringBuilder sBuilder = new StringBuilder();
String sCurrentLine = bReader.readLine();
while (sCurrentLine != null) {
sBuilder.append(sCurrentLine).append('\n');
sCurrentLine = bReader.readLine();
}
return sBuilder.toString();
} catch (IOException ingored) {
//summary file may not exist or may be incomplete in which case return null so a summary can be generated
return null; //no saved summary was able to be found
}
} else {
try { //if the file didn't exist make sure the parent directories exist before we move on to creating a summary
Files.createParentDirs(savedFile);
} catch (IOException ex) {
logger.log(Level.WARNING, "Unable to create summaries directory in case folder for file at: " + summarySavePath, ex);
}
return null; //no saved summary was able to be found
}
}
/**
* Save a summary at the specified location.
*
* @param summary The text of the summary being saved.
* @param summarySavePath The full path for the saved summary file.
*/
private static void saveSummary(String summary, String summarySavePath) {
if (summarySavePath == null) {
return; //can't save a summary if we don't have a path
}
try (FileWriter myWriter = new FileWriter(summarySavePath)) {
myWriter.write(summary);
} catch (IOException ex) {
logger.log(Level.WARNING, "Unable to save summary at: " + summarySavePath, ex);
}
}
/**

View File

@ -310,7 +310,7 @@ final public class MapPanel extends javax.swing.JPanel {
void setZoom(int zoom) {
zoomChanging = true;
mapViewer.setZoom(zoom);
zoomSlider.setValue((zoomSlider.getMaximum() + zoomSlider.getMinimum()) - zoom);
zoomSlider.setValue(zoom);
zoomChanging = false;
}
@ -572,6 +572,7 @@ final public class MapPanel extends javax.swing.JPanel {
zoomSlider.setOrientation(javax.swing.JSlider.VERTICAL);
zoomSlider.setPaintTicks(true);
zoomSlider.setSnapToTicks(true);
zoomSlider.setInverted(true);
zoomSlider.setMinimumSize(new java.awt.Dimension(35, 100));
zoomSlider.setOpaque(false);
zoomSlider.setPreferredSize(new java.awt.Dimension(35, 190));

View File

@ -2,7 +2,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,9 +25,9 @@ import java.util.Map;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil;
import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil.GeoWaypointList.GeoWaypoint;
import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil.GeoWaypointList;
import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil;
import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil.InvalidJsonException;
import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoints;
/**
* A Route represents a TSK_GPS_ROUTE artifact which has a start and end point
@ -42,8 +42,6 @@ public class Route extends GeoPath {
// This list is not expected to change after construction so the
// constructor will take care of creating an unmodifiable List
private final List<Waypoint.Property> propertiesList;
private static final TskGeoWaypointsUtil attributeUtil = new TskGeoWaypointsUtil();
/**
* Construct a route for the given artifact.
@ -119,9 +117,13 @@ public class Route extends GeoPath {
}
if (attribute != null) {
GeoWaypointList waypoints = attributeUtil.fromAttribute(attribute);
for(GeoWaypoint waypoint: waypoints) {
GeoWaypoints waypoints;
try {
waypoints = BlackboardJsonAttrUtil.fromAttribute(attribute, GeoWaypoints.class);
} catch (InvalidJsonException ex) {
throw new GeoLocationDataException(String.format("Unable to parse waypoints in TSK_GEO_WAYPOINTS attribute (artifact object ID =%d)", artifact.getId()), ex);
}
for (GeoWaypoints.Waypoint waypoint : waypoints) {
addToPath(new Waypoint(artifact, label, null, waypoint.getLatitude(), waypoint.getLongitude(), waypoint.getAltitude(), null, attributeMap, this));
}
} else {

View File

@ -1,5 +1,4 @@
/*
*
* Autopsy Forensic Browser
*
* Copyright 2020 Basis Technology Corp.
@ -26,26 +25,24 @@ import java.util.Map;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil;
import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList;
import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList.GeoTrackPoint;
import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil;
import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil.InvalidJsonException;
import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints;
/**
* A GPS track with which wraps the TSK_GPS_TRACK artifact.
*/
public final class Track extends GeoPath{
public final class Track extends GeoPath {
private final Long startTimestamp;
private final Long endTimeStamp;
private static final TskGeoTrackpointsUtil attributeUtil = new TskGeoTrackpointsUtil();
/**
* Construct a new Track for the given artifact.
*
*
* @param artifact
*
* @throws GeoLocationDataException
*
* @throws GeoLocationDataException
*/
public Track(BlackboardArtifact artifact) throws GeoLocationDataException {
this(artifact, Waypoint.getAttributesFromArtifactAsMap(artifact));
@ -53,49 +50,49 @@ public final class Track extends GeoPath{
/**
* Construct a Track for the given artifact and attributeMap.
*
* @param artifact TSK_GPD_TRACK artifact
* @param attributeMap Map of the artifact attributes
*
* @throws GeoLocationDataException
*
* @param artifact TSK_GPD_TRACK artifact
* @param attributeMap Map of the artifact attributes
*
* @throws GeoLocationDataException
*/
private Track(BlackboardArtifact artifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
super(artifact, getTrackName(attributeMap));
GeoTrackPointList points = getPointsList(attributeMap);
GeoTrackPoints points = getPointsList(attributeMap);
buildPath(points, artifact);
startTimestamp = points.getStartTime();
endTimeStamp = points.getEndTime();
}
/**
* Returns the start time of this track.
*
* @return Earliest time, or null if none was available.
* (seconds from java epoch)
*
* @return Earliest time, or null if none was available. (seconds from java
* epoch)
*/
public Long getStartTime() {
return startTimestamp;
}
/**
* Returns the end time of this track.
*
* @return Earliest timestamp, or null if none was available.
* (seconds from java epoch)
*
* @return Earliest timestamp, or null if none was available. (seconds from
* java epoch)
*/
public Long getEndTime() {
return endTimeStamp;
}
/**
* Return the name of the track from the attributeMap.
* Track name is stored in the attribute TSK_NAME
*
* Return the name of the track from the attributeMap. Track name is stored
* in the attribute TSK_NAME
*
* @param attributeMap
* @return Track name or empty string if none was available.
*
* @return Track name or empty string if none was available.
*/
private static String getTrackName(Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) {
BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
@ -105,38 +102,41 @@ public final class Track extends GeoPath{
/**
* Create the list of TrackWaypoints from the GeoTrackPoint list.
*
* @param points List of GeoTrackPoints
*
*
* @param points GeoTrackPoints object.
* @param artifact The artifact to which these points belong
*
* @throws GeoLocationDataException
*
* @throws GeoLocationDataException
*/
@Messages({
"# {0} - track name",
"GEOTrack_point_label_header=Trackpoint for track: {0}"
})
private void buildPath(GeoTrackPointList points, BlackboardArtifact artifact)
throws GeoLocationDataException {
for(GeoTrackPoint point: points) {
private void buildPath(GeoTrackPoints points, BlackboardArtifact artifact) throws GeoLocationDataException {
for (GeoTrackPoints.TrackPoint point : points) {
addToPath(new TrackWaypoint(artifact, Bundle.GEOTrack_point_label_header(getLabel()), point));
}
}
/**
* Returns the list of GeoTrackPoints from the attributeMap. Creates the
* Returns the list of GeoTrackPoints from the attributeMap. Creates the
* GeoTrackPoint list from the TSK_GEO_TRACKPOINTS attribute.
*
*
* @param attributeMap Map of artifact attributes.
*
*
* @return GeoTrackPoint list empty list if the attribute was not found.
*
* @throws GeoLocationDataException
*/
private GeoTrackPointList getPointsList(Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) {
private GeoTrackPoints getPointsList(Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_TRACKPOINTS);
if (attribute != null) {
return attributeUtil.fromAttribute(attribute);
try {
return BlackboardJsonAttrUtil.fromAttribute(attribute, GeoTrackPoints.class);
} catch (InvalidJsonException ex) {
throw new GeoLocationDataException("Unable to parse track points in TSK_GEO_TRACKPOINTS attribute", ex);
}
}
return null;
}
@ -149,16 +149,16 @@ public final class Track extends GeoPath{
/**
* Construct a TrackWaypoint.
*
* @param artifact the artifact to which this waypoint belongs
*
*
* @param artifact the artifact to which this waypoint belongs
*
* @param pointLabel the label for the waypoint
*
* @param point GeoTrackPoint
*
* @throws GeoLocationDataException
*
* @param point GeoTrackPoint
*
* @throws GeoLocationDataException
*/
TrackWaypoint(BlackboardArtifact artifact, String pointLabel, GeoTrackPoint point) throws GeoLocationDataException {
TrackWaypoint(BlackboardArtifact artifact, String pointLabel, GeoTrackPoints.TrackPoint point) throws GeoLocationDataException {
super(artifact, pointLabel,
point.getTimeStamp(),
point.getLatitude(),
@ -172,10 +172,10 @@ public final class Track extends GeoPath{
}
/**
* Overloaded to return a property list that is generated from
* the GeoTrackPoint instead of an artifact.
*
* @return unmodifiable list of Waypoint.Property
* Overloaded to return a property list that is generated from the
* GeoTrackPoint instead of an artifact.
*
* @return unmodifiable list of Waypoint.Property
*/
@Override
public List<Waypoint.Property> getOtherProperties() {
@ -184,16 +184,16 @@ public final class Track extends GeoPath{
/**
* Create a propertyList specific to GeoTrackPoints.
*
*
* @param point GeoTrackPoint to get values from.
*
*
* @return A list of Waypoint.properies.
*/
@Messages({
"Track_distanceTraveled_displayName=Distance traveled",
"Track_distanceFromHome_displayName=Distance from home point"
})
private List<Waypoint.Property> createPropertyList(GeoTrackPoint point) {
private List<Waypoint.Property> createPropertyList(GeoTrackPoints.TrackPoint point) {
List<Waypoint.Property> list = new ArrayList<>();
Long timestamp = point.getTimeStamp();

View File

@ -41,11 +41,11 @@ import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList.GeoTrackPoint;
import org.sleuthkit.datamodel.blackboardutils.GeoArtifactsHelper;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.Blackboard.BlackboardException;
import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList;
import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints;
import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints.TrackPoint;
/**
* Extract drone position data from DJI Phantom drones.
@ -111,7 +111,7 @@ final class DATExtractor extends DroneExtractor {
}
// Process the csv file
GeoTrackPointList trackPoints = processCSVFile(context, DATFile, csvFilePath);
GeoTrackPoints trackPoints = processCSVFile(context, DATFile, csvFilePath);
if (trackPoints != null && !trackPoints.isEmpty()) {
(new GeoArtifactsHelper(getSleuthkitCase(), getName(), "DatCon", DATFile)).addTrack(DATFile.getName(), trackPoints, null);
@ -188,8 +188,8 @@ final class DATExtractor extends DroneExtractor {
*
* @throws DroneIngestException
*/
private GeoTrackPointList processCSVFile(IngestJobContext context, AbstractFile DATFile, String csvFilePath) throws DroneIngestException {
GeoTrackPointList trackPoints = new GeoTrackPointList();
private GeoTrackPoints processCSVFile(IngestJobContext context, AbstractFile DATFile, String csvFilePath) throws DroneIngestException {
GeoTrackPoints trackPoints = new GeoTrackPoints();
try (BufferedReader reader = new BufferedReader(new FileReader(new File(csvFilePath)))) {
// First read in the header line and process
String line = reader.readLine();
@ -201,7 +201,7 @@ final class DATExtractor extends DroneExtractor {
}
String[] values = line.split(","); //NON-NLS
GeoTrackPoint point = createTrackPoint(headerMap, values);
TrackPoint point = createTrackPoint(headerMap, values);
if (point != null) {
trackPoints.addPoint(point);
}
@ -246,7 +246,7 @@ final class DATExtractor extends DroneExtractor {
*
* @throws DroneIngestException
*/
private GeoTrackPoint createTrackPoint(Map<String, Integer> columnLookup, String[] values) throws DroneIngestException {
private TrackPoint createTrackPoint(Map<String, Integer> columnLookup, String[] values) throws DroneIngestException {
Double latitude = getDoubleValue(columnLookup.get(HEADER_LAT), values);
Double longitude = getDoubleValue(columnLookup.get(HEADER_LONG), values);
@ -256,7 +256,7 @@ final class DATExtractor extends DroneExtractor {
return null;
}
return new GeoTrackPoint(latitude,
return new TrackPoint(latitude,
longitude,
getDoubleValue(columnLookup.get(HEADER_ALTITUDE), values),
null,

View File

@ -52,6 +52,7 @@ import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.CentralRepoHashS
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.SetEvt;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
/**
@ -94,6 +95,17 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan
}
}
});
HashDbManager.getInstance().addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String propName = evt.getPropertyName();
if(propName.equals(SetEvt.DB_ADDED.toString()) ||
propName.equals(SetEvt.DB_DELETED.toString())) {
hashSetTableModel.refreshModel();
}
}
});
}
@NbBundle.Messages({"HashLookupSettingsPanel.Title=Global Hash Lookup Settings"})

View File

@ -59,7 +59,7 @@ import org.sleuthkit.autopsy.report.ReportModule;
@ActionReferences(value = {
@ActionReference(path = "Menu/Tools", position = 301, separatorAfter = 399)
,
@ActionReference(path = "Toolbars/Case", position = 107)})
@ActionReference(path = "Toolbars/Case", position = 106)})
public final class ReportWizardAction extends CallableSystemAction implements Presenter.Toolbar, ActionListener {
private static final Logger logger = Logger.getLogger(ReportWizardAction.class.getName());

View File

@ -1,8 +1,8 @@
Manifest-Version: 1.0
OpenIDE-Module: org.sleuthkit.autopsy.corelibs/3
OpenIDE-Module-Implementation-Version: 6
OpenIDE-Module-Implementation-Version: 7
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/corelibs/Bundle.properties
OpenIDE-Module-Specification-Version: 1.3
OpenIDE-Module-Specification-Version: 1.4
AutoUpdate-Show-In-Client: true
AutoUpdate-Essential-Module: true

View File

@ -135,7 +135,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.18</specification-version>
<specification-version>10.19</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -144,7 +144,7 @@
<compile-dependency/>
<run-dependency>
<release-version>3</release-version>
<specification-version>1.3</specification-version>
<specification-version>1.4</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -57,6 +57,7 @@ import org.sleuthkit.autopsy.ingest.IngestJobStartResult;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestModuleError;
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.datamodel.AbstractFile;
/**
@ -83,6 +84,7 @@ class MultiUserTestTool {
"MultiUserTestTool.unableCreatFile=Unable to create a file in case output directory",
"MultiUserTestTool.unableAddFileAsDataSource=Unable to add test file as data source to case",
"MultiUserTestTool.unableToReadTestFileFromDatabase=Unable to read test file info from case database",
"MultiUserTestTool.unableToInitializeFilTypeDetector=Unable to initialize File Type Detector",
"MultiUserTestTool.unableToUpdateKWSIndex=Unable to write to Keyword Search index",
"MultiUserTestTool.unableToRunIngest=Unable to run ingest on test data source",
"MultiUserTestTool.unexpectedError=Unexpected error while performing Multi User test",
@ -187,6 +189,16 @@ class MultiUserTestTool {
}
AbstractFile file = listOfFiles.get(0);
// Set MIME type of the test file (required to test indexing)
FileTypeDetector fileTypeDetector = null;
try {
fileTypeDetector = new FileTypeDetector();
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
return Bundle.MultiUserTestTool_unableToInitializeFilTypeDetector() + ". " + ex.getMessage();
}
String mimeType = fileTypeDetector.getMIMEType(file);
file.setMIMEType(mimeType);
// write to KWS index
KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class);

View File

@ -127,7 +127,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.18</specification-version>
<specification-version>10.19</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -136,7 +136,7 @@
<compile-dependency/>
<run-dependency>
<release-version>3</release-version>
<specification-version>1.3</specification-version>
<specification-version>1.4</specification-version>
</run-dependency>
</dependency>
</module-dependencies>

View File

@ -37,12 +37,10 @@ from org.sleuthkit.datamodel import BlackboardArtifact
from org.sleuthkit.datamodel import BlackboardAttribute
from org.sleuthkit.datamodel import TskCoreException
from org.sleuthkit.datamodel.blackboardutils import GeoArtifactsHelper
from org.sleuthkit.datamodel.blackboardutils.attributes import TskGeoWaypointsUtil
from org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil import GeoWaypointList
from org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil.GeoWaypointList import GeoWaypoint
from org.sleuthkit.datamodel.blackboardutils.attributes import TskGeoTrackpointsUtil
from org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil import GeoTrackPointList
from org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList import GeoTrackPoint
from org.sleuthkit.datamodel.blackboardutils.attributes import GeoWaypoints
from org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoints import Waypoint
from org.sleuthkit.datamodel.blackboardutils.attributes import GeoTrackPoints
from org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints import TrackPoint
from org.sleuthkit.autopsy.datamodel import ContentUtils
from org.sleuthkit.autopsy.ingest import IngestModule
from org.sleuthkit.autopsy.ingest.IngestModule import IngestModuleException
@ -166,7 +164,7 @@ class GPXParserDataSourceIngestModule(DataSourceIngestModule):
if self.writeDebugMsgs: self.log(Level.INFO, "Processing tracks from " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
for track in gpx.tracks:
for segment in track.segments:
geoPointList = TskGeoTrackpointsUtil.GeoTrackPointList()
geoPointList = GeoTrackPoints()
for point in segment.points:
elevation = 0
@ -180,7 +178,7 @@ class GPXParserDataSourceIngestModule(DataSourceIngestModule):
except Exception as e:
self.log(Level.WARNING, "Error getting track timestamp from " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + str(e))
geoPointList.addPoint(GeoTrackPoint(point.latitude, point.longitude, elevation, None, 0, 0, 0, timeStamp))
geoPointList.addPoint(TrackPoint(point.latitude, point.longitude, elevation, None, 0, 0, 0, timeStamp))
try:
geoArtifactHelper.addTrack("Track", geoPointList, None)
@ -213,13 +211,13 @@ class GPXParserDataSourceIngestModule(DataSourceIngestModule):
if self.writeDebugMsgs: self.log(Level.INFO, "Processing routes from " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
for route in gpx.routes:
geoWaypointList = TskGeoWaypointsUtil.GeoWaypointList()
geoWaypoints = GeoWaypoints()
for point in route.points:
geoWaypointList.addPoint(GeoWaypoint(point.latitude, point.longitude, point.elevation, point.name))
geoWaypoints.addPoint(Waypoint(point.latitude, point.longitude, point.elevation, point.name))
try:
geoArtifactHelper.addRoute(None, None, geoWaypointList, None)
geoArtifactHelper.addRoute(None, None, geoWaypoints, None)
except Blackboard.BlackboardException as e:
self.log("Error posting GPS route artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
except TskCoreException as e:

View File

@ -103,10 +103,7 @@ class CallLogAnalyzer(general.AndroidComponentAnalyzer):
calleeId = None
timeStamp = resultSet.getLong("date") / 1000
number = resultSet.getString("number")
if not general.isValidPhoneNumer(number):
number = None
duration = resultSet.getLong("duration") # duration of call is in seconds
name = resultSet.getString("name") # name of person dialed or called. None if unregistered

View File

@ -45,19 +45,15 @@ def appendAttachmentList(msgBody, attachmentsList):
"""
Checks if the given string might be a phone number.
"""
def isValidPhoneNumer(data):
try:
return CommunicationsUtils.normalizePhoneNum(data) is not None
except TskCoreException as ex:
return False
def isValidPhoneNumber(data):
return CommunicationsUtils.isValidPhoneNumber(data)
"""
Checks if the given string is a valid email address.
"""
def isValidEmailAddress(data):
try:
return CommunicationsUtils.normalizeEmailAddress(data) is not None
except TskCoreException as ex:
return False
return CommunicationsUtils.isValidEmailAddress(data)

View File

@ -43,8 +43,8 @@ from org.sleuthkit.datamodel import Content
from org.sleuthkit.datamodel import TskCoreException
from org.sleuthkit.datamodel.Blackboard import BlackboardException
from org.sleuthkit.datamodel.blackboardutils import GeoArtifactsHelper
from org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil import GeoWaypointList
from org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil.GeoWaypointList import GeoWaypoint
from org.sleuthkit.datamodel.blackboardutils.attributes import GeoWaypoints
from org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoints import Waypoint
import traceback
import general
@ -117,9 +117,9 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer):
source_lat = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("source_lat"))
source_lng = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("source_lng"))
waypointlist = GeoWaypointList()
waypointlist.addPoint(GeoWaypoint(source_lat, source_lng, None, None))
waypointlist.addPoint(GeoWaypoint(dest_lat, dest_lng, None, dest_address))
waypointlist = GeoWaypoints()
waypointlist.addPoint(Waypoint(source_lat, source_lng, None, None))
waypointlist.addPoint(Waypoint(dest_lat, dest_lng, None, dest_address))
artifactHelper.addRoute(dest_title, time, waypointlist, None)

View File

@ -45,7 +45,8 @@ from org.sleuthkit.datamodel import Content
from org.sleuthkit.datamodel import TskCoreException
from org.sleuthkit.datamodel.Blackboard import BlackboardException
from org.sleuthkit.datamodel.blackboardutils import GeoArtifactsHelper
from org.sleuthkit.datamodel.blackboardutils.attributes import TskGeoTrackpointsUtil
from org.sleuthkit.datamodel.blackboardutils.attributes import GeoTrackPoints
from org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints import TrackPoint
import traceback
import general
@ -139,14 +140,14 @@ class OruxMapsAnalyzer(general.AndroidComponentAnalyzer):
trackpointsQueryString = "SELECT trkptlat, trkptlon, trkptalt, trkpttime FROM trackpoints WHERE trkptseg = " + segmentId
trackpointsResultSet = oruxMapsTrackpointsDb.runQuery(trackpointsQueryString)
if trackpointsResultSet is not None:
geoPointList = TskGeoTrackpointsUtil.GeoTrackPointList()
geoPointList = GeoTrackPoints()
while trackpointsResultSet.next():
latitude = trackpointsResultSet.getDouble("trkptlat")
longitude = trackpointsResultSet.getDouble("trkptlon")
altitude = trackpointsResultSet.getDouble("trkptalt")
time = trackpointsResultSet.getLong("trkpttime") / 1000 # milliseconds since unix epoch
geoPointList.addPoint(TskGeoTrackpointsUtil.GeoTrackPointList.GeoTrackPoint(latitude, longitude, altitude, segmentName, 0, 0, 0, time))
geoPointList.addPoint(TrackPoint(latitude, longitude, altitude, segmentName, 0, 0, 0, time))
try:
geoartifact = geoArtifactHelper.addTrack(segmentName, geoPointList, None)

View File

@ -286,7 +286,7 @@ class TextNowContactsParser(TskContactsParser):
def get_phone(self):
number = self.result_set.getString("number")
return (number if general.isValidPhoneNumer(number) else None)
return (number if general.isValidPhoneNumber(number) else None)
def get_email(self):
# occasionally the 'number' column may have an email address instead

View File

@ -435,7 +435,7 @@ class WhatsAppContactsParser(TskContactsParser):
def get_phone(self):
number = self.result_set.getString("number")
return (number if general.isValidPhoneNumer(number) else None)
return (number if general.isValidPhoneNumber(number) else None)
def get_email(self):
# occasionally the 'number' column may have an email address instead

View File

@ -119,7 +119,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.18</specification-version>
<specification-version>10.19</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -128,7 +128,7 @@
<compile-dependency/>
<run-dependency>
<release-version>3</release-version>
<specification-version>1.3</specification-version>
<specification-version>1.4</specification-version>
</run-dependency>
</dependency>
</module-dependencies>

View File

@ -1,3 +1,32 @@
---------------- VERSION 4.15.0 --------------
New UI Features:
- Added Document view to File Discovery.
- Expanded Context Content Viewer to show if an app accessed a file.
- Added translation feature to Message Content Viewer.
- Added waypoint type filter to the Geolocation viewer.
- Added zoom feature to Indexed Text Content Viewer.
New Ingest Modules Features:
- New GPX ingest module.
- New Drone ingest module for DJI drones based on DatCon.
- Create artifacts for files opened by Adobe Reader, Windows Media Player, Office Docs (Most Recently Used (MRU) and TrustRecords), 7Zip MRU, WinRAR MRU, Applets, Microsoft Management Console (MMC) via RegRipper.
New Central Repository Features:
- Central Repository stores account IDs that were previously seen.
- Central Repository is enabled by default to store past hashes. Feature to flag previously seen files is disabled by default.
Other New Features:
- Multi-user cases can be created via command line
Bug fixes:
- Prevent entire application from crashing when gstreamer crashes on videos.
- Improve Geolocation viewer with large data sets.
- Fix error with non-sector aligned reads on local disks.
- Times from Recycle Bin files are now in timeline.
- Validate timeline events and ignore events too far in the future.
- Moved some database queries off of UI thread.
- Remove hard coded sizes from UI that cause issues with other languages.
---------------- VERSION 4.14.0 --------------
Specialized UIs:
- New File Discovery UI that allows you to search and filter for certain types of files.

View File

@ -60,7 +60,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.18</specification-version>
<specification-version>10.19</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -69,7 +69,7 @@
<compile-dependency/>
<run-dependency>
<release-version>3</release-version>
<specification-version>1.3</specification-version>
<specification-version>1.4</specification-version>
</run-dependency>
</dependency>
</module-dependencies>

View File

@ -47,7 +47,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.18</specification-version>
<specification-version>10.19</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy User Documentation"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 4.14.0
PROJECT_NUMBER = 4.15.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@ -1025,7 +1025,7 @@ GENERATE_HTML = YES
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = 4.14.0
HTML_OUTPUT = 4.15.0
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1017 B

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@ -8,14 +8,14 @@ ActiveMQ is a messaging service that allows the Autopsy clients to communicate w
\section install_activemq_prereq Prerequisites
You will need:
- 64-bit version of the Java Runtime Environment (JRE) from http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html.
- 64-bit version of the Java 8 Runtime Environment (JRE) from https://github.com/ojdkbuild/ojdkbuild (<a href="https://github.com/ojdkbuild/ojdkbuild/releases/download/java-1.8.0-openjdk-1.8.0.242-1.b08/java-1.8.0-openjdk-1.8.0.242-1.b08.ojdkbuild.windows.x86_64.msi"> Link to installer</a>)
- Download ActiveMQ from: http://activemq.apache.org/download.html . Autopsy has been tested with ActiveMQ version 5.14.0.
\section install_activemq_install Installation
\subsection install_activemq_install_java JRE Installation
Install the Java JRE if needed. You can test this by running _where java_ from the command line. If you see output like the yellow results below, you have a JRE.
Install the Java JRE if needed. You can test this by running _where java_ from the command line. If you see output similar to the results below, you have a JRE.
<br><br>
\image html wherejava.PNG
<br><br>

View File

@ -13,7 +13,7 @@ Solr's embedded ZooKeeper is also used as a coordination service for Autopsy.
We use Bitnami Solr, which packages Solr as a Windows service.
You will need:
- A 64-bit version of the Java Runtime Environment (JRE) from http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html.
- A 64-bit version of the Java 8 Runtime Environment (JRE) from https://github.com/ojdkbuild/ojdkbuild. (<a href="https://github.com/ojdkbuild/ojdkbuild/releases/download/java-1.8.0-openjdk-1.8.0.242-1.b08/java-1.8.0-openjdk-1.8.0.242-1.b08.ojdkbuild.windows.x86_64.msi"> Link to installer</a>)
- The Apache Solr 4.10.3-0 installation package. This is no longer available from its original source, but you can find it on our site: https://sourceforge.net/projects/autopsy/files/CollaborativeServices/Solr.
-- NOTE: We tested Solr 6 at one point, but ran into stability problems when loading and unloading cores. For now, you need to use Solr 4.
- An installed version of Autopsy so that you can copy files from it. You can install Autopsy on one of the planned client systems. You do not need to install it on the Solr server.
@ -24,7 +24,11 @@ You will need:
\section install_solr_install Installation
\subsection install_solr_install_java JRE Installation
1. JREs are normally installed under "C:\Program Files\Java\jre(version)", so check there to see if you have one installed already. If not, get the installer as listed in the above Prerequisites section and install it with the default settings.
1. Install the Java JRE if needed. You can test this by running _where java_ from the command line. If you see output similar to the results below, you have a JRE.
<br><br>
\image html wherejava.PNG
<br><br>
If you need the JRE, install it with the default settings.
\subsection install_solr_install_solr Solr Installation
@ -52,7 +56,7 @@ The following steps will configure Solr to run using an account that will have a
+ <i>++JvmOptions=-Dbootstrap_confdir="C:\Bitnami\solr-4.10.3-0\apache-solr\solr\configsets\AutopsyConfig\conf"</i>
+ <i>++JvmOptions=-DzkRun </i>
<br>
- Replace the path to JavaHome with the path to your 64-bit version of the JRE. If you do not know the path, the correct JavaHome path can be obtained by running the command "where java" from the Windows command line. An example is shown below. The text in yellow is what we are interested in. Do not include the "bin" folder in the path you place into the JavaHome variable. A correct example of the final result will look something like this: <i>-JavaHome="C:\Program Files\Java\jre1.8.0_111"</i>
- Replace the path to JavaHome with the path to your 64-bit version of the JRE. If you do not know the path, the correct JavaHome path can be obtained by running the command "where java" from the Windows command line. An example is shown below. The text in yellow is what we are interested in. Do not include the "bin" folder in the path you place into the JavaHome variable. A correct example of the final result will look something like this: <i>-JavaHome="C:\Program Files\ojdkbuild\java-1.8.0-openjdk-1.8.0.222-1"</i>
<br><br>
A portion of an updated _serviceinstall.bat_ is shown below, with the changes marked in yellow.
<br><br>

View File

@ -38,7 +38,7 @@ PROJECT_NAME = "Autopsy"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 4.14.0
PROJECT_NUMBER = 4.15.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears a the top of each page and should give viewer a
@ -1066,7 +1066,7 @@ GENERATE_HTML = YES
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = api-docs/4.14.0/
HTML_OUTPUT = api-docs/4.15.0/
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).

View File

@ -5,7 +5,7 @@ Report modules allow Autopsy users to create different report types. Autopsy co
All custom report modules will be general report modules. General report modules have a single method to generate the report. This method gives the module freedom to find and process any data it so chooses. General modules also have the ability to provide a configuration panel, allowing the user to choose from various displayed settings. The report module may then use the user's selection to generate a more specific report.
General modules are also given the responsibility of updating their report's progress bar and processing label in the UI. A progress panel is given to every general report module. It contains basic API to start, stop, and add to the progress bar, as well as update the processing label. The module is also expected to check the progress bar's status occasionally to see if the user has manually canceled the report.
General modules are also given the responsibility of updating their report's progress bar and processing label in the UI. A progress panel is given to every general report module. It defines a basic API to start, stop, and increment the progress bar and to update the processing label. The module is also expected to check the progress bar's status occasionally to see if the user has manually canceled the report.
\section report_create_module Creating a Report Module
To create a report module, start off by creating a new Java or Python (Jython) class and implementing (Java) or inheriting (Jython) from org.sleuthkit.autopsy.report.GeneralReportModule. You'll need to override multiple methods including the following:
@ -17,11 +17,11 @@ To create a report module, start off by creating a new Java or Python (Jython) c
If your report module requires configuration, you'll need to override:
- org.sleuthkit.autopsy.report.GeneralReportModule.getConfigurationPanel()
For general report modules, Autopsy will simply call the generateReport(String reportPath, ReportProgressPanel progressPanel) method and leave it up to the module to aquire and report data in its desired format. The only requirements are that the module saves to the given report path and updates the org.sleuthkit.autopsy.report.ReportProgressPanel as the report progresses.
For general report modules, Autopsy will simply call the generateReport(String reportPath, ReportProgressPanel progressPanel) method and leave it up to the module to acquire and report data in its desired format. The only requirements are that the module saves to the given report path and updates the org.sleuthkit.autopsy.report.ReportProgressPanel as the report progresses.
When updating the progress panel, it is recommended to update it as infrequently as possible, while still keeping the user informed. If your report processes 100,000 files and you chose to update the UI each time a file is reviewed, the UI would freeze when trying to process all your requests. This would cause problems to not only your reporting module, but to other modules running in parallel. A safer approach would be to update the UI every 1,000 files, or when a certain "category" of the files being processed has changed. For example, the HTML report module increments the progress bar and changes the processing label every time a new Blackboard Artifact Type is being processed.
Autopsy will also display the panel returned by getConfigurationPanel() in the generate report wizard. This panel can be used to allow the user custom controls over the report. To make this panel, use NetBeans to make a new JPanel class and use its layout interface to put the UI widgets in the places that you want them. Then, your getConfigurationPanel() method should create an instance of that class and return it.
Autopsy will also display the panel returned by getConfigurationPanel() in the generate report wizard. This panel can be used to allow the user to customize the report. To make this panel, use NetBeans to make a new JPanel class and use its layout interface to put the UI widgets in the places that you want them. Then, your getConfigurationPanel() method should create an instance of that class and return it.
Typically a general report module should interact with both the Blackboard API in the org.sleuthkit.datamodel.SleuthkitCase class, in addition to an API (possibly external/thirdparty) to convert Blackboard Artifacts to the desired reporting format.
@ -32,7 +32,7 @@ You should call org.sleuthkit.autopsy.casemodule.Case.addReport() with the path
\subsection report_create_module_indexing Indexing Reports
After you have called org.sleuthkit.autopsy.casemodule.Case.addReport() and created a report, you can pass it to org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService.index() so that it is indexed and can then be found by a user. This is most commonly used when an Ingest Module runs a 3rd party tool and the output of that tool is added back into Autopsy as a report. Here is some example code:
After you have called org.sleuthkit.autopsy.casemodule.Case.addReport() and created a report, you can pass it to org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService.index() so that the report text is indexed for keyword search. This is most commonly used when an Ingest Module runs a 3rd party tool and the output of that tool is added back into Autopsy as a report. Here is some example code:
\code{.java}
KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class);

View File

@ -4,10 +4,10 @@ app.title=Autopsy
### lowercase version of above
app.name=${branding.token}
### if left unset, version will default to today's date
app.version=4.14.0
app.version=4.15.0
### build.type must be one of: DEVELOPMENT, RELEASE
#build.type=RELEASE
build.type=DEVELOPMENT
build.type=RELEASE
#build.type=DEVELOPMENT
project.org.netbeans.progress=org-netbeans-api-progress
project.org.sleuthkit.autopsy.experimental=Experimental

View File

@ -36,7 +36,7 @@
<compile-dependency/>
<run-dependency>
<release-version>10</release-version>
<specification-version>10.18</specification-version>
<specification-version>10.19</specification-version>
</run-dependency>
</dependency>
<dependency>