Merge branch 'develop' of https://github.com/sleuthkit/autopsy into 1110-no-prepop-2

# Conflicts:
#	ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java
This commit is contained in:
Raman 2018-11-13 18:00:46 -05:00
commit d5bd765c9b
46 changed files with 816 additions and 1036 deletions

View File

@ -116,6 +116,7 @@ import org.sleuthkit.datamodel.Report;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskUnsupportedSchemaVersionException; import org.sleuthkit.datamodel.TskUnsupportedSchemaVersionException;
import org.sleuthkit.autopsy.coreutils.StopWatch;
/** /**
* An Autopsy case. Currently, only one case at a time may be open. * An Autopsy case. Currently, only one case at a time may be open.
@ -707,11 +708,15 @@ public class Case {
"Case.exceptionMessage.cannotGetLockToDeleteCase=Cannot delete case because it is open for another user or there is a problem with the coordination service." "Case.exceptionMessage.cannotGetLockToDeleteCase=Cannot delete case because it is open for another user or there is a problem with the coordination service."
}) })
public static void deleteCase(CaseMetadata metadata) throws CaseActionException { public static void deleteCase(CaseMetadata metadata) throws CaseActionException {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
synchronized (caseActionSerializationLock) { synchronized (caseActionSerializationLock) {
if (null != currentCase) { if (null != currentCase) {
throw new CaseActionException(Bundle.Case_exceptionMessage_cannotDeleteCurrentCase()); throw new CaseActionException(Bundle.Case_exceptionMessage_cannotDeleteCurrentCase());
} }
} }
stopWatch.stop();
logger.log(Level.INFO, String.format("Used %d s to acquire caseActionSerializationLock (Java monitor in Case class) for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
/* /*
* Set up either a GUI progress indicator without a cancel button (can't * Set up either a GUI progress indicator without a cancel button (can't
@ -733,10 +738,19 @@ public class Case {
* cannot be deleted if another node has it open. * cannot be deleted if another node has it open.
*/ */
progressIndicator.progress(Bundle.Case_progressMessage_checkingForOtherUser()); progressIndicator.progress(Bundle.Case_progressMessage_checkingForOtherUser());
stopWatch.reset();
stopWatch.start();
try (CoordinationService.Lock dirLock = CoordinationService.getInstance().tryGetExclusiveLock(CategoryNode.CASES, metadata.getCaseDirectory())) { try (CoordinationService.Lock dirLock = CoordinationService.getInstance().tryGetExclusiveLock(CategoryNode.CASES, metadata.getCaseDirectory())) {
assert (null != dirLock); stopWatch.stop();
logger.log(Level.INFO, String.format("Used %d s to acquire case directory coordination service lock for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
if (dirLock != null) {
deleteCase(metadata, progressIndicator); deleteCase(metadata, progressIndicator);
} else {
throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireDirLock());
}
} catch (CoordinationServiceException ex) { } catch (CoordinationServiceException ex) {
stopWatch.stop();
logger.log(Level.INFO, String.format("Used %d s to fail to acquire case directory coordination service lock for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
throw new CaseActionException(Bundle.Case_exceptionMessage_cannotGetLockToDeleteCase(), ex); throw new CaseActionException(Bundle.Case_exceptionMessage_cannotGetLockToDeleteCase(), ex);
} }
} }
@ -946,11 +960,13 @@ public class Case {
"Case.exceptionMessage.errorsDeletingCase=Errors occured while deleting the case. See the application log for details" "Case.exceptionMessage.errorsDeletingCase=Errors occured while deleting the case. See the application log for details"
}) })
private static void deleteCase(CaseMetadata metadata, ProgressIndicator progressIndicator) throws CaseActionException { private static void deleteCase(CaseMetadata metadata, ProgressIndicator progressIndicator) throws CaseActionException {
StopWatch stopWatch = new StopWatch();
boolean errorsOccurred = false; boolean errorsOccurred = false;
if (CaseType.MULTI_USER_CASE == metadata.getCaseType()) { if (CaseType.MULTI_USER_CASE == metadata.getCaseType()) {
/* /*
* Delete the case database from the database server. * Delete the case database from the database server.
*/ */
stopWatch.start();
try { try {
progressIndicator.progress(Bundle.Case_progressMessage_deletingCaseDatabase()); progressIndicator.progress(Bundle.Case_progressMessage_deletingCaseDatabase());
CaseDbConnectionInfo db; CaseDbConnectionInfo db;
@ -960,10 +976,14 @@ public class Case {
Statement statement = connection.createStatement();) { Statement statement = connection.createStatement();) {
String deleteCommand = "DROP DATABASE \"" + metadata.getCaseDatabaseName() + "\""; //NON-NLS String deleteCommand = "DROP DATABASE \"" + metadata.getCaseDatabaseName() + "\""; //NON-NLS
statement.execute(deleteCommand); statement.execute(deleteCommand);
stopWatch.stop();
logger.log(Level.INFO, String.format("Used %d s to delete case database for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
} }
} catch (UserPreferencesException | ClassNotFoundException | SQLException ex) { } catch (UserPreferencesException | ClassNotFoundException | SQLException ex) {
logger.log(Level.SEVERE, String.format("Failed to delete case database %s for %s (%s) in %s", metadata.getCaseDatabaseName(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()), ex); logger.log(Level.SEVERE, String.format("Failed to delete case database %s for %s (%s) in %s", metadata.getCaseDatabaseName(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()), ex);
errorsOccurred = true; errorsOccurred = true;
stopWatch.stop();
logger.log(Level.INFO, String.format("Used %d s to fail delete case database for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
} }
} }
@ -973,10 +993,16 @@ public class Case {
progressIndicator.progress(Bundle.Case_progressMessage_deletingTextIndex()); progressIndicator.progress(Bundle.Case_progressMessage_deletingTextIndex());
for (KeywordSearchService searchService : Lookup.getDefault().lookupAll(KeywordSearchService.class)) { for (KeywordSearchService searchService : Lookup.getDefault().lookupAll(KeywordSearchService.class)) {
try { try {
stopWatch.reset();
stopWatch.start();
searchService.deleteTextIndex(metadata); searchService.deleteTextIndex(metadata);
stopWatch.stop();
logger.log(Level.INFO, String.format("Used %d s to delete text index for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
} catch (KeywordSearchServiceException ex) { } catch (KeywordSearchServiceException ex) {
logger.log(Level.SEVERE, String.format("Failed to delete text index for %s (%s) in %s", metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()), ex); logger.log(Level.SEVERE, String.format("Failed to delete text index for %s (%s) in %s", metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()), ex);
errorsOccurred = true; errorsOccurred = true;
stopWatch.stop();
logger.log(Level.INFO, String.format("Used %d s to fail to delete text index for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
} }
} }
@ -984,9 +1010,16 @@ public class Case {
* Delete the case directory. * Delete the case directory.
*/ */
progressIndicator.progress(Bundle.Case_progressMessage_deletingCaseDirectory()); progressIndicator.progress(Bundle.Case_progressMessage_deletingCaseDirectory());
stopWatch.reset();
stopWatch.start();
if (!FileUtil.deleteDir(new File(metadata.getCaseDirectory()))) { if (!FileUtil.deleteDir(new File(metadata.getCaseDirectory()))) {
logger.log(Level.SEVERE, String.format("Failed to delete case directory for %s (%s) in %s", metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory())); logger.log(Level.SEVERE, String.format("Failed to delete case directory for %s (%s) in %s", metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
errorsOccurred = true; errorsOccurred = true;
stopWatch.stop();
logger.log(Level.INFO, String.format("Used %d s to fail to delete case directory for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
} else {
stopWatch.stop();
logger.log(Level.INFO, String.format("Used %d s to delete case directory for %s (%s) in %s", stopWatch.getElapsedTimeSecs(), metadata.getCaseDisplayName(), metadata.getCaseName(), metadata.getCaseDirectory()));
} }
/* /*
@ -1540,11 +1573,13 @@ public class Case {
} }
/** /**
* Notifies case event subscribers that a central repository comment has been changed. * Notifies case event subscribers that a central repository comment has
* been changed.
* *
* This should not be called from the event dispatch thread (EDT) * This should not be called from the event dispatch thread (EDT)
* *
* @param contentId the objectId for the Content which has had its central repo comment changed * @param contentId the objectId for the Content which has had its central
* repo comment changed
* @param newComment the new value of the comment * @param newComment the new value of the comment
*/ */
public void notifyCentralRepoCommentChanged(long contentId, String newComment) { public void notifyCentralRepoCommentChanged(long contentId, String newComment) {
@ -1800,7 +1835,7 @@ public class Case {
progressIndicator.progress(Bundle.Case_progressMessage_preparingToOpenCaseResources()); progressIndicator.progress(Bundle.Case_progressMessage_preparingToOpenCaseResources());
acquireSharedCaseDirLock(metadata.getCaseDirectory()); acquireSharedCaseDirLock(metadata.getCaseDirectory());
try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(metadata.getCaseDirectory())) { try (CoordinationService.Lock resourcesLock = acquireExclusiveCaseResourcesLock(metadata.getCaseDirectory())) {
assert (null != resourcesLock); assert(resourcesLock != null); // Use reference to avoid compile time warning.
open(isNewCase, progressIndicator); open(isNewCase, progressIndicator);
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
releaseSharedCaseDirLock(getMetadata().getCaseDirectory()); releaseSharedCaseDirLock(getMetadata().getCaseDirectory());
@ -2375,7 +2410,7 @@ public class Case {
* @throws CaseActionException with a user-friendly message if the lock * @throws CaseActionException with a user-friendly message if the lock
* cannot be acquired. * cannot be acquired.
*/ */
@Messages({"Case.creationException.couldNotAcquireDirLock=Failed to get lock on case directory."}) @Messages({"Case.creationException.couldNotAcquireDirLock=Failed to get lock on case directory"})
private void acquireSharedCaseDirLock(String caseDir) throws CaseActionException { private void acquireSharedCaseDirLock(String caseDir) throws CaseActionException {
try { try {
caseDirLock = CoordinationService.getInstance().tryGetSharedLock(CategoryNode.CASES, caseDir, DIR_LOCK_TIMOUT_HOURS, TimeUnit.HOURS); caseDirLock = CoordinationService.getInstance().tryGetSharedLock(CategoryNode.CASES, caseDir, DIR_LOCK_TIMOUT_HOURS, TimeUnit.HOURS);

View File

@ -369,7 +369,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor, AutoIngestDat
@Override @Override
public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) { public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
List<String> filePaths = Arrays.asList(new String[]{dataSourcePath.toString()}); List<String> filePaths = Arrays.asList(new String[]{dataSourcePath.toString()});
run(deviceId, deviceId, filePaths, progressMonitor, callBack); run(deviceId, "", filePaths, progressMonitor, callBack);
} }
/** /**

View File

@ -419,7 +419,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
} }
// we can correlate based on the MD5 if it is enabled // we can correlate based on the MD5 if it is enabled
if (this.file != null && EamDb.isEnabled()) { if (this.file != null && EamDb.isEnabled() && this.file.getSize() > 0) {
try { try {
List<CorrelationAttributeInstance.Type> artifactTypes = EamDb.getInstance().getDefinedCorrelationTypes(); List<CorrelationAttributeInstance.Type> artifactTypes = EamDb.getInstance().getDefinedCorrelationTypes();
@ -447,11 +447,8 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
} catch (EamDbException | TskCoreException ex) { } catch (EamDbException | TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
} }
} else {
// If EamDb not enabled, get the Files default correlation type to allow Other Occurances to be enabled. // If EamDb not enabled, get the Files default correlation type to allow Other Occurances to be enabled.
if (this.file != null) { } else if (this.file != null && this.file.getSize() > 0) {
String md5 = this.file.getMd5Hash(); String md5 = this.file.getMd5Hash();
if (md5 != null && !md5.isEmpty()) { if (md5 != null && !md5.isEmpty()) {
try { try {
@ -470,7 +467,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
} }
} }
} }
}
return ret; return ret;
} }
@ -657,9 +653,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
// - The central repo is disabled and the backing file has a valid MD5 hash // - The central repo is disabled and the backing file has a valid MD5 hash
this.file = this.getAbstractFileFromNode(node); this.file = this.getAbstractFileFromNode(node);
if (EamDb.isEnabled()) { if (EamDb.isEnabled()) {
return this.file != null return !getCorrelationAttributesFromNode(node).isEmpty();
&& this.file.getSize() > 0
&& !getCorrelationAttributesFromNode(node).isEmpty();
} else { } else {
return this.file != null return this.file != null
&& this.file.getSize() > 0 && this.file.getSize() > 0
@ -733,8 +727,8 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
* Adjust a given column for the text provided. * Adjust a given column for the text provided.
* *
* @param columnIndex The index of the column to adjust. * @param columnIndex The index of the column to adjust.
* @param text The text whose length will be used to adjust the column * @param text The text whose length will be used to adjust the
* width. * column width.
*/ */
private void setColumnWidthToText(int columnIndex, String text) { private void setColumnWidthToText(int columnIndex, String text) {
TableColumn column = otherCasesTable.getColumnModel().getColumn(columnIndex); TableColumn column = otherCasesTable.getColumnModel().getColumn(columnIndex);

View File

@ -2964,7 +2964,6 @@ abstract class AbstractSqlEamDb implements EamDb {
resultSet.getString("creation_date"), resultSet.getString("case_number"), resultSet.getString("examiner_name"), resultSet.getString("creation_date"), resultSet.getString("case_number"), resultSet.getString("examiner_name"),
resultSet.getString("examiner_email"), resultSet.getString("examiner_phone"), resultSet.getString("notes")); resultSet.getString("examiner_email"), resultSet.getString("examiner_phone"), resultSet.getString("notes"));
return eamCase; return eamCase;
} }
@ -3080,6 +3079,7 @@ abstract class AbstractSqlEamDb implements EamDb {
ResultSet resultSet = null; ResultSet resultSet = null;
Statement statement = null; Statement statement = null;
PreparedStatement preparedStatement = null;
Connection conn = null; Connection conn = null;
try { try {
@ -3114,6 +3114,10 @@ abstract class AbstractSqlEamDb implements EamDb {
logger.log(Level.INFO, "Central Repository is up to date"); logger.log(Level.INFO, "Central Repository is up to date");
return; return;
} }
if (dbSchemaVersion.compareTo(CURRENT_DB_SCHEMA_VERSION) > 0) {
logger.log(Level.INFO, "Central Repository is of newer version than software creates");
return;
}
// Update from 1.0 to 1.1 // Update from 1.0 to 1.1
if (dbSchemaVersion.compareTo(new CaseDbSchemaVersionNumber(1, 1)) < 0) { if (dbSchemaVersion.compareTo(new CaseDbSchemaVersionNumber(1, 1)) < 0) {
@ -3126,7 +3130,56 @@ abstract class AbstractSqlEamDb implements EamDb {
// regardless of whether this succeeds. // regardless of whether this succeeds.
EamDbUtil.insertDefaultOrganization(conn); EamDbUtil.insertDefaultOrganization(conn);
} }
//Update to 1.2
if (dbSchemaVersion.compareTo(new CaseDbSchemaVersionNumber(1, 2)) < 0) {
//update central repository to be able to store new correlation attributes
EamDbPlatformEnum selectedPlatform = EamDbPlatformEnum.getSelectedPlatform();
final String addSsidTableTemplate;
final String addCaseIdIndexTemplate;
final String addDataSourceIdIndexTemplate;
final String addValueIndexTemplate;
final String addKnownStatusIndexTemplate;
final String addAttributeSql;
//get the data base specific code for creating a new _instance table
switch (selectedPlatform) {
case POSTGRESQL:
addAttributeSql = "INSERT INTO correlation_types(id, display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?, ?) " + getConflictClause();
addSsidTableTemplate = PostgresEamDbSettings.getCreateArtifactInstancesTableTemplate();
addCaseIdIndexTemplate = PostgresEamDbSettings.getAddCaseIdIndexTemplate();
addDataSourceIdIndexTemplate = PostgresEamDbSettings.getAddDataSourceIdIndexTemplate();
addValueIndexTemplate = PostgresEamDbSettings.getAddValueIndexTemplate();
addKnownStatusIndexTemplate = PostgresEamDbSettings.getAddKnownStatusIndexTemplate();
break;
case SQLITE:
addAttributeSql = "INSERT OR IGNORE INTO correlation_types(id, display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?, ?)";
addSsidTableTemplate = SqliteEamDbSettings.getCreateArtifactInstancesTableTemplate();
addCaseIdIndexTemplate = SqliteEamDbSettings.getAddCaseIdIndexTemplate();
addDataSourceIdIndexTemplate = SqliteEamDbSettings.getAddDataSourceIdIndexTemplate();
addValueIndexTemplate = SqliteEamDbSettings.getAddValueIndexTemplate();
addKnownStatusIndexTemplate = SqliteEamDbSettings.getAddKnownStatusIndexTemplate();
break;
default:
throw new EamDbException("Currently selected database platform \"" + selectedPlatform.name() + "\" can not be upgraded.");
}
final String wirelessNetworsDbTableName = "wireless_networks";
final String wirelessNetworksTableInstanceName = wirelessNetworsDbTableName + "_instances";
//add the wireless_networks attribute to the correlation_types table
preparedStatement = conn.prepareStatement(addAttributeSql);
preparedStatement.setInt(1, CorrelationAttributeInstance.SSID_TYPE_ID);
preparedStatement.setString(2, Bundle.CorrelationType_SSID_displayName());
preparedStatement.setString(3, wirelessNetworsDbTableName);
preparedStatement.setInt(4, 1);
preparedStatement.setInt(5, 1);
preparedStatement.execute();
//create a new wireless_networks_instances table and add indexes for its columns
statement.execute(String.format(addSsidTableTemplate, wirelessNetworksTableInstanceName, wirelessNetworksTableInstanceName));
statement.execute(String.format(addCaseIdIndexTemplate, wirelessNetworksTableInstanceName, wirelessNetworksTableInstanceName));
statement.execute(String.format(addDataSourceIdIndexTemplate, wirelessNetworksTableInstanceName, wirelessNetworksTableInstanceName));
statement.execute(String.format(addValueIndexTemplate, wirelessNetworksTableInstanceName, wirelessNetworksTableInstanceName));
statement.execute(String.format(addKnownStatusIndexTemplate, wirelessNetworksTableInstanceName, wirelessNetworksTableInstanceName));
}
if (!updateSchemaVersion(conn)) { if (!updateSchemaVersion(conn)) {
throw new EamDbException("Error updating schema version"); throw new EamDbException("Error updating schema version");
} }
@ -3144,6 +3197,7 @@ abstract class AbstractSqlEamDb implements EamDb {
throw ex; throw ex;
} finally { } finally {
EamDbUtil.closeResultSet(resultSet); EamDbUtil.closeResultSet(resultSet);
EamDbUtil.closeStatement(preparedStatement);
EamDbUtil.closeStatement(statement); EamDbUtil.closeStatement(statement);
EamDbUtil.closeConnection(conn); EamDbUtil.closeConnection(conn);
} }

View File

@ -246,6 +246,7 @@ public class CorrelationAttributeInstance implements Serializable {
public static final int EMAIL_TYPE_ID = 2; public static final int EMAIL_TYPE_ID = 2;
public static final int PHONE_TYPE_ID = 3; public static final int PHONE_TYPE_ID = 3;
public static final int USBID_TYPE_ID = 4; public static final int USBID_TYPE_ID = 4;
public static final int SSID_TYPE_ID = 5;
/** /**
* Load the default correlation types * Load the default correlation types
@ -257,7 +258,8 @@ public class CorrelationAttributeInstance implements Serializable {
"CorrelationType.DOMAIN.displayName=Domains", "CorrelationType.DOMAIN.displayName=Domains",
"CorrelationType.EMAIL.displayName=Email Addresses", "CorrelationType.EMAIL.displayName=Email Addresses",
"CorrelationType.PHONE.displayName=Phone Numbers", "CorrelationType.PHONE.displayName=Phone Numbers",
"CorrelationType.USBID.displayName=USB Devices"}) "CorrelationType.USBID.displayName=USB Devices",
"CorrelationType.SSID.displayName=Wireless Networks"})
public static List<CorrelationAttributeInstance.Type> getDefaultCorrelationTypes() throws EamDbException { public static List<CorrelationAttributeInstance.Type> getDefaultCorrelationTypes() throws EamDbException {
List<CorrelationAttributeInstance.Type> DEFAULT_CORRELATION_TYPES = new ArrayList<>(); List<CorrelationAttributeInstance.Type> DEFAULT_CORRELATION_TYPES = new ArrayList<>();
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(FILES_TYPE_ID, Bundle.CorrelationType_FILES_displayName(), "file", true, true)); // NON-NLS DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(FILES_TYPE_ID, Bundle.CorrelationType_FILES_displayName(), "file", true, true)); // NON-NLS
@ -265,6 +267,7 @@ public class CorrelationAttributeInstance implements Serializable {
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(EMAIL_TYPE_ID, Bundle.CorrelationType_EMAIL_displayName(), "email_address", true, true)); // NON-NLS DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(EMAIL_TYPE_ID, Bundle.CorrelationType_EMAIL_displayName(), "email_address", true, true)); // NON-NLS
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(PHONE_TYPE_ID, Bundle.CorrelationType_PHONE_displayName(), "phone_number", true, true)); // NON-NLS DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(PHONE_TYPE_ID, Bundle.CorrelationType_PHONE_displayName(), "phone_number", true, true)); // NON-NLS
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(USBID_TYPE_ID, Bundle.CorrelationType_USBID_displayName(), "usb_devices", true, true)); // NON-NLS DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(USBID_TYPE_ID, Bundle.CorrelationType_USBID_displayName(), "usb_devices", true, true)); // NON-NLS
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(SSID_TYPE_ID, Bundle.CorrelationType_SSID_displayName(), "wireless_networks", true, true)); // NON-NLS
return DEFAULT_CORRELATION_TYPES; return DEFAULT_CORRELATION_TYPES;
} }
@ -286,8 +289,9 @@ public class CorrelationAttributeInstance implements Serializable {
* @param typeId Unique ID for this Correlation Type * @param typeId Unique ID for this Correlation Type
* @param displayName Name of this type displayed in the UI. * @param displayName Name of this type displayed in the UI.
* @param dbTableName Central repository db table where data of this * @param dbTableName Central repository db table where data of this
* type is stored. Must start with a lowercase letter and only contain * type is stored. Must start with a lowercase letter
* lowercase letters, numbers, and '_' characters. * and only contain lowercase letters, numbers, and
* '_' characters.
* @param supported Is this Type currently supported * @param supported Is this Type currently supported
* @param enabled Is this Type currently enabled. * @param enabled Is this Type currently enabled.
*/ */
@ -312,8 +316,9 @@ public class CorrelationAttributeInstance implements Serializable {
* *
* @param displayName Name of this type displayed in the UI. * @param displayName Name of this type displayed in the UI.
* @param dbTableName Central repository db table where data of this * @param dbTableName Central repository db table where data of this
* type is stored Must start with a lowercase letter and only contain * type is stored Must start with a lowercase letter
* lowercase letters, numbers, and '_' characters. * and only contain lowercase letters, numbers, and
* '_' characters.
* @param supported Is this Type currently supported * @param supported Is this Type currently supported
* @param enabled Is this Type currently enabled. * @param enabled Is this Type currently enabled.
*/ */
@ -477,8 +482,8 @@ public class CorrelationAttributeInstance implements Serializable {
* custom_instances) * custom_instances)
* *
* @param dbTableName the dbTableName to set. Must start with lowercase * @param dbTableName the dbTableName to set. Must start with lowercase
* letter and can only contain lowercase letters, numbers, and '_' * letter and can only contain lowercase letters,
* characters. * numbers, and '_' characters.
* *
* @throws EamDbException if dbTableName contains invalid characters * @throws EamDbException if dbTableName contains invalid characters
*/ */

View File

@ -63,6 +63,8 @@ final public class CorrelationAttributeNormalizer {
return normalizePhone(data); return normalizePhone(data);
case CorrelationAttributeInstance.USBID_TYPE_ID: case CorrelationAttributeInstance.USBID_TYPE_ID:
return normalizeUsbId(data); return normalizeUsbId(data);
case CorrelationAttributeInstance.SSID_TYPE_ID:
return data;
default: default:
final String errorMessage = String.format( final String errorMessage = String.format(
"Validator function not found for attribute type: %s", "Validator function not found for attribute type: %s",

View File

@ -159,13 +159,14 @@ public class EamArtifactUtil {
return null; return null;
} }
} }
} else if (correlationType.getId() == CorrelationAttributeInstance.USBID_TYPE_ID } else if (correlationType.getId() == CorrelationAttributeInstance.USBID_TYPE_ID
&& BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID() == artifactTypeID) { && BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID() == artifactTypeID) {
value = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID)).getValueString(); value = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID)).getValueString();
} else if (correlationType.getId() == CorrelationAttributeInstance.SSID_TYPE_ID
&& BlackboardArtifact.ARTIFACT_TYPE.TSK_WIFI_NETWORK.getTypeID() == artifactTypeID) {
value = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SSID)).getValueString();
} }
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting attribute while getting type from BlackboardArtifact.", ex); // NON-NLS logger.log(Level.SEVERE, "Error getting attribute while getting type from BlackboardArtifact.", ex); // NON-NLS
return null; return null;
@ -185,9 +186,10 @@ public class EamArtifactUtil {
* Uses the determined type and vallue, then looks up instance details to * Uses the determined type and vallue, then looks up instance details to
* create proper CorrelationAttributeInstance. * create proper CorrelationAttributeInstance.
* *
* @param bbArtifact the blackboard artifatc * @param bbArtifact the blackboard artifact
* @param correlationType the given type * @param correlationType the given type
* @param value the artifact value * @param value the artifact value
*
* @return CorrelationAttributeInstance from details * @return CorrelationAttributeInstance from details
*/ */
private static CorrelationAttributeInstance makeCorrelationAttributeInstanceUsingTypeValue(BlackboardArtifact bbArtifact, CorrelationAttributeInstance.Type correlationType, String value) { private static CorrelationAttributeInstance makeCorrelationAttributeInstanceUsingTypeValue(BlackboardArtifact bbArtifact, CorrelationAttributeInstance.Type correlationType, String value) {

View File

@ -31,9 +31,9 @@ import org.sleuthkit.datamodel.CaseDbSchemaVersionNumber;
*/ */
public interface EamDb { public interface EamDb {
public static final int SCHEMA_VERSION = 1; public static final int SCHEMA_VERSION = 2;
public static final CaseDbSchemaVersionNumber CURRENT_DB_SCHEMA_VERSION public static final CaseDbSchemaVersionNumber CURRENT_DB_SCHEMA_VERSION
= new CaseDbSchemaVersionNumber(1, 1); = new CaseDbSchemaVersionNumber(1, 2);
/** /**

View File

@ -36,7 +36,8 @@ import org.sleuthkit.autopsy.coreutils.TextConverterException;
/** /**
* Settings for the Postgres implementation of the Central Repository database * Settings for the Postgres implementation of the Central Repository database
* *
* NOTE: This is public scope because the options panel calls it directly to set/get * NOTE: This is public scope because the options panel calls it directly to
* set/get
*/ */
public final class PostgresEamDbSettings { public final class PostgresEamDbSettings {
@ -391,26 +392,13 @@ public final class PostgresEamDbSettings {
createCorrelationTypesTable.append("CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)"); createCorrelationTypesTable.append("CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)");
createCorrelationTypesTable.append(")"); createCorrelationTypesTable.append(")");
// Each "%s" will be replaced with the relevant TYPE_instances table name. String createArtifactInstancesTableTemplate = getCreateArtifactInstancesTableTemplate();
StringBuilder createArtifactInstancesTableTemplate = new StringBuilder();
createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
createArtifactInstancesTableTemplate.append("id SERIAL PRIMARY KEY,");
createArtifactInstancesTableTemplate.append("case_id integer NOT NULL,");
createArtifactInstancesTableTemplate.append("data_source_id integer NOT NULL,");
createArtifactInstancesTableTemplate.append("value text NOT NULL,");
createArtifactInstancesTableTemplate.append("file_path text NOT NULL,");
createArtifactInstancesTableTemplate.append("known_status integer NOT NULL,");
createArtifactInstancesTableTemplate.append("comment text,");
createArtifactInstancesTableTemplate.append("CONSTRAINT %s_multi_unique_ UNIQUE (data_source_id, value, file_path),");
createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,");
createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL");
createArtifactInstancesTableTemplate.append(")");
// Each "%s" will be replaced with the relevant TYPE_instances table name. String instancesIdx1 = getAddCaseIdIndexTemplate();
String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)"; String instancesIdx2 = getAddDataSourceIdIndexTemplate();
String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)"; String instancesIdx3 = getAddValueIndexTemplate();
String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)"; String instancesIdx4 = getAddKnownStatusIndexTemplate();
StringBuilder createDbInfoTable = new StringBuilder(); StringBuilder createDbInfoTable = new StringBuilder();
createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info ("); createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info (");
@ -454,7 +442,7 @@ public final class PostgresEamDbSettings {
reference_type_dbname = EamDbUtil.correlationTypeToReferenceTableName(type); reference_type_dbname = EamDbUtil.correlationTypeToReferenceTableName(type);
instance_type_dbname = EamDbUtil.correlationTypeToInstanceTableName(type); instance_type_dbname = EamDbUtil.correlationTypeToInstanceTableName(type);
stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), instance_type_dbname, instance_type_dbname)); stmt.execute(String.format(createArtifactInstancesTableTemplate, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesIdx1, instance_type_dbname, instance_type_dbname)); stmt.execute(String.format(instancesIdx1, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesIdx2, instance_type_dbname, instance_type_dbname)); stmt.execute(String.format(instancesIdx2, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesIdx3, instance_type_dbname, instance_type_dbname)); stmt.execute(String.format(instancesIdx3, instance_type_dbname, instance_type_dbname));
@ -480,6 +468,83 @@ public final class PostgresEamDbSettings {
return true; return true;
} }
/**
* Get the template String for creating a new _instances table in a Postgres
* central repository. %s will exist in the template where the name of the
* new table will be addedd.
*
* @return a String which is a template for cretating a new _instances table
*/
static String getCreateArtifactInstancesTableTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
StringBuilder createArtifactInstancesTableTemplate = new StringBuilder();
createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
createArtifactInstancesTableTemplate.append("id SERIAL PRIMARY KEY,");
createArtifactInstancesTableTemplate.append("case_id integer NOT NULL,");
createArtifactInstancesTableTemplate.append("data_source_id integer NOT NULL,");
createArtifactInstancesTableTemplate.append("value text NOT NULL,");
createArtifactInstancesTableTemplate.append("file_path text NOT NULL,");
createArtifactInstancesTableTemplate.append("known_status integer NOT NULL,");
createArtifactInstancesTableTemplate.append("comment text,");
createArtifactInstancesTableTemplate.append("CONSTRAINT %s_multi_unique_ UNIQUE (data_source_id, value, file_path),");
createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,");
createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL");
createArtifactInstancesTableTemplate.append(")");
return createArtifactInstancesTableTemplate.toString();
}
/**
* Get the template for creating an index on the case_id column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
*
* @return a String which is a template for adding an index to the case_id
* column of a _instances table
*/
static String getAddCaseIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)";
}
/**
* Get the template for creating an index on the data_source_id column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
*
* @return a String which is a template for adding an index to the
* data_source_id column of a _instances table
*/
static String getAddDataSourceIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
}
/**
* Get the template for creating an index on the value column of an instance
* table. %s will exist in the template where the name of the new table will
* be addedd.
*
* @return a String which is a template for adding an index to the value
* column of a _instances table
*/
static String getAddValueIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
}
/**
* Get the template for creating an index on the known_status column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
*
* @return a String which is a template for adding an index to the
* known_status column of a _instances table
*/
static String getAddKnownStatusIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
}
public boolean insertDefaultDatabaseContent() { public boolean insertDefaultDatabaseContent() {
Connection conn = getEphemeralConnection(false); Connection conn = getEphemeralConnection(false);
if (null == conn) { if (null == conn) {

View File

@ -36,7 +36,8 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil;
/** /**
* Settings for the sqlite implementation of the Central Repository database * Settings for the sqlite implementation of the Central Repository database
* *
* NOTE: This is public scope because the options panel calls it directly to set/get * NOTE: This is public scope because the options panel calls it directly to
* set/get
*/ */
public final class SqliteEamDbSettings { public final class SqliteEamDbSettings {
@ -151,6 +152,7 @@ public final class SqliteEamDbSettings {
/** /**
* Delete the database * Delete the database
*
* @return * @return
*/ */
public boolean deleteDatabase() { public boolean deleteDatabase() {
@ -333,26 +335,13 @@ public final class SqliteEamDbSettings {
createCorrelationTypesTable.append("CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)"); createCorrelationTypesTable.append("CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)");
createCorrelationTypesTable.append(")"); createCorrelationTypesTable.append(")");
// Each "%s" will be replaced with the relevant TYPE_instances table name. String createArtifactInstancesTableTemplate = getCreateArtifactInstancesTableTemplate();
StringBuilder createArtifactInstancesTableTemplate = new StringBuilder();
createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
createArtifactInstancesTableTemplate.append("id integer primary key autoincrement NOT NULL,");
createArtifactInstancesTableTemplate.append("case_id integer NOT NULL,");
createArtifactInstancesTableTemplate.append("data_source_id integer NOT NULL,");
createArtifactInstancesTableTemplate.append("value text NOT NULL,");
createArtifactInstancesTableTemplate.append("file_path text NOT NULL,");
createArtifactInstancesTableTemplate.append("known_status integer NOT NULL,");
createArtifactInstancesTableTemplate.append("comment text,");
createArtifactInstancesTableTemplate.append("CONSTRAINT %s_multi_unique UNIQUE(data_source_id, value, file_path) ON CONFLICT IGNORE,");
createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,");
createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL");
createArtifactInstancesTableTemplate.append(")");
// Each "%s" will be replaced with the relevant TYPE_instances table name. String instancesIdx1 = getAddCaseIdIndexTemplate();
String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)"; String instancesIdx2 = getAddDataSourceIdIndexTemplate();
String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)"; String instancesIdx3 = getAddValueIndexTemplate();
String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)"; String instancesIdx4 = getAddKnownStatusIndexTemplate();
StringBuilder createDbInfoTable = new StringBuilder(); StringBuilder createDbInfoTable = new StringBuilder();
createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info ("); createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info (");
@ -402,7 +391,7 @@ public final class SqliteEamDbSettings {
reference_type_dbname = EamDbUtil.correlationTypeToReferenceTableName(type); reference_type_dbname = EamDbUtil.correlationTypeToReferenceTableName(type);
instance_type_dbname = EamDbUtil.correlationTypeToInstanceTableName(type); instance_type_dbname = EamDbUtil.correlationTypeToInstanceTableName(type);
stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), instance_type_dbname, instance_type_dbname)); stmt.execute(String.format(createArtifactInstancesTableTemplate, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesIdx1, instance_type_dbname, instance_type_dbname)); stmt.execute(String.format(instancesIdx1, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesIdx2, instance_type_dbname, instance_type_dbname)); stmt.execute(String.format(instancesIdx2, instance_type_dbname, instance_type_dbname));
stmt.execute(String.format(instancesIdx3, instance_type_dbname, instance_type_dbname)); stmt.execute(String.format(instancesIdx3, instance_type_dbname, instance_type_dbname));
@ -427,6 +416,83 @@ public final class SqliteEamDbSettings {
return true; return true;
} }
/**
* Get the template String for creating a new _instances table in a Sqlite
* central repository. %s will exist in the template where the name of the
* new table will be addedd.
*
* @return a String which is a template for cretating a new _instances table
*/
static String getCreateArtifactInstancesTableTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
StringBuilder createArtifactInstancesTableTemplate = new StringBuilder();
createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
createArtifactInstancesTableTemplate.append("id integer primary key autoincrement NOT NULL,");
createArtifactInstancesTableTemplate.append("case_id integer NOT NULL,");
createArtifactInstancesTableTemplate.append("data_source_id integer NOT NULL,");
createArtifactInstancesTableTemplate.append("value text NOT NULL,");
createArtifactInstancesTableTemplate.append("file_path text NOT NULL,");
createArtifactInstancesTableTemplate.append("known_status integer NOT NULL,");
createArtifactInstancesTableTemplate.append("comment text,");
createArtifactInstancesTableTemplate.append("CONSTRAINT %s_multi_unique UNIQUE(data_source_id, value, file_path) ON CONFLICT IGNORE,");
createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,");
createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL");
createArtifactInstancesTableTemplate.append(")");
return createArtifactInstancesTableTemplate.toString();
}
/**
* Get the template for creating an index on the case_id column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
*
* @return a String which is a template for adding an index to the case_id
* column of a _instances table
*/
static String getAddCaseIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)";
}
/**
* Get the template for creating an index on the data_source_id column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
*
* @return a String which is a template for adding an index to the
* data_source_id column of a _instances table
*/
static String getAddDataSourceIdIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
}
/**
* Get the template for creating an index on the value column of an instance
* table. %s will exist in the template where the name of the new table will
* be addedd.
*
* @return a String which is a template for adding an index to the value
* column of a _instances table
*/
static String getAddValueIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
}
/**
* Get the template for creating an index on the known_status column of an
* instance table. %s will exist in the template where the name of the new
* table will be addedd.
*
* @return a String which is a template for adding an index to the
* known_status column of a _instances table
*/
static String getAddKnownStatusIndexTemplate() {
// Each "%s" will be replaced with the relevant TYPE_instances table name.
return "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
}
public boolean insertDefaultDatabaseContent() { public boolean insertDefaultDatabaseContent() {
Connection conn = getEphemeralConnection(); Connection conn = getEphemeralConnection();
if (null == conn) { if (null == conn) {
@ -490,8 +556,6 @@ public final class SqliteEamDbSettings {
} }
} }
/** /**
* @return the dbDirectory * @return the dbDirectory
*/ */

View File

@ -183,7 +183,10 @@ public class IngestEventsListener {
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
if (getCeModuleInstanceCount() > 0) { //if ingest is running we want there to check if there is a Correlation Engine module running
//sometimes artifacts are generated by DSPs or other sources while ingest is not running
//in these cases we still want to create correlation attributes for those artifacts when appropriate
if (!IngestManager.getInstance().isIngestRunning() || getCeModuleInstanceCount() > 0) {
EamDb dbManager; EamDb dbManager;
try { try {
dbManager = EamDb.getInstance(); dbManager = EamDb.getInstance();
@ -193,7 +196,9 @@ public class IngestEventsListener {
} }
switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) { switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) {
case DATA_ADDED: { case DATA_ADDED: {
jobProcessingExecutor.submit(new DataAddedTask(dbManager, evt, isFlagNotableItems())); //if ingest isn't running create the interesting items otherwise use the ingest module setting to determine if we create interesting items
boolean flagNotable = !IngestManager.getInstance().isIngestRunning() || isFlagNotableItems();
jobProcessingExecutor.submit(new DataAddedTask(dbManager, evt, flagNotable));
break; break;
} }
} }

View File

@ -71,7 +71,6 @@ final class IngestModule implements FileIngestModule {
private CorrelationDataSource eamDataSource; private CorrelationDataSource eamDataSource;
private Blackboard blackboard; private Blackboard blackboard;
private CorrelationAttributeInstance.Type filesType; private CorrelationAttributeInstance.Type filesType;
private final boolean flagTaggedNotableItems; private final boolean flagTaggedNotableItems;
/** /**

View File

@ -34,7 +34,7 @@ AddNewOrganizationDialog.bnOK.text=OK
AddNewOrganizationDialog.tfName.tooltip=POC Name AddNewOrganizationDialog.tfName.tooltip=POC Name
ManageTagsDialog.okButton.text=OK ManageTagsDialog.okButton.text=OK
ManageTagsDialog.cancelButton.text=Cancel ManageTagsDialog.cancelButton.text=Cancel
ManageArtifactTypesDialog.taInstructionsMsg.text=Enable one or more correlation properties to use for correlation during ingest. Note, these properties are global and impact all users of the central repository. ManageArtifactTypesDialog.taInstructionsMsg.text=Enable one or more correlation properties to use for correlation during ingest. Note, these properties are global and impact all users of the Central Repository.
EamSqliteSettingsDialog.bnOk.text=OK EamSqliteSettingsDialog.bnOk.text=OK
EamPostgresSettingsDialog.bnSave.text=Save EamPostgresSettingsDialog.bnSave.text=Save
EamDbSettingsDialog.bnDatabasePathFileOpen.text=Browse... EamDbSettingsDialog.bnDatabasePathFileOpen.text=Browse...
@ -58,11 +58,10 @@ ManageCorrelationPropertiesDialog.okButton.text=OK
GlobalSettingsPanel.bnManageProperties.text=Manage Correlation Properties GlobalSettingsPanel.bnManageProperties.text=Manage Correlation Properties
EamDbSettingsDialog.lbDatabaseDesc.text=Database File: EamDbSettingsDialog.lbDatabaseDesc.text=Database File:
EamDbSettingsDialog.lbFullDbPath.text= EamDbSettingsDialog.lbFullDbPath.text=
GlobalSettingsPanel.cbUseCentralRepo.text=Use a central repository GlobalSettingsPanel.cbUseCentralRepo.text=Use a Central Repository
GlobalSettingsPanel.correlationPropertiesTextArea.text=Choose which file and result properties to store in the central repository for later correlation.\n GlobalSettingsPanel.organizationTextArea.text=Organization information can be tracked in the Central Repository.
GlobalSettingsPanel.organizationTextArea.text=Organization information can be tracked in the central repository.
GlobalSettingsPanel.manageOrganizationButton.text=Manage Organizations GlobalSettingsPanel.manageOrganizationButton.text=Manage Organizations
GlobalSettingsPanel.lbCentralRepository.text=A central repository allows you to correlate files and results between cases. GlobalSettingsPanel.lbCentralRepository.text=A Central Repository allows you to correlate files and results between cases.
GlobalSettingsPanel.pnCorrelationProperties.border.title=Correlation Properties GlobalSettingsPanel.pnCorrelationProperties.border.title=Correlation Properties
GlobalSettingsPanel.organizationPanel.border.title=Organizations GlobalSettingsPanel.organizationPanel.border.title=Organizations
GlobalSettingsPanel.casesPanel.border.title=Case Details GlobalSettingsPanel.casesPanel.border.title=Case Details
@ -74,8 +73,9 @@ ShowCasesDialog.caseDetailsTable.toolTipText=Click column name to sort. Right-cl
ShowCasesDialog.title=Case Details ShowCasesDialog.title=Case Details
GlobalSettingsPanel.Case\ Details.AccessibleContext.accessibleName=Cases Details GlobalSettingsPanel.Case\ Details.AccessibleContext.accessibleName=Cases Details
ShowCasesDialog.caseDetailsTable.AccessibleContext.accessibleDescription=Click column name to sort. ShowCasesDialog.caseDetailsTable.AccessibleContext.accessibleDescription=Click column name to sort.
GlobalSettingsPanel.casesTextArea.text=Display table that lists central repository case details. GlobalSettingsPanel.casesTextArea.text=Display table that lists Central Repository case details.
GlobalSettingsPanel.ingestRunningWarningLabel.text=Cannot make changes to central repository settings when ingest is running! GlobalSettingsPanel.ingestRunningWarningLabel.text=Cannot make changes to Central Repository settings when ingest is running!
GlobalSettingsPanel.correlationPropertiesTextArea.text=Choose which file and result properties to store in the Central Repository for later correlation.\n
ManageCasesDialog.examinerPhoneLabel.text=Examiner Phone: ManageCasesDialog.examinerPhoneLabel.text=Examiner Phone:
ManageCasesDialog.examinerNameLabel.text=Examiner Name: ManageCasesDialog.examinerNameLabel.text=Examiner Name:
ManageCasesDialog.examinerEmailLabel.text=Examiner Email: ManageCasesDialog.examinerEmailLabel.text=Examiner Email:

View File

@ -102,7 +102,7 @@ public class EamDbSettingsDialog extends JDialog {
@Override @Override
public String getDescription() { public String getDescription() {
return "Directories and central repository databases"; return "Directories and Central Repository databases";
} }
}); });
cbDatabaseType.setSelectedItem(selectedPlatform); cbDatabaseType.setSelectedItem(selectedPlatform);

View File

@ -57,7 +57,7 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="lbCentralRepository" pref="1022" max="32767" attributes="0"/> <Component id="lbCentralRepository" max="32767" attributes="0"/>
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="pnDatabaseConfiguration" alignment="0" max="32767" attributes="0"/> <Component id="pnDatabaseConfiguration" alignment="0" max="32767" attributes="0"/>
@ -67,7 +67,7 @@
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Component id="cbUseCentralRepo" min="-2" pref="162" max="-2" attributes="0"/> <Component id="cbUseCentralRepo" min="-2" pref="162" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="ingestRunningWarningLabel" max="32767" attributes="0"/> <Component id="ingestRunningWarningLabel" pref="844" max="32767" attributes="0"/>
</Group> </Group>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
@ -89,13 +89,13 @@
</Group> </Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="pnDatabaseConfiguration" min="-2" max="-2" attributes="0"/> <Component id="pnDatabaseConfiguration" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="pnCorrelationProperties" min="-2" max="-2" attributes="0"/> <Component id="pnCorrelationProperties" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="organizationPanel" min="-2" max="-2" attributes="0"/> <Component id="organizationPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="casesPanel" min="-2" max="-2" attributes="0"/> <Component id="casesPanel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="tbOops" min="-2" max="-2" attributes="0"/> <Component id="tbOops" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
@ -242,14 +242,14 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="correlationPropertiesScrollPane" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="bnManageTypes" min="-2" max="-2" attributes="0"/> <Component id="bnManageTypes" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group> </Group>
<Component id="correlationPropertiesScrollPane" max="32767" attributes="0"/>
</Group> </Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
</Group> </Group>
@ -258,8 +258,7 @@
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<EmptySpace min="-2" pref="7" max="-2" attributes="0"/> <Component id="correlationPropertiesScrollPane" pref="32" max="32767" attributes="0"/>
<Component id="correlationPropertiesScrollPane" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="bnManageTypes" min="-2" max="-2" attributes="0"/> <Component id="bnManageTypes" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/> <EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
@ -301,7 +300,7 @@
<Font name="Tahoma" size="11" style="0"/> <Font name="Tahoma" size="11" style="0"/>
</Property> </Property>
<Property name="lineWrap" type="boolean" value="true"/> <Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="2"/> <Property name="rows" type="int" value="1"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <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.correlationPropertiesTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties" key="GlobalSettingsPanel.correlationPropertiesTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
@ -334,7 +333,7 @@
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="organizationScrollPane" pref="992" max="32767" attributes="0"/> <Component id="organizationScrollPane" max="32767" attributes="0"/>
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Component id="manageOrganizationButton" min="-2" max="-2" attributes="0"/> <Component id="manageOrganizationButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>

View File

@ -222,7 +222,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
correlationPropertiesTextArea.setColumns(20); correlationPropertiesTextArea.setColumns(20);
correlationPropertiesTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N correlationPropertiesTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
correlationPropertiesTextArea.setLineWrap(true); correlationPropertiesTextArea.setLineWrap(true);
correlationPropertiesTextArea.setRows(2); correlationPropertiesTextArea.setRows(1);
correlationPropertiesTextArea.setText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.correlationPropertiesTextArea.text")); // NOI18N correlationPropertiesTextArea.setText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.correlationPropertiesTextArea.text")); // NOI18N
correlationPropertiesTextArea.setToolTipText(""); correlationPropertiesTextArea.setToolTipText("");
correlationPropertiesTextArea.setWrapStyleWord(true); correlationPropertiesTextArea.setWrapStyleWord(true);
@ -236,17 +236,16 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
.addGroup(pnCorrelationPropertiesLayout.createSequentialGroup() .addGroup(pnCorrelationPropertiesLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(pnCorrelationPropertiesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(pnCorrelationPropertiesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(correlationPropertiesScrollPane)
.addGroup(pnCorrelationPropertiesLayout.createSequentialGroup() .addGroup(pnCorrelationPropertiesLayout.createSequentialGroup()
.addComponent(bnManageTypes) .addComponent(bnManageTypes)
.addGap(0, 0, Short.MAX_VALUE))) .addGap(0, 0, Short.MAX_VALUE))
.addComponent(correlationPropertiesScrollPane))
.addContainerGap()) .addContainerGap())
); );
pnCorrelationPropertiesLayout.setVerticalGroup( pnCorrelationPropertiesLayout.setVerticalGroup(
pnCorrelationPropertiesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) pnCorrelationPropertiesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnCorrelationPropertiesLayout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnCorrelationPropertiesLayout.createSequentialGroup()
.addGap(7, 7, 7) .addComponent(correlationPropertiesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 32, Short.MAX_VALUE)
.addComponent(correlationPropertiesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnManageTypes) .addComponent(bnManageTypes)
.addGap(8, 8, 8)) .addGap(8, 8, 8))
@ -281,7 +280,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
.addGroup(organizationPanelLayout.createSequentialGroup() .addGroup(organizationPanelLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(organizationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(organizationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(organizationScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 992, Short.MAX_VALUE) .addComponent(organizationScrollPane)
.addGroup(organizationPanelLayout.createSequentialGroup() .addGroup(organizationPanelLayout.createSequentialGroup()
.addComponent(manageOrganizationButton) .addComponent(manageOrganizationButton)
.addGap(0, 0, Short.MAX_VALUE))) .addGap(0, 0, Short.MAX_VALUE)))
@ -356,7 +355,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
jPanel1.setLayout(jPanel1Layout); jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup( jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbCentralRepository, javax.swing.GroupLayout.DEFAULT_SIZE, 1022, Short.MAX_VALUE) .addComponent(lbCentralRepository, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
@ -366,7 +365,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(cbUseCentralRepo, javax.swing.GroupLayout.PREFERRED_SIZE, 162, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(cbUseCentralRepo, javax.swing.GroupLayout.PREFERRED_SIZE, 162, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(ingestRunningWarningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(ingestRunningWarningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 844, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, 974, javax.swing.GroupLayout.PREFERRED_SIZE))) .addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, 974, javax.swing.GroupLayout.PREFERRED_SIZE)))
@ -382,13 +381,13 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
.addComponent(ingestRunningWarningLabel)) .addComponent(ingestRunningWarningLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGap(0, 0, 0)
.addComponent(pnCorrelationProperties, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(pnCorrelationProperties, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGap(0, 0, 0)
.addComponent(organizationPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(organizationPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGap(0, 0, 0)
.addComponent(casesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(casesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGap(0, 0, 0)
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap()) .addContainerGap())
); );

View File

@ -74,7 +74,7 @@ class PListViewer extends javax.swing.JPanel implements FileTypeViewer, Explorer
private final Outline outline; private final Outline outline;
private ExplorerManager explorerManager; private ExplorerManager explorerManager;
private NSDictionary rootDict; private NSObject rootDict;
/** /**
* Creates new form PListViewer * Creates new form PListViewer
@ -415,24 +415,37 @@ class PListViewer extends javax.swing.JPanel implements FileTypeViewer, Explorer
} }
/** /**
* Parses given binary stream and extracts Plist key/value * Parses given binary stream and extracts Plist key/value.
* *
* @param plistbytes * @param plistbytes The byte array containing the Plist data.
* *
* @return list of PropKeyValue * @return list of PropKeyValue
*/ */
private List<PropKeyValue> parsePList(final byte[] plistbytes) throws IOException, PropertyListFormatException, ParseException, ParserConfigurationException, SAXException { private List<PropKeyValue> parsePList(final byte[] plistbytes) throws IOException, PropertyListFormatException, ParseException, ParserConfigurationException, SAXException {
final List<PropKeyValue> plist = new ArrayList<>(); final List<PropKeyValue> plist = new ArrayList<>();
rootDict = (NSDictionary) PropertyListParser.parse(plistbytes); rootDict = PropertyListParser.parse(plistbytes);
final String[] keys = rootDict.allKeys(); /*
for (final String key : keys) { * Parse the data if the root is an NSArray or NSDictionary. Anything
final PropKeyValue pkv = parseProperty(key, rootDict.objectForKey(key)); * else is unexpected and will be ignored.
*/
if (rootDict instanceof NSArray) {
for (int i=0; i < ((NSArray)rootDict).count(); i++) {
final PropKeyValue pkv = parseProperty("", ((NSArray)rootDict).objectAtIndex(i));
if (null != pkv) { if (null != pkv) {
plist.add(pkv); plist.add(pkv);
} }
} }
} else if (rootDict instanceof NSDictionary) {
final String[] keys = ((NSDictionary)rootDict).allKeys();
for (final String key : keys) {
final PropKeyValue pkv = parseProperty(key, ((NSDictionary)rootDict).objectForKey(key));
if (null != pkv) {
plist.add(pkv);
}
}
}
return plist; return plist;
} }

View File

@ -487,7 +487,8 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID())
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()) || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID())
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID()) || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID())
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID())) { || (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_METADATA_EXIF.getTypeID())
|| (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID())) {
return 3; return 3;
} else { } else {
return 6; return 6;

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2012-2015 Basis Technology Corp. * Copyright 2012-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -18,14 +18,22 @@
*/ */
package org.sleuthkit.autopsy.coreutils; package org.sleuthkit.autopsy.coreutils;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.StringTokenizer;
public class NetworkUtils { public class NetworkUtils {
private NetworkUtils() {
}
/** /**
* Set the host name variable. Sometimes the network can be finicky, so the * Set the host name variable. Sometimes the network can be finicky, so the
* answer returned by getHostName() could throw an exception or be null. * answer returned by getHostName() could throw an exception or be null.
* Have it read the environment variable if getHostName() is unsuccessful. * Have it read the environment variable if getHostName() is unsuccessful.
*
* @return the local host name
*/ */
public static String getLocalHostName() { public static String getLocalHostName() {
String hostName = ""; String hostName = "";
@ -41,4 +49,78 @@ public class NetworkUtils {
} }
return hostName; return hostName;
} }
/**
* Attempt to manually extract the domain from a URL.
*
* @param url
* @return empty string if no domain could be found
*/
private static String getBaseDomain(String url) {
String host = null;
//strip protocol
String cleanUrl = url.replaceFirst(".*:\\/\\/", "");
//strip after slashes
String dirToks[] = cleanUrl.split("\\/");
if (dirToks.length > 0) {
host = dirToks[0];
} else {
host = cleanUrl;
}
//get the domain part from host (last 2)
StringTokenizer tok = new StringTokenizer(host, ".");
StringBuilder hostB = new StringBuilder();
int toks = tok.countTokens();
for (int count = 0; count < toks; ++count) {
String part = tok.nextToken();
int diff = toks - count;
if (diff < 3) {
hostB.append(part);
}
if (diff == 2) {
hostB.append(".");
}
}
String base = hostB.toString();
// verify there are no special characters in there
if (base.matches(".*[~`!@#$%^&\\*\\(\\)\\+={}\\[\\];:\\?<>,/ ].*")) {
return "";
}
return base;
}
/**
* Attempt to extract the domain from a URL.
* Will start by using the built-in URL class, and if that fails will
* try to extract it manually.
*
* @param urlString The URL to extract the domain from
* @return empty string if no domain name was found
*/
public static String extractDomain(String urlString) {
if (urlString == null) {
return "";
}
String result = "";
try {
URL url = new URL(urlString);
result = url.getHost();
} catch (MalformedURLException ex) {
//do not log if not a valid URL - we will try to extract it ourselves
}
//was not a valid URL, try a less picky method
if (result == null || result.trim().isEmpty()) {
return getBaseDomain(urlString);
}
return result;
}
} }

View File

@ -21,6 +21,8 @@ package org.sleuthkit.autopsy.coreutils;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.List; import java.util.List;
import java.util.SimpleTimeZone; import java.util.SimpleTimeZone;
@ -45,7 +47,7 @@ public class TimeZoneUtils {
java.util.TimeZone zone = java.util.TimeZone.getTimeZone(timeZoneId); java.util.TimeZone zone = java.util.TimeZone.getTimeZone(timeZoneId);
int offset = zone.getRawOffset() / 1000; int offset = zone.getRawOffset() / 1000;
int hour = offset / 3600; int hour = offset / 3600;
int min = (offset % 3600) / 60; int min = Math.abs((offset % 3600) / 60);
DateFormat dfm = new SimpleDateFormat("z"); DateFormat dfm = new SimpleDateFormat("z");
dfm.setTimeZone(zone); dfm.setTimeZone(zone);
@ -74,7 +76,7 @@ public class TimeZoneUtils {
public static String createTimeZoneString(TimeZone timeZone) { public static String createTimeZoneString(TimeZone timeZone) {
int offset = timeZone.getRawOffset() / 1000; int offset = timeZone.getRawOffset() / 1000;
int hour = offset / 3600; int hour = offset / 3600;
int minutes = (offset % 3600) / 60; int minutes = Math.abs((offset % 3600) / 60);
return String.format("(GMT%+d:%02d) %s", hour, minutes, timeZone.getID()); //NON-NLS return String.format("(GMT%+d:%02d) %s", hour, minutes, timeZone.getID()); //NON-NLS
} }
@ -83,9 +85,11 @@ public class TimeZoneUtils {
* Generates a list of time zones. * Generates a list of time zones.
*/ */
public static List<String> createTimeZoneList() { public static List<String> createTimeZoneList() {
List<String> timeZoneList = new ArrayList<>(); /*
* Create a list of time zones.
*/
List<TimeZone> timeZoneList = new ArrayList<>();
// load and add all timezone
String[] ids = SimpleTimeZone.getAvailableIDs(); String[] ids = SimpleTimeZone.getAvailableIDs();
for (String id : ids) { for (String id : ids) {
/* /*
@ -97,10 +101,36 @@ public class TimeZoneUtils {
* if(hasDaylight){ result = result + second; } * if(hasDaylight){ result = result + second; }
* timeZoneComboBox.addItem(item + " (" + result + ")"); * timeZoneComboBox.addItem(item + " (" + result + ")");
*/ */
timeZoneList.add(createTimeZoneString(TimeZone.getTimeZone(id))); timeZoneList.add(TimeZone.getTimeZone(id));
} }
return timeZoneList; /*
* Sort the list of time zones first by offset, then by ID.
*/
Collections.sort(timeZoneList, new Comparator<TimeZone>(){
@Override
public int compare(TimeZone o1, TimeZone o2){
int offsetDelta = Integer.compare(o1.getRawOffset(), o2.getRawOffset());
if (offsetDelta == 0) {
return o1.getID().compareToIgnoreCase(o2.getID());
}
return offsetDelta;
}
});
/*
* Create a list of Strings encompassing both the GMT offset and the
* time zone ID.
*/
List<String> outputList = new ArrayList<>();
for (TimeZone timeZone : timeZoneList) {
outputList.add(createTimeZoneString(timeZone));
}
return outputList;
} }
/** /**

View File

@ -156,6 +156,8 @@ public class ExtractedContent implements AutopsyVisitableItem {
return filePath + "drive_network.png"; //NON-NLS return filePath + "drive_network.png"; //NON-NLS
} else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_FACE_DETECTED.getTypeID()) { } else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_FACE_DETECTED.getTypeID()) {
return filePath + "face.png"; //NON-NLS return filePath + "face.png"; //NON-NLS
} else if (typeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_WIFI_NETWORK.getTypeID()) {
return filePath + "network-wifi.png"; //NON-NLS
} }
return filePath + "artifact-icon.png"; //NON-NLS return filePath + "artifact-icon.png"; //NON-NLS
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 B

View File

@ -21,9 +21,6 @@ package org.sleuthkit.autopsy.modules.embeddedfileextractor;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -166,11 +163,12 @@ class SevenZipExtractor {
* *
* @param archiveFile the AbstractFile for the parent archive which * @param archiveFile the AbstractFile for the parent archive which
* which we are checking * which we are checking
* @param inArchive The SevenZip archive currently open for extraction * @param inArchive The SevenZip archive currently open for
* extraction
* *
* @param inArchiveItemIndex Index of item inside the SevenZip archive. Each * @param inArchiveItemIndex Index of item inside the SevenZip archive. Each
* file inside an archive is associated with a unique * file inside an archive is associated with a
* integer * unique integer
* *
* @param depthMap a concurrent hashmap which keeps track of the * @param depthMap a concurrent hashmap which keeps track of the
* depth of all nested archives, key of objectID * depth of all nested archives, key of objectID
@ -797,138 +795,55 @@ class SevenZipExtractor {
} }
/** /**
* Stream used to unpack the archive to local file * UnpackStream used by the SevenZipBindings to do archive extraction. A memory
* leak exists in the SevenZip library that will not let go of the streams until
* the entire archive extraction is complete. Instead of creating a new UnpackStream
* for every file in the archive, instead we just rebase our EncodedFileOutputStream pointer
* for every new file.
*/ */
private abstract static class UnpackStream implements ISequentialOutStream { private final static class UnpackStream implements ISequentialOutStream {
private OutputStream output; private EncodedFileOutputStream output;
private String localAbsPath; private String localAbsPath;
private int bytesWritten;
UnpackStream(String localAbsPath) { UnpackStream(String localAbsPath) throws IOException {
this.output = new EncodedFileOutputStream(new FileOutputStream(localAbsPath), TskData.EncodingType.XOR1);
this.localAbsPath = localAbsPath; this.localAbsPath = localAbsPath;
try { this.bytesWritten = 0;
output = new EncodedFileOutputStream(new FileOutputStream(localAbsPath), TskData.EncodingType.XOR1);
} catch (IOException ex) {
logger.log(Level.SEVERE, "Error writing extracted file: " + localAbsPath, ex); //NON-NLS
} }
public void setNewOutputStream(String localAbsPath) throws IOException {
this.output.close();
this.output = new EncodedFileOutputStream(new FileOutputStream(localAbsPath), TskData.EncodingType.XOR1);
this.localAbsPath = localAbsPath;
this.bytesWritten = 0;
} }
public abstract long getSize(); public int getSize() {
return bytesWritten;
OutputStream getOutput() {
return output;
}
String getLocalAbsPath() {
return localAbsPath;
}
public void close() {
if (output != null) {
try {
output.flush();
output.close();
output = null;
} catch (IOException e) {
logger.log(Level.SEVERE, "Error closing unpack stream for file: {0}", localAbsPath); //NON-NLS
}
}
}
}
/**
* Stream used to unpack the archive of unknown size to local file
*/
private static class UnknownSizeUnpackStream extends UnpackStream {
private long freeDiskSpace;
private boolean outOfSpace = false;
private long bytesWritten = 0;
UnknownSizeUnpackStream(String localAbsPath, long freeDiskSpace) {
super(localAbsPath);
this.freeDiskSpace = freeDiskSpace;
}
@Override
public long getSize() {
return this.bytesWritten;
} }
@Override @Override
public int write(byte[] bytes) throws SevenZipException { public int write(byte[] bytes) throws SevenZipException {
try { try {
// If the content size is unknown, cautiously write to disk. output.write(bytes);
// Write only if byte array is less than 80% of the current
// free disk space.
if (freeDiskSpace == IngestMonitor.DISK_FREE_SPACE_UNKNOWN || bytes.length < 0.8 * freeDiskSpace) {
getOutput().write(bytes);
// NOTE: this method is called multiple times for a
// single extractSlow() call. Update bytesWritten and
// freeDiskSpace after every write operation.
this.bytesWritten += bytes.length; this.bytesWritten += bytes.length;
this.freeDiskSpace -= bytes.length;
} else {
this.outOfSpace = true;
logger.log(Level.INFO, NbBundle.getMessage(
SevenZipExtractor.class,
"EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.noSpace.msg"));
throw new SevenZipException(
NbBundle.getMessage(SevenZipExtractor.class, "EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.noSpace.msg"));
}
} catch (IOException ex) { } catch (IOException ex) {
throw new SevenZipException( throw new SevenZipException(
NbBundle.getMessage(SevenZipExtractor.class, "EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.exception.msg", NbBundle.getMessage(SevenZipExtractor.class,
getLocalAbsPath()), ex); "EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.exception.msg",
localAbsPath), ex);
} }
return bytes.length; return bytes.length;
} }
@Override public void close() throws IOException {
public void close() { try(EncodedFileOutputStream out = output) {
if (getOutput() != null) { out.flush();
try {
getOutput().flush();
getOutput().close();
if (this.outOfSpace) {
Files.delete(Paths.get(getLocalAbsPath()));
}
} catch (IOException e) {
logger.log(Level.SEVERE, "Error closing unpack stream for file: {0}", getLocalAbsPath()); //NON-NLS
}
}
} }
} }
/**
* Stream used to unpack the archive of known size to local file
*/
private static class KnownSizeUnpackStream extends UnpackStream {
private long size;
KnownSizeUnpackStream(String localAbsPath, long size) {
super(localAbsPath);
this.size = size;
}
@Override
public long getSize() {
return this.size;
}
@Override
public int write(byte[] bytes) throws SevenZipException {
try {
getOutput().write(bytes);
} catch (IOException ex) {
throw new SevenZipException(
NbBundle.getMessage(SevenZipExtractor.class, "EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.exception.msg",
getLocalAbsPath()), ex);
}
return bytes.length;
}
} }
/** /**
@ -975,7 +890,6 @@ class SevenZipExtractor {
private final ProgressHandle progressHandle; private final ProgressHandle progressHandle;
private int inArchiveItemIndex; private int inArchiveItemIndex;
private final long freeDiskSpace;
private long createTimeInSeconds; private long createTimeInSeconds;
private long modTimeInSeconds; private long modTimeInSeconds;
@ -992,7 +906,6 @@ class SevenZipExtractor {
String password, long freeDiskSpace) { String password, long freeDiskSpace) {
this.inArchive = inArchive; this.inArchive = inArchive;
this.freeDiskSpace = freeDiskSpace;
this.progressHandle = progressHandle; this.progressHandle = progressHandle;
this.archiveFile = archiveFile; this.archiveFile = archiveFile;
this.archiveDetailsMap = archiveDetailsMap; this.archiveDetailsMap = archiveDetailsMap;
@ -1000,15 +913,17 @@ class SevenZipExtractor {
} }
/** /**
* Get stream is called by the internal framework as it traverses * Get stream is called by the internal framework as it traverses the
* the archive structure. The ISequentialOutStream is where the * archive structure. The ISequentialOutStream is where the archive file
* archive file contents will be expanded and written to the local disk. * contents will be expanded and written to the local disk.
* *
* Skips folders, as there is nothing to extract. * Skips folders, as there is nothing to extract.
* *
* @param inArchiveItemIndex current location of the * @param inArchiveItemIndex current location of the
* @param mode Will always be EXTRACT * @param mode Will always be EXTRACT
*
* @return * @return
*
* @throws SevenZipException * @throws SevenZipException
*/ */
@Override @Override
@ -1023,17 +938,24 @@ class SevenZipExtractor {
return null; return null;
} }
final Long archiveItemSize = (Long) inArchive.getProperty(
inArchiveItemIndex, PropID.SIZE);
final String localAbsPath = archiveDetailsMap.get( final String localAbsPath = archiveDetailsMap.get(
inArchiveItemIndex).getLocalAbsPath(); inArchiveItemIndex).getLocalAbsPath();
if (archiveItemSize != null) { //If the Unpackstream has been allocated, then set the Outputstream
unpackStream = new SevenZipExtractor.KnownSizeUnpackStream( //to another file rather than creating a new unpack stream. The 7Zip
localAbsPath, archiveItemSize); //binding has a memory leak, so creating new unpack streams will not be
//dereferenced. As a fix, we create one UnpackStream, and mutate its state,
//so that there only exists one 8192 byte buffer in memory per archive.
try {
if (unpackStream != null) {
unpackStream.setNewOutputStream(localAbsPath);
} else { } else {
unpackStream = new SevenZipExtractor.UnknownSizeUnpackStream( unpackStream = new UnpackStream(localAbsPath);
localAbsPath, freeDiskSpace); }
} catch (IOException ex) {
logger.log(Level.WARNING, String.format("Error opening or setting new stream " //NON-NLS
+ "for archive file at %s", localAbsPath), ex.getMessage()); //NON-NLS
return null;
} }
return unpackStream; return unpackStream;
@ -1044,6 +966,7 @@ class SevenZipExtractor {
* Called after getStream. * Called after getStream.
* *
* @param mode Will always be EXTRACT. * @param mode Will always be EXTRACT.
*
* @throws SevenZipException * @throws SevenZipException
*/ */
@Override @Override
@ -1103,7 +1026,11 @@ class SevenZipExtractor {
!(Boolean) inArchive.getProperty(inArchiveItemIndex, PropID.IS_FOLDER), !(Boolean) inArchive.getProperty(inArchiveItemIndex, PropID.IS_FOLDER),
0L, createTimeInSeconds, accessTimeInSeconds, modTimeInSeconds, localRelPath); 0L, createTimeInSeconds, accessTimeInSeconds, modTimeInSeconds, localRelPath);
try {
unpackStream.close(); unpackStream.close();
} catch (IOException e) {
logger.log(Level.WARNING, "Error closing unpack stream for file: {0}", localAbsPath); //NON-NLS
}
} }
@Override @Override
@ -1214,9 +1141,9 @@ class SevenZipExtractor {
*/ */
List<AbstractFile> getRootFileObjects() { List<AbstractFile> getRootFileObjects() {
List<AbstractFile> ret = new ArrayList<>(); List<AbstractFile> ret = new ArrayList<>();
for (UnpackedNode child : rootNode.getChildren()) { rootNode.getChildren().forEach((child) -> {
ret.add(child.getFile()); ret.add(child.getFile());
} });
return ret; return ret;
} }
@ -1228,17 +1155,17 @@ class SevenZipExtractor {
*/ */
List<AbstractFile> getAllFileObjects() { List<AbstractFile> getAllFileObjects() {
List<AbstractFile> ret = new ArrayList<>(); List<AbstractFile> ret = new ArrayList<>();
for (UnpackedNode child : rootNode.getChildren()) { rootNode.getChildren().forEach((child) -> {
getAllFileObjectsRec(ret, child); getAllFileObjectsRec(ret, child);
} });
return ret; return ret;
} }
private void getAllFileObjectsRec(List<AbstractFile> list, UnpackedNode parent) { private void getAllFileObjectsRec(List<AbstractFile> list, UnpackedNode parent) {
list.add(parent.getFile()); list.add(parent.getFile());
for (UnpackedNode child : parent.getChildren()) { parent.getChildren().forEach((child) -> {
getAllFileObjectsRec(list, child); getAllFileObjectsRec(list, child);
} });
} }
/** /**

View File

@ -91,7 +91,7 @@ HashDbImportDatabaseDialog.errorMessage.failedToOpenHashDbMsg=Failed to open has
HashLookupModuleFactory.moduleName.text=Hash Lookup HashLookupModuleFactory.moduleName.text=Hash Lookup
HashLookupModuleFactory.moduleDescription.text=Identifies known and notable files using supplied hash sets, such as a standard NSRL hash set. HashLookupModuleFactory.moduleDescription.text=Identifies known and notable files using supplied hash sets, such as a standard NSRL hash set.
HashDbIngestModule.fileReadErrorMsg=Read Error\: {0} HashDbIngestModule.fileReadErrorMsg=Read Error\: {0}
HashDbIngestModule.calcHashValueErr=Error encountered while calculating the hash value for {0}. HashDbIngestModule.calcHashValueErr=Error encountered while calculating the hash value for {0} ({1}).
HashDbIngestModule.hashLookupErrorMsg=Hash Lookup Error\: {0} HashDbIngestModule.hashLookupErrorMsg=Hash Lookup Error\: {0}
HashDbIngestModule.settingKnownBadStateErr=Error encountered while setting notable state for {0}. HashDbIngestModule.settingKnownBadStateErr=Error encountered while setting notable state for {0}.
HashDbIngestModule.lookingUpKnownBadHashValueErr=Error encountered while looking up notable hash value for {0}. HashDbIngestModule.lookingUpKnownBadHashValueErr=Error encountered while looking up notable hash value for {0}.

View File

@ -229,7 +229,9 @@ public class HashDbIngestModule implements FileIngestModule {
services.postMessage(IngestMessage.createErrorMessage( services.postMessage(IngestMessage.createErrorMessage(
HashLookupModuleFactory.getModuleName(), HashLookupModuleFactory.getModuleName(),
NbBundle.getMessage(this.getClass(), "HashDbIngestModule.fileReadErrorMsg", name), NbBundle.getMessage(this.getClass(), "HashDbIngestModule.fileReadErrorMsg", name),
NbBundle.getMessage(this.getClass(), "HashDbIngestModule.calcHashValueErr", name))); NbBundle.getMessage(this.getClass(), "HashDbIngestModule.calcHashValueErr",
file.getParentPath() + file.getName(),
file.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)?"Allocated File" : "Deleted File")));
return ProcessResult.ERROR; return ProcessResult.ERROR;
} }
} }

View File

@ -471,7 +471,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
if (!this.nameTextField.getText().isEmpty()) { if (!this.nameTextField.getText().isEmpty()) {
if (this.nameRegexCheckbox.isSelected()) { if (this.nameRegexCheckbox.isSelected()) {
try { try {
Pattern pattern = Pattern.compile(this.nameTextField.getText()); Pattern pattern = Pattern.compile(this.nameTextField.getText(), Pattern.CASE_INSENSITIVE);
if (this.fullNameRadioButton.isSelected()) { if (this.fullNameRadioButton.isSelected()) {
condition = new FilesSet.Rule.FullNameCondition(pattern); condition = new FilesSet.Rule.FullNameCondition(pattern);
} else { } else {
@ -556,7 +556,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel {
if (!this.pathTextField.getText().isEmpty()) { if (!this.pathTextField.getText().isEmpty()) {
if (this.pathRegexCheckBox.isSelected()) { if (this.pathRegexCheckBox.isSelected()) {
try { try {
condition = new FilesSet.Rule.ParentPathCondition(Pattern.compile(this.pathTextField.getText())); condition = new FilesSet.Rule.ParentPathCondition(Pattern.compile(this.pathTextField.getText(), Pattern.CASE_INSENSITIVE));
} catch (PatternSyntaxException ex) { } catch (PatternSyntaxException ex) {
logger.log(Level.SEVERE, "Attempt to get malformed path condition", ex); // NON-NLS logger.log(Level.SEVERE, "Attempt to get malformed path condition", ex); // NON-NLS
throw new IllegalStateException("The files set rule panel path condition is not in a valid state"); // NON-NLS throw new IllegalStateException("The files set rule panel path condition is not in a valid state"); // NON-NLS

View File

@ -271,6 +271,9 @@ class ReportHTML implements TableReportModule {
case TSK_ACCOUNT: case TSK_ACCOUNT:
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/accounts.png"); //NON-NLS in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/accounts.png"); //NON-NLS
break; break;
case TSK_WIFI_NETWORK:
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/network-wifi.png"); //NON-NLS
break;
default: default:
logger.log(Level.WARNING, "useDataTypeIcon: unhandled artifact type = {0}", dataType); //NON-NLS logger.log(Level.WARNING, "useDataTypeIcon: unhandled artifact type = {0}", dataType); //NON-NLS
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/star.png"); //NON-NLS in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/star.png"); //NON-NLS

View File

@ -41,6 +41,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor; import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.TimeStampUtils; import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.DataSource;
/* /*
* A runnable that adds an archive data source as well as data sources contained * A runnable that adds an archive data source as well as data sources contained
@ -195,10 +196,19 @@ class AddArchiveTask implements Runnable {
continue; continue;
} }
// if we are here it means the data source was addedd successfully // if we are here it means the data source was added successfully
success = true; success = true;
newDataSources.addAll(internalDataSource.getContent()); newDataSources.addAll(internalDataSource.getContent());
// Update the names for all new data sources to be the root archive plus the name of the data source
for (Content c:internalDataSource.getContent()) {
if (c instanceof DataSource) {
DataSource ds = (DataSource) c;
String newName = Paths.get(archivePath).getFileName() + "/" + ds.getName();
ds.setDisplayName(newName);
}
}
// skip all other DSPs for this data source // skip all other DSPs for this data source
break; break;
} }

View File

@ -45,6 +45,7 @@ import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.NetworkUtils; import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.coreutils.StopWatch;
import org.sleuthkit.autopsy.events.AutopsyEventException; import org.sleuthkit.autopsy.events.AutopsyEventException;
import org.sleuthkit.autopsy.events.AutopsyEventPublisher; import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJob.ProcessingStatus; import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestJob.ProcessingStatus;
@ -666,43 +667,73 @@ final class AutoIngestMonitor extends Observable implements PropertyChangeListen
* @return A result code indicating success, partial success, or failure. * @return A result code indicating success, partial success, or failure.
*/ */
CaseDeletionResult deleteCase(AutoIngestJob job) { CaseDeletionResult deleteCase(AutoIngestJob job) {
synchronized (jobsLock) {
String caseName = job.getManifest().getCaseName(); String caseName = job.getManifest().getCaseName();
Path metadataFilePath = job.getCaseDirectoryPath().resolve(caseName + CaseMetadata.getFileExtension()); Path caseDirectoryPath = job.getCaseDirectoryPath();
Path metadataFilePath = caseDirectoryPath.resolve(caseName + CaseMetadata.getFileExtension());
StopWatch stopWatch = new StopWatch();
stopWatch.start();
synchronized (jobsLock) {
stopWatch.stop();
LOGGER.log(Level.INFO, String.format("Used %d s to acquire jobsLock (Java monitor in AutoIngestMonitor class) for case %s at %s", stopWatch.getElapsedTimeSecs(), caseName, caseDirectoryPath));
stopWatch.reset();
stopWatch.start();
try { try {
CaseMetadata metadata = new CaseMetadata(metadataFilePath); CaseMetadata metadata = new CaseMetadata(metadataFilePath);
stopWatch.stop();
LOGGER.log(Level.INFO, String.format("Used %d s to read case metadata for case %s at %s", stopWatch.getElapsedTimeSecs(), caseName, caseDirectoryPath));
stopWatch.reset();
stopWatch.start();
Case.deleteCase(metadata); Case.deleteCase(metadata);
} catch (CaseMetadata.CaseMetadataException ex) { } catch (CaseMetadata.CaseMetadataException ex) {
LOGGER.log(Level.SEVERE, String.format("Failed to get case metadata file %s for case %s at %s", metadataFilePath.toString(), caseName, job.getCaseDirectoryPath().toString()), ex); LOGGER.log(Level.SEVERE, String.format("Failed to read case metadata file %s for case %s at %s", metadataFilePath, caseName, caseDirectoryPath), ex);
stopWatch.stop();
LOGGER.log(Level.INFO, String.format("Used %d s to fail to read case metadata file %s for case %s at %s", stopWatch.getElapsedTimeSecs(), metadataFilePath, caseName, caseDirectoryPath));
return CaseDeletionResult.FAILED; return CaseDeletionResult.FAILED;
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
LOGGER.log(Level.SEVERE, String.format("Failed to physically delete case %s at %s", caseName, job.getCaseDirectoryPath().toString()), ex); LOGGER.log(Level.SEVERE, String.format("Failed to delete case %s at %s", caseName, caseDirectoryPath), ex);
return CaseDeletionResult.FAILED; return CaseDeletionResult.FAILED;
} }
// Update the state of completed jobs associated with this case to indicate // Update the state of completed jobs associated with this case to indicate
// that the case has been deleted // that the case has been deleted
for (AutoIngestJob completedJob : getCompletedJobs()) { stopWatch.reset();
stopWatch.start();
List<AutoIngestJob> completedJobs = getCompletedJobs();
stopWatch.stop();
LOGGER.log(Level.INFO, String.format("Used %d s to get completed jobs listing for case %s at %s", stopWatch.getElapsedTimeSecs(), caseName, caseDirectoryPath));
stopWatch.reset();
stopWatch.start();
for (AutoIngestJob completedJob : completedJobs) {
if (caseName.equals(completedJob.getManifest().getCaseName())) { if (caseName.equals(completedJob.getManifest().getCaseName())) {
try { try {
completedJob.setProcessingStatus(DELETED); completedJob.setProcessingStatus(DELETED);
AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(completedJob); AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(completedJob);
coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, completedJob.getManifest().getFilePath().toString(), nodeData.toArray()); coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, completedJob.getManifest().getFilePath().toString(), nodeData.toArray());
} catch (CoordinationServiceException | InterruptedException ex) { } catch (CoordinationServiceException | InterruptedException ex) {
LOGGER.log(Level.SEVERE, String.format("Failed to update completed job node data for %s when deleting case %s", completedJob.getManifest().getFilePath().toString(), caseName), ex); LOGGER.log(Level.SEVERE, String.format("Failed to update completed job node data for %s when deleting case %s at %s", completedJob.getManifest().getFilePath(), caseName, caseDirectoryPath), ex);
stopWatch.stop();
LOGGER.log(Level.INFO, String.format("Used %d s to fail to update job node data for completed jobs for case %s at %s", stopWatch.getElapsedTimeSecs(), caseName, caseDirectoryPath));
return CaseDeletionResult.PARTIALLY_DELETED; return CaseDeletionResult.PARTIALLY_DELETED;
} }
} }
} }
stopWatch.stop();
LOGGER.log(Level.INFO, String.format("Used %d s to update job node data for completed jobs for case %s at %s", stopWatch.getElapsedTimeSecs(), caseName, caseDirectoryPath));
// Remove jobs associated with this case from the completed jobs collection. // Remove jobs associated with this case from the completed jobs collection.
jobsSnapshot.completedJobs.removeIf((AutoIngestJob completedJob) stopWatch.reset();
stopWatch.start();
completedJobs.removeIf((AutoIngestJob completedJob)
-> completedJob.getManifest().getCaseName().equals(caseName)); -> completedJob.getManifest().getCaseName().equals(caseName));
stopWatch.stop();
LOGGER.log(Level.INFO, String.format("Used %d s to remove completed jobs for case %s at %s from current jobs snapshot", stopWatch.getElapsedTimeSecs(), caseName, caseDirectoryPath));
// Publish a message to update auto ingest nodes. // Publish a message to update auto ingest nodes.
stopWatch.reset();
stopWatch.start();
eventPublisher.publishRemotely(new AutoIngestCaseDeletedEvent(caseName, LOCAL_HOST_NAME, AutoIngestManager.getSystemUserNameProperty())); eventPublisher.publishRemotely(new AutoIngestCaseDeletedEvent(caseName, LOCAL_HOST_NAME, AutoIngestManager.getSystemUserNameProperty()));
stopWatch.stop();
LOGGER.log(Level.INFO, String.format("Used %d s to publish job deletion event for case %s at %s", stopWatch.getElapsedTimeSecs(), caseName,caseDirectoryPath));
} }
return CaseDeletionResult.FULLY_DELETED; return CaseDeletionResult.FULLY_DELETED;

View File

@ -254,6 +254,7 @@ public final class ImageGalleryController {
/** /**
* Should the "forward" button on the history be enabled? * Should the "forward" button on the history be enabled?
*
* @return * @return
*/ */
public ReadOnlyBooleanProperty getCanAdvance() { public ReadOnlyBooleanProperty getCanAdvance() {
@ -262,6 +263,7 @@ public final class ImageGalleryController {
/** /**
* Should the "Back" button on the history be enabled? * Should the "Back" button on the history be enabled?
*
* @return * @return
*/ */
public ReadOnlyBooleanProperty getCanRetreat() { public ReadOnlyBooleanProperty getCanRetreat() {
@ -269,10 +271,9 @@ public final class ImageGalleryController {
} }
/** /**
* Display the passed in group. Causes this group to * Display the passed in group. Causes this group to get recorded in the
* get recorded in the history queue and observers of the * history queue and observers of the current state will be notified and
* current state will be notified and update their panels/widgets * update their panels/widgets appropriately.
* appropriately.
* *
* @param newState * @param newState
*/ */
@ -283,6 +284,7 @@ public final class ImageGalleryController {
/** /**
* Display the next group in the "forward" history stack * Display the next group in the "forward" history stack
*
* @return * @return
*/ */
public GroupViewState advance() { public GroupViewState advance() {
@ -291,6 +293,7 @@ public final class ImageGalleryController {
/** /**
* Display the previous group in the "back" history stack * Display the previous group in the "back" history stack
*
* @return * @return
*/ */
public GroupViewState retreat() { public GroupViewState retreat() {
@ -500,10 +503,6 @@ public final class ImageGalleryController {
return drawableDB.getFileFromID(fileID); return drawableDB.getFileFromID(fileID);
} }
public ReadOnlyDoubleProperty regroupProgress() {
return groupManager.regroupProgress();
}
public HashSetManager getHashSetManager() { public HashSetManager getHashSetManager() {
return hashSetManager; return hashSetManager;
} }
@ -764,8 +763,9 @@ public final class ImageGalleryController {
//do in transaction //do in transaction
drawableDbTransaction = taskDB.beginTransaction(); drawableDbTransaction = taskDB.beginTransaction();
/* We are going to periodically commit the CaseDB transaction and sleep so /* We are going to periodically commit the CaseDB transaction
* that the user can have Autopsy do other stuff while these bulk tasks are ongoing. * and sleep so that the user can have Autopsy do other stuff
* while these bulk tasks are ongoing.
*/ */
int caseDbCounter = 0; int caseDbCounter = 0;
for (final AbstractFile f : files) { for (final AbstractFile f : files) {

View File

@ -68,13 +68,6 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
DrawableGroup(GroupKey<?> groupKey, Set<Long> filesInGroup, boolean seen) { DrawableGroup(GroupKey<?> groupKey, Set<Long> filesInGroup, boolean seen) {
this.groupKey = groupKey; this.groupKey = groupKey;
this.fileIDs.setAll(filesInGroup); this.fileIDs.setAll(filesInGroup);
fileIDs.addListener((ListChangeListener.Change<? extends Long> listchange) -> {
boolean seenChanged = false;
while (false == seenChanged && listchange.next()) {
seenChanged |= listchange.wasAdded();
}
invalidateProperties(seenChanged);
});
this.seen.set(seen); this.seen.set(seen);
} }
@ -183,15 +176,21 @@ public class DrawableGroup implements Comparable<DrawableGroup> {
if (fileIDs.contains(f) == false) { if (fileIDs.contains(f) == false) {
fileIDs.add(f); fileIDs.add(f);
} }
// invalidate no matter what because the file could have new hash hits, etc.
invalidateProperties(true);
} }
synchronized void setFiles(Set<? extends Long> newFileIds) { synchronized void setFiles(Set<? extends Long> newFileIds) {
fileIDs.removeIf(fileID -> newFileIds.contains(fileID) == false); fileIDs.removeIf(fileID -> newFileIds.contains(fileID) == false);
invalidateProperties(false);
newFileIds.stream().forEach(this::addFile); newFileIds.stream().forEach(this::addFile);
} }
synchronized void removeFile(Long f) { synchronized void removeFile(Long f) {
if (fileIDs.contains(f)) {
fileIDs.removeAll(f); fileIDs.removeAll(f);
invalidateProperties(false);
}
} }
private void invalidateProperties(boolean seenChanged) { private void invalidateProperties(boolean seenChanged) {

View File

@ -50,6 +50,7 @@ import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.beans.property.ReadOnlyDoubleProperty; import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.concurrent.Service; import javafx.concurrent.Service;
@ -278,8 +279,8 @@ public class GroupManager {
} }
/** /**
* Update unseenGroups list accordingly based on the current status * Update unseenGroups list accordingly based on the current status of
* of 'group'. Removes it if it is seen or adds it if it is unseen. * 'group'. Removes it if it is seen or adds it if it is unseen.
* *
* @param group * @param group
*/ */
@ -505,6 +506,10 @@ public class GroupManager {
return regrouper.progressProperty(); return regrouper.progressProperty();
} }
public ReadOnlyStringProperty regroupMessage() {
return regrouper.messageProperty();
}
@Subscribe @Subscribe
synchronized public void handleTagAdded(ContentTagAddedEvent evt) { synchronized public void handleTagAdded(ContentTagAddedEvent evt) {
GroupKey<?> newGroupKey = null; GroupKey<?> newGroupKey = null;
@ -730,12 +735,7 @@ public class GroupManager {
*/ */
@SuppressWarnings({"unchecked", "rawtypes"}) @SuppressWarnings({"unchecked", "rawtypes"})
@NbBundle.Messages({"# {0} - groupBy attribute Name", @NbBundle.Messages({"# {0} - groupBy attribute Name",
"# {1} - sortBy name", "ReGroupTask.displayTitle=regrouping by {0}: " })
"# {2} - sort Order",
"ReGroupTask.displayTitle=regrouping files by {0} sorted by {1} in {2} order",
"# {0} - groupBy attribute Name",
"# {1} - atribute value",
"ReGroupTask.progressUpdate=regrouping files by {0} : {1}"})
class ReGroupTask<AttrValType extends Comparable<AttrValType>> extends LoggedTask<Void> { class ReGroupTask<AttrValType extends Comparable<AttrValType>> extends LoggedTask<Void> {
private final DataSource dataSource; private final DataSource dataSource;
@ -743,16 +743,14 @@ public class GroupManager {
private final GroupSortBy sortBy; private final GroupSortBy sortBy;
private final SortOrder sortOrder; private final SortOrder sortOrder;
private final ProgressHandle groupProgress;
ReGroupTask(DataSource dataSource, DrawableAttribute<AttrValType> groupBy, GroupSortBy sortBy, SortOrder sortOrder) { ReGroupTask(DataSource dataSource, DrawableAttribute<AttrValType> groupBy, GroupSortBy sortBy, SortOrder sortOrder) {
super(Bundle.ReGroupTask_displayTitle(groupBy.attrName.toString(), sortBy.getDisplayName(), sortOrder.toString()), true); super(Bundle.ReGroupTask_displayTitle(groupBy.attrName.toString() ), true);
this.dataSource = dataSource; this.dataSource = dataSource;
this.groupBy = groupBy; this.groupBy = groupBy;
this.sortBy = sortBy; this.sortBy = sortBy;
this.sortOrder = sortOrder; this.sortOrder = sortOrder;
groupProgress = ProgressHandle.createHandle(Bundle.ReGroupTask_displayTitle(groupBy.attrName.toString(), sortBy.getDisplayName(), sortOrder.toString()), this); updateTitle(Bundle.ReGroupTask_displayTitle(groupBy.attrName.toString() ));
} }
@Override @Override
@ -761,7 +759,8 @@ public class GroupManager {
if (isCancelled()) { if (isCancelled()) {
return null; return null;
} }
groupProgress.start();
updateProgress(-1, 1);
analyzedGroups.clear(); analyzedGroups.clear();
unSeenGroups.clear(); unSeenGroups.clear();
@ -769,7 +768,7 @@ public class GroupManager {
// Get the list of group keys // Get the list of group keys
Multimap<DataSource, AttrValType> valsByDataSource = findValuesForAttribute(); Multimap<DataSource, AttrValType> valsByDataSource = findValuesForAttribute();
groupProgress.switchToDeterminate(valsByDataSource.entries().size()); updateProgress(0, valsByDataSource.entries().size());
int p = 0; int p = 0;
// For each key value, partially create the group and add it to the list. // For each key value, partially create the group and add it to the list.
for (final Map.Entry<DataSource, AttrValType> valForDataSource : valsByDataSource.entries()) { for (final Map.Entry<DataSource, AttrValType> valForDataSource : valsByDataSource.entries()) {
@ -777,9 +776,8 @@ public class GroupManager {
return null; return null;
} }
p++; p++;
updateMessage(Bundle.ReGroupTask_progressUpdate(groupBy.attrName.toString(), valForDataSource.getValue())); updateMessage(Bundle.ReGroupTask_displayTitle(groupBy.attrName.toString()) + valForDataSource.getValue());
updateProgress(p, valsByDataSource.size()); updateProgress(p, valsByDataSource.size());
groupProgress.progress(Bundle.ReGroupTask_progressUpdate(groupBy.attrName.toString(), valForDataSource), p);
popuplateIfAnalyzed(new GroupKey<>(groupBy, valForDataSource.getValue(), valForDataSource.getKey()), this); popuplateIfAnalyzed(new GroupKey<>(groupBy, valForDataSource.getValue(), valForDataSource.getKey()), this);
} }
@ -808,8 +806,8 @@ public class GroupManager {
} }
} }
} finally { } finally {
groupProgress.finish();
updateProgress(1, 1); updateProgress(1, 1);
updateMessage("");
} }
return null; return null;
} }
@ -827,12 +825,9 @@ public class GroupManager {
} }
/** /**
* find the distinct values for the given column (DrawableAttribute) * Find the distinct values for the given column (DrawableAttribute).
*
* These values represent the groups of files. * These values represent the groups of files.
* *
* @param groupBy
*
* @return map of data source (or null if group by attribute ignores * @return map of data source (or null if group by attribute ignores
* data sources) to list of unique group values * data sources) to list of unique group values
*/ */

View File

@ -10,12 +10,21 @@
<?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?> <?import javafx.scene.layout.StackPane?>
<fx:root id="AnchorPane" maxHeight="-Infinity" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" type="javafx.scene.layout.AnchorPane" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1"> <fx:root id="AnchorPane" maxHeight="-Infinity" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" type="javafx.scene.layout.AnchorPane" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1">
<children> <children>
<BorderPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <BorderPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<right> <right>
<HBox alignment="CENTER_RIGHT" prefHeight="-1.0" prefWidth="-1.0" spacing="5.0" BorderPane.alignment="CENTER_RIGHT"> <HBox alignment="CENTER_RIGHT" prefHeight="-1.0" prefWidth="-1.0" spacing="5.0" BorderPane.alignment="CENTER_RIGHT">
<children> <children>
<Label fx:id="staleLabel" text="Some data may be out of date. Enable listening to ingest to update.">
<graphic>
<ImageView fitHeight="16.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../images/information.png" />
</image>
</ImageView>
</graphic>
</Label>
<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" HBox.hgrow="NEVER"> <StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" HBox.hgrow="NEVER">
<children> <children>
<ProgressBar id="progBar" fx:id="fileTaskProgresBar" focusTraversable="false" maxHeight="-1.0" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-1.0" prefHeight="24.0" prefWidth="-1.0" progress="0.0" visible="true" /> <ProgressBar id="progBar" fx:id="fileTaskProgresBar" focusTraversable="false" maxHeight="-1.0" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-1.0" prefHeight="24.0" prefWidth="-1.0" progress="0.0" visible="true" />
@ -29,21 +38,6 @@
</children> </children>
<HBox.margin> <HBox.margin>
<Insets /> <Insets />
</HBox.margin>
</StackPane>
<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" HBox.hgrow="NEVER">
<children>
<ProgressBar fx:id="bgTaskProgressBar" maxHeight="-1.0" maxWidth="-1.0" minHeight="-Infinity" minWidth="-1.0" prefHeight="24.0" prefWidth="-1.0" progress="0.0" StackPane.alignment="CENTER" />
<Label fx:id="bgTaskLabel" alignment="CENTER" cache="false" contentDisplay="CENTER" disable="false" focusTraversable="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" text="" StackPane.alignment="CENTER">
<StackPane.margin>
<Insets left="3.0" right="3.0" />
</StackPane.margin>
<padding>
<Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
</padding></Label>
</children>
<HBox.margin>
<Insets right="5.0" />
</HBox.margin> </HBox.margin>
</StackPane> </StackPane>
</children> </children>
@ -52,15 +46,20 @@
</BorderPane.margin> </BorderPane.margin>
</HBox> </HBox>
</right> </right>
<left><Label fx:id="staleLabel" text="Some data may be out of date. Enable listening to ingest to update." BorderPane.alignment="CENTER"> <left>
<graphic><ImageView fitHeight="16.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true"> <StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" BorderPane.alignment="CENTER">
<image> <children>
<Image url="@../images/information.png" /> <ProgressBar fx:id="regroupProgressBar" maxHeight="-1.0" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-1.0" prefHeight="24.0" prefWidth="500.0" progress="0.0" StackPane.alignment="CENTER_LEFT" />
</image></ImageView> <Label fx:id="regroupLabel" cache="false" contentDisplay="CENTER" disable="false" focusTraversable="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="500.0" text="" textOverrun="CENTER_ELLIPSIS" StackPane.alignment="CENTER_LEFT">
</graphic> <StackPane.margin>
<BorderPane.margin> <Insets left="3.0" right="3.0" />
<Insets bottom="5.0" left="5.0" right="10.0" top="5.0" /> </StackPane.margin>
</BorderPane.margin></Label> <padding>
<Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
</padding>
</Label>
</children>
</StackPane>
</left> </left>
</BorderPane> </BorderPane>
</children> </children>

View File

@ -28,28 +28,26 @@ import javafx.scene.control.Tooltip;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupManager;
/** /**
* *
*/ */
public class StatusBar extends AnchorPane { public class StatusBar extends AnchorPane {
private final ImageGalleryController controller;
@FXML @FXML
private ProgressBar fileTaskProgresBar; private ProgressBar fileTaskProgresBar;
@FXML @FXML
private Label fileUpdateTaskLabel; private Label fileUpdateTaskLabel;
@FXML @FXML
private Label bgTaskLabel; private Label regroupLabel;
@FXML @FXML
private Label staleLabel; private Label staleLabel;
@FXML @FXML
private ProgressBar bgTaskProgressBar; private ProgressBar regroupProgressBar;
private final ImageGalleryController controller;
private final GroupManager groupManager;
@FXML @FXML
@NbBundle.Messages({"StatusBar.fileUpdateTaskLabel.text= File Update Tasks", @NbBundle.Messages({"StatusBar.fileUpdateTaskLabel.text= File Update Tasks",
@ -58,23 +56,25 @@ public class StatusBar extends AnchorPane {
void initialize() { void initialize() {
assert fileTaskProgresBar != null : "fx:id=\"fileTaskProgresBar\" was not injected: check your FXML file 'StatusBar.fxml'."; assert fileTaskProgresBar != null : "fx:id=\"fileTaskProgresBar\" was not injected: check your FXML file 'StatusBar.fxml'.";
assert fileUpdateTaskLabel != null : "fx:id=\"fileUpdateTaskLabel\" was not injected: check your FXML file 'StatusBar.fxml'."; assert fileUpdateTaskLabel != null : "fx:id=\"fileUpdateTaskLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
assert bgTaskLabel != null : "fx:id=\"bgTaskLabel\" was not injected: check your FXML file 'StatusBar.fxml'."; assert regroupLabel != null : "fx:id=\"regroupLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
assert bgTaskProgressBar != null : "fx:id=\"bgTaskProgressBar\" was not injected: check your FXML file 'StatusBar.fxml'."; assert regroupProgressBar != null : "fx:id=\"regroupProgressBar\" was not injected: check your FXML file 'StatusBar.fxml'.";
fileUpdateTaskLabel.textProperty().bind(controller.getDBTasksQueueSizeProperty().asString().concat(Bundle.StatusBar_fileUpdateTaskLabel_text())); fileUpdateTaskLabel.textProperty().bind(controller.getDBTasksQueueSizeProperty().asString().concat(Bundle.StatusBar_fileUpdateTaskLabel_text()));
fileTaskProgresBar.progressProperty().bind(controller.getDBTasksQueueSizeProperty().negate()); fileTaskProgresBar.progressProperty().bind(controller.getDBTasksQueueSizeProperty().negate());
controller.regroupProgress().addListener((ov, oldSize, newSize) -> { groupManager.regroupProgress().addListener((ov, oldSize, newSize) -> {
Platform.runLater(() -> { Platform.runLater(() -> {
if (controller.regroupProgress().lessThan(1.0).get()) { if (groupManager.regroupProgress().lessThan(1.0).get()) {
// Regrouping in progress // Regrouping in progress
bgTaskProgressBar.progressProperty().setValue(-1.0); regroupProgressBar.progressProperty().setValue(groupManager.regroupProgress().doubleValue());
bgTaskLabel.setText(Bundle.StatusBar_bgTaskLabel_text()); regroupLabel.setText(groupManager.regroupMessage().get());
} else { } else {
// Clear the progress bar // Clear the progress bar
bgTaskProgressBar.progressProperty().setValue(0.0); regroupProgressBar.progressProperty().setValue(0.0);
bgTaskLabel.setText(""); regroupLabel.setText("");
} }
regroupLabel.setTooltip(new Tooltip(regroupLabel.getText()));
}); });
}); });
@ -84,6 +84,7 @@ public class StatusBar extends AnchorPane {
public StatusBar(ImageGalleryController controller) { public StatusBar(ImageGalleryController controller) {
this.controller = controller; this.controller = controller;
this.groupManager = controller.getGroupManager();
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("StatusBar.fxml")); //NON-NLS FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("StatusBar.fxml")); //NON-NLS
fxmlLoader.setRoot(this); fxmlLoader.setRoot(this);
fxmlLoader.setController(this); fxmlLoader.setController(this);
@ -93,6 +94,5 @@ public class StatusBar extends AnchorPane {
} catch (IOException exception) { } catch (IOException exception) {
throw new RuntimeException(exception); throw new RuntimeException(exception);
} }
} }
} }

View File

@ -1,8 +1,8 @@
---------------- VERSION 4.9.0 -------------- ---------------- VERSION 4.9.1 --------------
Bug Fixes: Bug Fixes:
- Fixed possible ingest deadlock from Image Gallery database inserts - Fixed possible ingest deadlock from Image Gallery database inserts.
- Image Gallery does not need lock on Case DB during pre-population, which makes UI more responsive - Image Gallery does not need lock on Case DB during pre-population, which makes UI more responsive.
- Other misc Image Gallery fixes - Other misc Image Gallery fixes.
---------------- VERSION 4.9.0 -------------- ---------------- VERSION 4.9.0 --------------

View File

@ -64,9 +64,7 @@
</run-dependency> </run-dependency>
</dependency> </dependency>
</module-dependencies> </module-dependencies>
<public-packages> <public-packages/>
<package>org.sleuthkit.autopsy.recentactivity</package>
</public-packages>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/gson-2.1.jar</runtime-relative-path> <runtime-relative-path>ext/gson-2.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/gson-2.1.jar</binary-origin> <binary-origin>release/modules/ext/gson-2.1.jar</binary-origin>

View File

@ -39,6 +39,7 @@ import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
@ -163,7 +164,7 @@ class Chrome extends Extract {
NbBundle.getMessage(this.getClass(), "Chrome.moduleName"))); NbBundle.getMessage(this.getClass(), "Chrome.moduleName")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
(Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS (NetworkUtils.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes); BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
if (bbart != null) { if (bbart != null) {
@ -286,7 +287,7 @@ class Chrome extends Extract {
} else { } else {
date = Long.valueOf(0); date = Long.valueOf(0);
} }
String domain = Util.extractDomain(url); String domain = NetworkUtils.extractDomain(url);
try { try {
BlackboardArtifact bbart = bookmarkFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK); BlackboardArtifact bbart = bookmarkFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
Collection<BlackboardAttribute> bbattributes = new ArrayList<>(); Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
@ -496,7 +497,7 @@ class Chrome extends Extract {
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", time)); //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", time));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), time)); NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), time));
String domain = Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : ""); //NON-NLS String domain = NetworkUtils.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : ""); //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), domain)); NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), domain));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
@ -590,7 +591,7 @@ class Chrome extends Extract {
NbBundle.getMessage(this.getClass(), "Chrome.moduleName"))); NbBundle.getMessage(this.getClass(), "Chrome.moduleName")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
(Util.extractDomain((result.get("origin_url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS (NetworkUtils.extractDomain((result.get("origin_url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
((result.get("username_value").toString() != null) ? result.get("username_value").toString().replaceAll("'", "''") : ""))); //NON-NLS ((result.get("username_value").toString() != null) ? result.get("username_value").toString().replaceAll("'", "''") : ""))); //NON-NLS

View File

@ -26,6 +26,7 @@ import java.io.BufferedReader;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.ExecUtil; import org.sleuthkit.autopsy.coreutils.ExecUtil;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -609,6 +610,6 @@ class ExtractIE extends Extract {
return null; return null;
} }
return Util.extractDomain(url); return NetworkUtils.extractDomain(url);
} }
} }

View File

@ -374,7 +374,9 @@ class ExtractRegistry extends Extract {
// Add all "usb" dataType nodes to collection of BlackboardArtifacts // Add all "usb" dataType nodes to collection of BlackboardArtifacts
// that we will submit in a ModuleDataEvent for additional processing. // that we will submit in a ModuleDataEvent for additional processing.
Collection<BlackboardArtifact> usbBBartifacts = new ArrayList<>(); Collection<BlackboardArtifact> usbBBartifacts = new ArrayList<>();
// Add all "ssid" dataType nodes to collection of BlackboardArtifacts
// that we will submit in a ModuleDataEvent for additional processing.
Collection<BlackboardArtifact> wifiBBartifacts = new ArrayList<>();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
Element tempnode = (Element) children.item(i); Element tempnode = (Element) children.item(i);
@ -734,6 +736,7 @@ class ExtractRegistry extends Extract {
bbart.addAttributes(bbattributes); bbart.addAttributes(bbattributes);
// index the artifact for keyword search // index the artifact for keyword search
this.indexArtifact(bbart); this.indexArtifact(bbart);
wifiBBartifacts.add(bbart);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding SSID artifact to blackboard."); //NON-NLS logger.log(Level.SEVERE, "Error adding SSID artifact to blackboard."); //NON-NLS
} }
@ -756,6 +759,9 @@ class ExtractRegistry extends Extract {
if (!usbBBartifacts.isEmpty()) { if (!usbBBartifacts.isEmpty()) {
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED, usbBBartifacts)); IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED, usbBBartifacts));
} }
if (!wifiBBartifacts.isEmpty()){
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_WIFI_NETWORK, wifiBBartifacts));
}
return true; return true;
} catch (FileNotFoundException ex) { } catch (FileNotFoundException ex) {
logger.log(Level.SEVERE, "Error finding the registry file."); //NON-NLS logger.log(Level.SEVERE, "Error finding the registry file."); //NON-NLS

View File

@ -35,6 +35,7 @@ import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestServices;
@ -669,6 +670,6 @@ class Firefox extends Extract {
return null; return null;
} }
return Util.extractDomain(url); return NetworkUtils.extractDomain(url);
} }
} }

View File

@ -84,83 +84,6 @@ class Util {
} }
} }
/**
*
* @param url
* @return empty string if no domain could be found
*/
private static String getBaseDomain(String url) {
String host = null;
//strip protocol
String cleanUrl = url.replaceFirst(".*:\\/\\/", "");
//strip after slashes
String dirToks[] = cleanUrl.split("\\/");
if (dirToks.length > 0) {
host = dirToks[0];
} else {
host = cleanUrl;
}
//get the domain part from host (last 2)
StringTokenizer tok = new StringTokenizer(host, ".");
StringBuilder hostB = new StringBuilder();
int toks = tok.countTokens();
for (int count = 0; count < toks; ++count) {
String part = tok.nextToken();
int diff = toks - count;
if (diff < 3) {
hostB.append(part);
}
if (diff == 2) {
hostB.append(".");
}
}
String base = hostB.toString();
// verify there are no special characters in there
if (base.matches(".*[~`!@#$%^&\\*\\(\\)\\+={}\\[\\];:\\?<>,/ ].*")) {
return "";
}
return base;
}
/**
*
* @param value
* @return empty string if no domain name was found
*/
public static String extractDomain(String value) {
if (value == null) {
return "";
}
String result = "";
// String domainPattern = "(\\w+)\\.(AC|AD|AE|AERO|AF|AG|AI|AL|AM|AN|AO|AQ|AR|ARPA|AS|ASIA|AT|AU|AW|AX|AZ|BA|BB|BD|BE|BF|BG|BH|BI|BIZ|BJ|BM|BN|BO|BR|BS|BT|BV|BW|BY|BZ|CA|CAT|CC|CD|CF|CG|CH|CI|CK|CL|CM|CN|CO|COM|COOP|CR|CU|CV|CW|CX|CY|CZ|DE|DJ|DK|DM|DO|DZ|EC|EDU|EE|EG|ER|ES|ET|EU|FI|FJ|FK|FM|FO|FR|GA|GB|GD|GE|GF|GG|GH|GI|GL|GM|GN|GOV|GP|GQ|GR|GS|GT|GU|GW|GY|HK|HM|HN|HR|HT|HU|ID|IE|IL|IM|IN|INFO|INT|IO|IQ|IR|IS|IT|JE|JM|JO|JOBS|JP|KE|KG|KH|KI|KM|KN|KP|KR|KW|KY|KZ|LA|LB|LC|LI|LK|LR|LS|LT|LU|LV|LY|MA|MC|MD|ME|MG|MH|MIL|MK|ML|MM|MN|MO|MOBI|MP|MQ|MR|MS|MT|MU|MUSEUM|MV|MW|MX|MY|MZ|NA|NAME|NC|NE|NET|NF|NG|NI|NL|NO|NP|NR|NU|NZ|OM|ORG|PA|PE|PF|PG|PH|PK|PL|PM|PN|PR|PRO|PS|PT|PW|PY|QA|RE|RO|RS|RU|RW|SA|SB|SC|SD|SE|SG|SH|SI|SJ|SK|SL|SM|SN|SO|SR|ST|SU|SV|SX|SY|SZ|TC|TD|TEL|TF|TG|TH|TJ|TK|TL|TM|TN|TO|TP|TR|TRAVEL|TT|TV|TW|TZ|UA|UG|UK|US|UY|UZ|VA|VC|VE|VG|VI|VN|VU|WF|WS|XXX|YE|YT|ZA|ZM|ZW(co\\.[a-z].))";
// Pattern p = Pattern.compile(domainPattern,Pattern.CASE_INSENSITIVE);
// Matcher m = p.matcher(value);
// while (m.find()) {
// result = value.substring(m.start(0),m.end(0));
// }
try {
URL url = new URL(value);
result = url.getHost();
} catch (MalformedURLException ex) {
//do not log if not a valid URL, and handle later
//Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex);
}
//was not a valid URL, try a less picky method
if (result == null || result.trim().isEmpty()) {
return getBaseDomain(value);
}
return result;
}
public static String getFileName(String value) { public static String getFileName(String value) {
String filename = ""; String filename = "";
String filematch = "^([a-zA-Z]\\:)(\\\\[^\\\\/:*?<>\"|]*(?<!\\[ \\]))*(\\.[a-zA-Z]{2,6})$"; //NON-NLS String filematch = "^([a-zA-Z]\\:)(\\\\[^\\\\/:*?<>\"|]*(?<!\\[ \\]))*(\\.[a-zA-Z]{2,6})$"; //NON-NLS

View File

@ -1,5 +1,5 @@
#Updated by build script #Updated by build script
#Sat, 13 Oct 2018 21:02:18 -0400 #Tue, 13 Nov 2018 17:30:09 -0500
LBL_splash_window_title=Starting Autopsy LBL_splash_window_title=Starting Autopsy
SPLASH_HEIGHT=314 SPLASH_HEIGHT=314
SPLASH_WIDTH=538 SPLASH_WIDTH=538
@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18
SplashRunningTextColor=0x0 SplashRunningTextColor=0x0
SplashRunningTextFontSize=19 SplashRunningTextFontSize=19
currentVersion=Autopsy 4.9.0 currentVersion=Autopsy 4.9.1

View File

@ -1,4 +1,4 @@
#Updated by build script #Updated by build script
#Sat, 13 Oct 2018 21:02:18 -0400 #Tue, 13 Nov 2018 17:30:09 -0500
CTL_MainWindow_Title=Autopsy 4.9.0 CTL_MainWindow_Title=Autopsy 4.9.1
CTL_MainWindow_Title_No_Project=Autopsy 4.9.0 CTL_MainWindow_Title_No_Project=Autopsy 4.9.1

View File

@ -1,268 +0,0 @@
#!/usr/bin/perl
# Updates various Autopsy version numbers
use strict;
use File::Copy;
# global variables
my $VER;
my $TESTING = 0;
print "TESTING MODE (no commits)\n" if ($TESTING);
sub main {
# Get the Autopsy version argument
if (scalar (@ARGV) != 1) {
print stderr "Missing release version argument (i.e. 4.9.0)\n";
exit;
}
$VER = $ARGV[0];
die "Invalid version number: $VER (1.2.3 or 1.2.3b1 expected)" unless ($VER =~ /^\d+\.\d+\.\d+(b\d+)?$/);
my $AUT_RELNAME = "autopsy-${VER}";
# Verify the tag doesn't already exist
exec_pipe(*OUT, "git tag | grep \"${AUT_RELNAME}\$\"");
my $foo = read_pipe_line(*OUT);
if ($foo ne "") {
print "Tag ${AUT_RELNAME} already exists\n";
print "Remove with 'git tag -d ${AUT_RELNAME}'\n";
die "stopping";
}
close(OUT);
# Assume we running out of 'release' folder
chdir ".." or die "Error changing directories to root";
# verify_precheckin();
# Update the version info in that tag
update_project_properties();
update_doxygen_dev();
update_doxygen_user();
print "Files updated. You need to commit and push them\n";
}
######################################################
# Utility functions
# Function to execute a command and send output to pipe
# returns handle
# exec_pipe(HANDLE, CMD);
sub exec_pipe {
my $handle = shift(@_);
my $cmd = shift(@_);
die "Can't open pipe for exec_pipe"
unless defined(my $pid = open($handle, '-|'));
if ($pid) {
return $handle;
}
else {
$| = 1;
exec("$cmd") or die "Can't exec program: $!";
}
}
# Read a line of text from an open exec_pipe handle
sub read_pipe_line {
my $handle = shift(@_);
my $out;
for (my $i = 0; $i < 100; $i++) {
$out = <$handle>;
return $out if (defined $out);
}
return $out;
}
# Prompt user for argument and return response
sub prompt_user {
my $q = shift(@_);
print "$q: ";
$| = 1;
$_ = <STDIN>;
chomp;
return $_;
}
#############################################
# File update methods
# Verify that all files in the current source directory
# are checked in. dies if any are modified.
sub verify_precheckin {
#system ("git pull");
print "Verifying everything is checked in\n";
exec_pipe(*OUT, "git status -s | grep \"^ M\"");
my $foo = read_pipe_line(*OUT);
if ($foo ne "") {
print "Files not checked in\n";
while ($foo ne "") {
print "$foo";
$foo = read_pipe_line(*OUT);
}
die "stopping" unless ($TESTING);
}
close(OUT);
print "Verifying everything is pushed\n";
exec_pipe(*OUT, "git status -sb | grep \"^##\" | grep \"ahead \"");
my $foo = read_pipe_line(*OUT);
if ($foo ne "") {
print "$foo";
print "Files not pushed to remote\n";
die "stopping" unless ($TESTING);
}
close(OUT);
}
# update the version in nbproject/project.properties
sub update_project_properties {
my $orig = "project.properties";
my $temp = "${orig}-bak";
print "Updating the version in ${orig}\n";
chdir "nbproject" or die "cannot change into nbproject directory";
open (CONF_IN, "<${orig}") or die "Cannot open ${orig}";
open (CONF_OUT, ">${temp}") or die "Cannot open ${temp}";
my $found = 0;
while (<CONF_IN>) {
if (/^app\.version=/) {
print CONF_OUT "app.version=$VER\n";
$found++;
}
else {
print CONF_OUT $_;
}
}
close (CONF_IN);
close (CONF_OUT);
if ($found != 1) {
die "$found (instead of 1) occurrences of app.version found in ${orig}";
}
unlink ($orig) or die "Error deleting ${orig}";
rename ($temp, $orig) or die "Error renaming tmp $orig file";
system("git add ${orig}") unless ($TESTING);
chdir ".." or die "Error changing directories back to root";
}
# update the dev docs
sub update_doxygen_dev {
my $orig = "Doxyfile";
my $temp = "${orig}-bak";
print "Updating the version in ${orig} (Dev)\n";
chdir "docs/doxygen" or die "cannot change into docs/doxygen directory";
open (CONF_IN, "<${orig}") or die "Cannot open ${orig}";
open (CONF_OUT, ">${temp}") or die "Cannot open ${temp}";
my $found = 0;
while (<CONF_IN>) {
if (/^PROJECT_NUMBER/) {
print CONF_OUT "PROJECT_NUMBER = ${VER}\n";
$found++;
}
elsif (/^HTML_OUTPUT/) {
print CONF_OUT "HTML_OUTPUT = api-docs/${VER}/\n";
$found++;
}
else {
print CONF_OUT $_;
}
}
close (CONF_IN);
close (CONF_OUT);
if ($found != 2) {
die "$found (instead of 2) occurrences of version found in (DEV) ${orig}";
}
unlink ($orig) or die "Error deleting ${orig}";
rename ($temp, $orig) or die "Error renaming tmp $orig file";
system("git add ${orig}") unless ($TESTING);
chdir "../.." or die "Error changing directories back to root";
}
# update the user docs
sub update_doxygen_user {
my $orig = "Doxyfile";
my $temp = "${orig}-bak";
print "Updating the version in ${orig} (User)\n";
chdir "docs/doxygen-user" or die "cannot change into docs/doxygen-user directory";
open (CONF_IN, "<${orig}") or die "Cannot open ${orig}";
open (CONF_OUT, ">${temp}") or die "Cannot open ${temp}";
my $found = 0;
while (<CONF_IN>) {
if (/^PROJECT_NUMBER/) {
print CONF_OUT "PROJECT_NUMBER = ${VER}\n";
$found++;
}
elsif (/^HTML_OUTPUT/) {
print CONF_OUT "HTML_OUTPUT = ${VER}\n";
$found++;
}
else {
print CONF_OUT $_;
}
}
close (CONF_IN);
close (CONF_OUT);
if ($found != 2) {
die "$found (instead of 2) occurrences of version found in (USER) ${orig}";
}
unlink ($orig) or die "Error deleting ${orig}";
rename ($temp, $orig) or die "Error renaming tmp $orig file";
system("git add ${orig}") unless ($TESTING);
chdir "../.." or die "Error changing directories back to root";
}
main();

View File

@ -1,199 +0,0 @@
#!/usr/bin/perl
# Updates various TSK version numbers
# use this when the version of TSK that Autopsy depends on changes
use strict;
use File::Copy;
# global variables
my $VER;
my $TESTING = 0;
print "TESTING MODE (no commits)\n" if ($TESTING);
sub main {
# Get the TSK version argument
if (scalar (@ARGV) != 1) {
print stderr "Missing release version argument (i.e. 4.9.0)\n";
exit;
}
$VER = $ARGV[0];
die "Invalid version number: $VER (1.2.3 or 1.2.3b1 expected)" unless ($VER =~ /^\d+\.\d+\.\d+(b\d+)?$/);
# Assume we running out of 'release' folder
chdir ".." or die "Error changing directories to root";
# Update the version info in that tag
update_tsk_version();
update_core_project_properties();
update_core_project_xml();
print "Files updated. You need to commit and push them\n";
}
######################################################
# Utility functions
# Function to execute a command and send output to pipe
# returns handle
# exec_pipe(HANDLE, CMD);
sub exec_pipe {
my $handle = shift(@_);
my $cmd = shift(@_);
die "Can't open pipe for exec_pipe"
unless defined(my $pid = open($handle, '-|'));
if ($pid) {
return $handle;
}
else {
$| = 1;
exec("$cmd") or die "Can't exec program: $!";
}
}
# Read a line of text from an open exec_pipe handle
sub read_pipe_line {
my $handle = shift(@_);
my $out;
for (my $i = 0; $i < 100; $i++) {
$out = <$handle>;
return $out if (defined $out);
}
return $out;
}
#############################################
# File update methods
# update the tskversion.xml
sub update_tsk_version {
my $orig = "TSKVersion.xml";
my $temp = "${orig}-bak";
print "Updating the version in ${orig}\n";
open (CONF_IN, "<${orig}") or die "Cannot open ${orig}";
open (CONF_OUT, ">${temp}") or die "Cannot open ${temp}";
my $found = 0;
while (<CONF_IN>) {
if (/name="TSK_VERSION" value=/) {
print CONF_OUT " <property name=\"TSK_VERSION\" value=\"${VER}\"/>\n";
$found++;
}
else {
print CONF_OUT $_;
}
}
close (CONF_IN);
close (CONF_OUT);
if ($found != 1) {
die "$found (instead of 1) occurrences of app.version found in ${orig}";
}
unlink ($orig) or die "Error deleting ${orig}";
rename ($temp, $orig) or die "Error renaming tmp $orig file";
system("git add ${orig}") unless ($TESTING);
}
sub update_core_project_properties {
my $orig = "project.properties";
my $temp = "${orig}-bak";
print "Updating the version in ${orig}\n";
chdir "Core/nbproject" or die "cannot change into Core/nbproject directory";
open (CONF_IN, "<${orig}") or die "Cannot open ${orig}";
open (CONF_OUT, ">${temp}") or die "Cannot open ${temp}";
my $found = 0;
while (<CONF_IN>) {
if (/^file\.reference\.sleuthkit\-postgresql-/) {
print CONF_OUT "file.reference.sleuthkit-postgresql-${VER}.jar=release/modules/ext/sleuthkit-postgresql-${VER}.jar\n";
$found++;
}
else {
print CONF_OUT $_;
}
}
close (CONF_IN);
close (CONF_OUT);
if ($found != 1) {
die "$found (instead of 1) occurrences of version found in ${orig}";
}
unlink ($orig) or die "Error deleting ${orig}";
rename ($temp, $orig) or die "Error renaming tmp $orig file";
system("git add ${orig}") unless ($TESTING);
chdir "../.." or die "Error changing directories back to root";
}
sub update_core_project_xml {
my $orig = "project.xml";
my $temp = "${orig}-bak";
print "Updating the version in ${orig}\n";
chdir "Core/nbproject" or die "cannot change into Core/nbproject directory";
open (CONF_IN, "<${orig}") or die "Cannot open ${orig}";
open (CONF_OUT, ">${temp}") or die "Cannot open ${temp}";
my $found = 0;
while (<CONF_IN>) {
if (/<runtime-relative-path>ext\/sleuthkit-postgresql/) {
print CONF_OUT " <runtime-relative-path>ext/sleuthkit-postgresql-${VER}.jar</runtime-relative-path>\n";
$found++;
}
elsif (/<binary-origin>release\/modules\/ext\/sleuthkit-postgresql/) {
print CONF_OUT " <binary-origin>release/modules/ext/sleuthkit-postgresql-${VER}.jar</binary-origin>\n";
$found++;
}
else {
print CONF_OUT $_;
}
}
close (CONF_IN);
close (CONF_OUT);
if ($found != 2) {
die "$found (instead of 2) occurrences of version found in ${orig}";
}
unlink ($orig) or die "Error deleting ${orig}";
rename ($temp, $orig) or die "Error renaming tmp $orig file";
system("git add ${orig}") unless ($TESTING);
chdir "../.." or die "Error changing directories back to root";
}
main();