diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 46e9dad2bc..03816fc64c 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -78,7 +78,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ReportAddedEvent; import org.sleuthkit.autopsy.casemodule.services.Services; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeSearchAction; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeSearchAction; import org.sleuthkit.autopsy.communications.OpenCommVisualizationToolAction; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CategoryNode; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index 760b7df5e2..0892f24335 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -621,8 +621,8 @@ abstract class AbstractSqlEamDb implements EamDb { Connection conn = connect(); PreparedStatement preparedStatement = null; - //The conflict clause exists incase multiple nodes are trying to add the datasource because it did not exist at the same time - String sql = "INSERT INTO data_sources(device_id, case_id, name, datasource_obj_id) VALUES (?, ?, ?, ?) " + //The conflict clause exists in case multiple nodes are trying to add the data source because it did not exist at the same time + String sql = "INSERT INTO data_sources(device_id, case_id, name, datasource_obj_id, md5, sha1, sha256) VALUES (?, ?, ?, ?, ?, ?, ?) " + getConflictClause(); ResultSet resultSet = null; try { @@ -632,6 +632,9 @@ abstract class AbstractSqlEamDb implements EamDb { preparedStatement.setInt(2, eamDataSource.getCaseID()); preparedStatement.setString(3, eamDataSource.getName()); preparedStatement.setLong(4, eamDataSource.getDataSourceObjectID()); + preparedStatement.setString(5, eamDataSource.getMd5()); + preparedStatement.setString(6, eamDataSource.getSha1()); + preparedStatement.setString(7, eamDataSource.getSha256()); preparedStatement.executeUpdate(); resultSet = preparedStatement.getGeneratedKeys(); @@ -647,11 +650,12 @@ abstract class AbstractSqlEamDb implements EamDb { } else { //if a new data source was added to the central repository update the caches to include it and return it int dataSourceId = resultSet.getInt(1); //last_insert_rowid() - CorrelationDataSource dataSource = new CorrelationDataSource(eamDataSource.getCaseID(), dataSourceId, eamDataSource.getDeviceID(), eamDataSource.getName(), eamDataSource.getDataSourceObjectID()); + CorrelationDataSource dataSource = new CorrelationDataSource(eamDataSource.getCaseID(), dataSourceId, eamDataSource.getDeviceID(), eamDataSource.getName(), eamDataSource.getDataSourceObjectID(), eamDataSource.getMd5(), eamDataSource.getSha1(), eamDataSource.getSha256()); dataSourceCacheByDsObjectId.put(getDataSourceByDSObjectIdCacheKey(dataSource.getCaseID(), dataSource.getDataSourceObjectID()), dataSource); dataSourceCacheById.put(getDataSourceByIdCacheKey(dataSource.getCaseID(), dataSource.getID()), dataSource); return dataSource; } + } catch (SQLException ex) { throw new EamDbException("Error inserting new data source.", ex); // NON-NLS } finally { @@ -828,6 +832,73 @@ abstract class AbstractSqlEamDb implements EamDb { return dataSources; } + + /** + * Updates the MD5 hash value in an existing data source in the database. + * + * @param eamDataSource The data source to update + */ + @Override + public void updateDataSourceMd5Hash(CorrelationDataSource eamDataSource) throws EamDbException { + updateDataSourceStringValue(eamDataSource, "md5", eamDataSource.getMd5()); + } + + /** + * Updates the SHA-1 hash value in an existing data source in the database. + * + * @param eamDataSource The data source to update + */ + @Override + public void updateDataSourceSha1Hash(CorrelationDataSource eamDataSource) throws EamDbException { + updateDataSourceStringValue(eamDataSource, "sha1", eamDataSource.getSha1()); + } + + /** + * Updates the SHA-256 hash value in an existing data source in the database. + * + * @param eamDataSource The data source to update + */ + @Override + public void updateDataSourceSha256Hash(CorrelationDataSource eamDataSource) throws EamDbException { + updateDataSourceStringValue(eamDataSource, "sha256", eamDataSource.getSha256()); + } + + /** + * Updates the specified value in an existing data source in the database. + * + * @param eamDataSource The data source to update + * @param column The name of the column to be updated + * @param value The value to assign to the specified column + */ + private void updateDataSourceStringValue(CorrelationDataSource eamDataSource, String column, String value) throws EamDbException { + if (eamDataSource == null) { + throw new EamDbException("Correlation data source is null"); + } + + Connection conn = connect(); + + PreparedStatement preparedStatement = null; + String sql = "UPDATE data_sources " + + "SET " + column + "=? " + + "WHERE id=?"; + + try { + preparedStatement = conn.prepareStatement(sql); + + preparedStatement.setString(1, value); + preparedStatement.setInt(2, eamDataSource.getID()); + + preparedStatement.executeUpdate(); + //update the case in the cache + dataSourceCacheByDsObjectId.put(getDataSourceByDSObjectIdCacheKey(eamDataSource.getCaseID(), eamDataSource.getDataSourceObjectID()), eamDataSource); + dataSourceCacheById.put(getDataSourceByIdCacheKey(eamDataSource.getCaseID(), eamDataSource.getID()), eamDataSource); + } catch (SQLException ex) { + throw new EamDbException(String.format("Error updating data source (obj_id=%d).", eamDataSource.getDataSourceObjectID()), ex); // NON-NLS + } finally { + EamDbUtil.closeStatement(preparedStatement); + EamDbUtil.closeConnection(conn); + } + } /** * Inserts new Artifact(s) into the database. Should add associated Case and @@ -941,7 +1012,7 @@ abstract class AbstractSqlEamDb implements EamDb { + ".value," + tableName + ".file_obj_id," - + " cases.case_name, cases.case_uid, data_sources.id AS data_source_id, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, data_sources.datasource_obj_id FROM " + + " cases.case_name, cases.case_uid, data_sources.id AS data_source_id, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, data_sources.datasource_obj_id, data_sources.md5, data_sources.sha1, data_sources.sha256 FROM " + tableName + " LEFT JOIN cases ON " + tableName @@ -1006,7 +1077,7 @@ abstract class AbstractSqlEamDb implements EamDb { + ".value," + tableName + ".file_obj_id," - + " cases.case_name, cases.case_uid, data_sources.id AS data_source_id, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, data_sources.datasource_obj_id FROM " + + " cases.case_name, cases.case_uid, data_sources.id AS data_source_id, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, data_sources.datasource_obj_id, data_sources.md5, data_sources.sha1, data_sources.sha256 FROM " + tableName + " LEFT JOIN cases ON " + tableName @@ -1731,7 +1802,7 @@ abstract class AbstractSqlEamDb implements EamDb { + ".value, " + tableName + ".file_obj_id," - + "cases.case_name, cases.case_uid, data_sources.id AS data_source_id, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, data_sources.datasource_obj_id FROM " + + "cases.case_name, cases.case_uid, data_sources.id AS data_source_id, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, data_sources.datasource_obj_id, data_sources.md5, data_sources.sha1, data_sources.sha256 FROM " + tableName + " LEFT JOIN cases ON " + tableName @@ -1788,7 +1859,7 @@ abstract class AbstractSqlEamDb implements EamDb { String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType); String sql - = "SELECT cases.case_name, cases.case_uid, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, id, value, file_obj_id, data_sources.datasource_obj_id FROM " + = "SELECT cases.case_name, cases.case_uid, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, id, value, file_obj_id, data_sources.datasource_obj_id, data_sources.md5, data_sources.sha1, data_sources.sha256 FROM " + tableName + " LEFT JOIN cases ON " + tableName @@ -3071,7 +3142,10 @@ abstract class AbstractSqlEamDb implements EamDb { resultSet.getInt("id"), resultSet.getString("device_id"), resultSet.getString("name"), - resultSet.getLong("datasource_obj_id") + resultSet.getLong("datasource_obj_id"), + resultSet.getString("md5"), + resultSet.getString("sha1"), + resultSet.getString("sha256") ); return eamDataSource; @@ -3112,7 +3186,9 @@ abstract class AbstractSqlEamDb implements EamDb { resultSet.getString("value"), resultSet.getInt("id"), new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), resultSet.getString("case_name")), - new CorrelationDataSource(resultSet.getInt("case_id"), resultSet.getInt("data_source_id"), resultSet.getString("device_id"), resultSet.getString("name"), resultSet.getLong("datasource_obj_id")), + new CorrelationDataSource( + resultSet.getInt("case_id"), resultSet.getInt("data_source_id"), resultSet.getString("device_id"), resultSet.getString("name"), + resultSet.getLong("datasource_obj_id"), resultSet.getString("md5"), resultSet.getString("sha1"), resultSet.getString("sha256")), resultSet.getString("file_path"), resultSet.getString("comment"), TskData.FileKnown.valueOf(resultSet.getByte("known_status")), diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationDataSource.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationDataSource.java index 5b38c8a39e..03175347ca 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationDataSource.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationDataSource.java @@ -1,7 +1,7 @@ /* * Central Repository * - * Copyright 2015-2018 Basis Technology Corp. + * Copyright 2015-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,6 +22,7 @@ import java.io.Serializable; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskDataException; @@ -39,20 +40,31 @@ public class CorrelationDataSource implements Serializable { private final Long dataSourceObjectID; //< Id for data source in the caseDB private final String deviceID; //< Unique to its associated case (not necessarily globally unique) private final String name; + private String md5Hash; + private String sha1Hash; + private String sha256Hash; /** - * Create a CorrelationDataSource object, the object will not have the data - * source id for the row in the central repository. + * Create a CorrelationDataSource object. * * @param correlationCase CorrelationCase object data source is * associated with. Must have been created by * EamDB and have a valid ID. - * @param deviceId User specified case-specific ID - * @param name Display name of data source + * @param deviceId User specified ID for device (unique per case) + * @param name User specified name * @param dataSourceObjectId The object ID for the datasource + * @param md5Hash The MD5 hash value + * @param sha1Hash The SHA-1 hash value + * @param sha256Hash The SHA-256 hash value */ - public CorrelationDataSource(CorrelationCase correlationCase, String deviceId, String name, long dataSourceObjectId) { - this(correlationCase.getID(), -1, deviceId, name, dataSourceObjectId); + public CorrelationDataSource(CorrelationCase correlationCase, + String deviceId, + String name, + Long dataSourceObjectId, + String md5Hash, + String sha1Hash, + String sha256Hash) { + this(correlationCase.getID(), -1, deviceId, name, dataSourceObjectId, md5Hash, sha1Hash, sha256Hash); } /** @@ -63,17 +75,26 @@ public class CorrelationDataSource implements Serializable { * @param deviceId User specified ID for device (unique per case) * @param name User specified name * @param dataSourceObjectId The object ID for the datasource + * @param md5Hash The MD5 hash value + * @param sha1Hash The SHA-1 hash value + * @param sha256Hash The SHA-256 hash value */ CorrelationDataSource(int caseId, int dataSourceId, String deviceId, String name, - Long dataSourceObjectId) { + Long dataSourceObjectId, + String md5Hash, + String sha1Hash, + String sha256Hash) { this.caseID = caseId; this.dataSourceID = dataSourceId; this.deviceID = deviceId; this.name = name; this.dataSourceObjectID = dataSourceObjectId; + this.md5Hash = md5Hash; + this.sha1Hash = sha1Hash; + this.sha256Hash = sha256Hash; } /** @@ -105,12 +126,23 @@ public class CorrelationDataSource implements Serializable { if (correlationDataSource == null) { String deviceId; + String md5 = null; + String sha1 = null; + String sha256 = null; try { deviceId = curCase.getSleuthkitCase().getDataSource(dataSource.getId()).getDeviceId(); + + if (dataSource instanceof Image) { + Image image = (Image) dataSource; + md5 = image.getMd5(); + sha1 = image.getSha1(); + sha256 = image.getSha256(); + } } catch (TskDataException | TskCoreException ex) { throw new EamDbException("Error getting data source info: " + ex.getMessage()); } - correlationDataSource = new CorrelationDataSource(correlationCase, deviceId, dataSource.getName(), dataSource.getId()); + + correlationDataSource = new CorrelationDataSource(correlationCase, deviceId, dataSource.getName(), dataSource.getId(), md5, sha1, sha256); if (useCR) { //add the correlation data source to the central repository and fill in the Central repository data source id in the object correlationDataSource = EamDb.getInstance().newDataSource(correlationDataSource); @@ -173,4 +205,69 @@ public class CorrelationDataSource implements Serializable { public String getName() { return name; } + + /** + * @return the MD5 hash value + */ + public String getMd5() { + return (md5Hash == null ? "" : md5Hash); + } + + /** + * Set the MD5 hash value and persist to the Central Repository if available. + * + * @param md5Hash The MD5 hash value. + * + * @exception EamDbException If there's an issue updating the Central + * Repository. + */ + public void setMd5(String md5Hash) throws EamDbException { + this.md5Hash = md5Hash; + + if (dataSourceObjectID != -1) { + EamDb.getInstance().updateDataSourceMd5Hash(this); + } + } + + /** + * @return the SHA-1 hash value + */ + public String getSha1() { + return (sha1Hash == null ? "" : sha1Hash); + } + + /** + * Set the SHA-1 hash value and persist to the Central Repository if + * available. + * + * @param sha1Hash The SHA-1 hash value. + */ + public void setSha1(String sha1Hash) throws EamDbException { + this.sha1Hash = sha1Hash; + + if (dataSourceObjectID != -1) { + EamDb.getInstance().updateDataSourceSha1Hash(this); + } + } + + /** + * @return the SHA-256 hash value + */ + public String getSha256() { + return (sha256Hash == null ? "" : sha256Hash); + } + + /** + * Set the SHA-256 hash value and persist to the Central Repository if + * available. + * + * @param sha256Hash The SHA-256 hash value. + */ + public void setSha256(String sha256Hash) throws EamDbException { + this.sha256Hash = sha256Hash; + + if (dataSourceObjectID != -1) { + EamDb.getInstance().updateDataSourceSha256Hash(this); + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DataSourceUpdateService.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DataSourceUpdateService.java index 46696bad94..f1e52b03e4 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DataSourceUpdateService.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DataSourceUpdateService.java @@ -65,4 +65,4 @@ public class DataSourceUpdateService implements AutopsyService { } } -} +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java index c633dc5adc..ddd10b2b0e 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java @@ -1,7 +1,7 @@ /* * Central Repository * - * Copyright 2015-2018 Basis Technology Corp. + * Copyright 2015-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -204,6 +204,27 @@ public interface EamDb { * @return - A CorrelationDataSource object with data source's central repository id */ CorrelationDataSource newDataSource(CorrelationDataSource eamDataSource) throws EamDbException; + + /** + * Updates the MD5 hash value in an existing data source in the database. + * + * @param eamDataSource The data source to update + */ + void updateDataSourceMd5Hash(CorrelationDataSource eamDataSource) throws EamDbException; + + /** + * Updates the SHA-1 hash value in an existing data source in the database. + * + * @param eamDataSource The data source to update + */ + void updateDataSourceSha1Hash(CorrelationDataSource eamDataSource) throws EamDbException; + + /** + * Updates the SHA-256 hash value in an existing data source in the database. + * + * @param eamDataSource The data source to update + */ + void updateDataSourceSha256Hash(CorrelationDataSource eamDataSource) throws EamDbException; /** * Retrieves Data Source details based on data source device ID diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java index 69826a3355..2996a5be15 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java @@ -1,7 +1,7 @@ /* * Central Repository * - * Copyright 2015-2018 Basis Technology Corp. + * Copyright 2015-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -433,6 +433,51 @@ final class SqliteEamDb extends AbstractSqlEamDb { releaseSharedLock(); } } + + /** + * Updates the MD5 hash value in an existing data source in the database. + * + * @param eamDataSource The data source to update + */ + @Override + public void updateDataSourceMd5Hash(CorrelationDataSource eamDataSource) throws EamDbException { + try { + acquireExclusiveLock(); + super.updateDataSourceMd5Hash(eamDataSource); + } finally { + releaseExclusiveLock(); + } + } + + /** + * Updates the SHA-1 hash value in an existing data source in the database. + * + * @param eamDataSource The data source to update + */ + @Override + public void updateDataSourceSha1Hash(CorrelationDataSource eamDataSource) throws EamDbException { + try { + acquireExclusiveLock(); + super.updateDataSourceSha1Hash(eamDataSource); + } finally { + releaseExclusiveLock(); + } + } + + /** + * Updates the SHA-256 hash value in an existing data source in the database. + * + * @param eamDataSource The data source to update + */ + @Override + public void updateDataSourceSha256Hash(CorrelationDataSource eamDataSource) throws EamDbException { + try { + acquireExclusiveLock(); + super.updateDataSourceSha256Hash(eamDataSource); + } finally { + releaseExclusiveLock(); + } + } /** * Inserts new Artifact(s) into the database. Should add associated Case and diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java index 1dc66b0bf6..37f0f595cb 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java @@ -1,7 +1,7 @@ /* * Central Repository * - * Copyright 2015-2018 Basis Technology Corp. + * Copyright 2015-2019 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -30,6 +30,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.logging.Level; import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -40,6 +41,8 @@ import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; +import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase; +import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource; import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.datamodel.AbstractFile; @@ -48,6 +51,9 @@ import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.coreutils.ThreadUtils; +import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.SleuthkitCase; /** @@ -294,6 +300,8 @@ public class IngestEventsListener { jobProcessingExecutor.submit(new DataAddedTask(dbManager, evt, flagNotable, flagPrevious, createAttributes)); break; } + default: + break; } } } @@ -303,17 +311,35 @@ public class IngestEventsListener { @Override public void propertyChange(PropertyChangeEvent evt) { + EamDb dbManager; + try { + dbManager = EamDb.getInstance(); + } catch (EamDbException ex) { + LOGGER.log(Level.SEVERE, "Failed to connect to Central Repository database.", ex); + return; + } + switch (IngestManager.IngestJobEvent.valueOf(evt.getPropertyName())) { case DATA_SOURCE_ANALYSIS_COMPLETED: { - jobProcessingExecutor.submit(new AnalysisCompleteTask()); + jobProcessingExecutor.submit(new AnalysisCompleteTask(dbManager, evt)); break; } + default: + break; } } } private final class AnalysisCompleteTask implements Runnable { + + private final EamDb dbManager; + private final PropertyChangeEvent event; + + private AnalysisCompleteTask(EamDb db, PropertyChangeEvent evt) { + dbManager = db; + event = evt; + } @Override public void run() { @@ -322,6 +348,86 @@ public class IngestEventsListener { recentlyAddedCeArtifacts.clear(); } //else another instance of the Correlation Engine Module is still being run. + + /* + * Ensure the data source in the Central Repository has hash values + * that match those in the case database. + */ + if (!EamDb.isEnabled()) { + return; + } + Content dataSource; + String dataSourceName = ""; + long dataSourceObjectId = -1; + try { + dataSource = ((DataSourceAnalysisCompletedEvent) event).getDataSource(); + + /* + * We only care about Images for the purpose of + * updating hash values. + */ + if (!(dataSource instanceof Image)) { + return; + } + + dataSourceName = dataSource.getName(); + dataSourceObjectId = dataSource.getId(); + + Case openCase = Case.getCurrentCaseThrows(); + + CorrelationCase correlationCase = dbManager.getCase(openCase); + if (null == correlationCase) { + correlationCase = dbManager.newCase(openCase); + } + + CorrelationDataSource correlationDataSource = dbManager.getDataSource(correlationCase, dataSource.getId()); + if (correlationDataSource == null) { + // Add the data source. + CorrelationDataSource.fromTSKDataSource(correlationCase, dataSource); + } else { + // Sync the data source hash values if necessary. + if (dataSource instanceof Image) { + Image image = (Image) dataSource; + + String imageMd5Hash = image.getMd5(); + if (imageMd5Hash == null) { + imageMd5Hash = ""; + } + String crMd5Hash = correlationDataSource.getMd5(); + if (StringUtils.equals(imageMd5Hash, crMd5Hash) == false) { + correlationDataSource.setMd5(imageMd5Hash); + } + + String imageSha1Hash = image.getSha1(); + if (imageSha1Hash == null) { + imageSha1Hash = ""; + } + String crSha1Hash = correlationDataSource.getSha1(); + if (StringUtils.equals(imageSha1Hash, crSha1Hash) == false) { + correlationDataSource.setSha1(imageSha1Hash); + } + + String imageSha256Hash = image.getSha256(); + if (imageSha256Hash == null) { + imageSha256Hash = ""; + } + String crSha256Hash = correlationDataSource.getSha256(); + if (StringUtils.equals(imageSha256Hash, crSha256Hash) == false) { + correlationDataSource.setSha256(imageSha256Hash); + } + } + } + } catch (EamDbException ex) { + LOGGER.log(Level.SEVERE, String.format( + "Unable to fetch data from the Central Repository for data source '%s' (obj_id=%d)", + dataSourceName, dataSourceObjectId), ex); + } catch (NoCurrentCaseException ex) { + LOGGER.log(Level.SEVERE, "No current case opened.", ex); + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, String.format( + "Unable to fetch data from the case database for data source '%s' (obj_id=%d)", + dataSourceName, dataSourceObjectId), ex); + } } // DATA_SOURCE_ANALYSIS_COMPLETED } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AbstractCommonAttributeInstance.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/AbstractCommonAttributeInstance.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/AbstractCommonAttributeInstance.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/AbstractCommonAttributeInstance.java index 472acf4dac..f657173d8a 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AbstractCommonAttributeInstance.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/AbstractCommonAttributeInstance.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AbstractCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/AbstractCommonAttributeSearcher.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/AbstractCommonAttributeSearcher.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/AbstractCommonAttributeSearcher.java index a486097e1a..00a4a0f653 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AbstractCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/AbstractCommonAttributeSearcher.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.sql.SQLException; import java.util.ArrayList; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllInterCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/AllInterCaseCommonAttributeSearcher.java similarity index 96% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/AllInterCaseCommonAttributeSearcher.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/AllInterCaseCommonAttributeSearcher.java index 7e28b1dcec..e718c01041 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllInterCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/AllInterCaseCommonAttributeSearcher.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.sql.SQLException; import java.util.HashSet; @@ -29,7 +29,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance.Type; -import static org.sleuthkit.autopsy.commonfilesearch.AbstractCommonAttributeSearcher.MEDIA_PICS_VIDEO_MIME_TYPES; +import static org.sleuthkit.autopsy.commonpropertiessearch.AbstractCommonAttributeSearcher.MEDIA_PICS_VIDEO_MIME_TYPES; /** * Algorithm which finds files anywhere in the Central Repo which also occur in diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllIntraCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/AllIntraCaseCommonAttributeSearcher.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/AllIntraCaseCommonAttributeSearcher.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/AllIntraCaseCommonAttributeSearcher.java index f7a954aee0..090b233b36 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/AllIntraCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/AllIntraCaseCommonAttributeSearcher.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.Map; import org.openide.util.NbBundle; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/Bundle.properties similarity index 100% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/Bundle.properties rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/Bundle.properties diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CaseDBCommonAttributeInstance.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CaseDBCommonAttributeInstance.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/CaseDBCommonAttributeInstance.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CaseDBCommonAttributeInstance.java index 141d5427cd..33371f2f7d 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CaseDBCommonAttributeInstance.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CaseDBCommonAttributeInstance.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.Arrays; import java.util.logging.Level; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CaseDBCommonAttributeInstanceNode.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CaseDBCommonAttributeInstanceNode.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/CaseDBCommonAttributeInstanceNode.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CaseDBCommonAttributeInstanceNode.java index ac9cb360aa..e98ba37ce5 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CaseDBCommonAttributeInstanceNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CaseDBCommonAttributeInstanceNode.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.Arrays; import java.util.HashSet; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CentralRepoCommonAttributeInstance.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CentralRepoCommonAttributeInstance.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/CentralRepoCommonAttributeInstance.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CentralRepoCommonAttributeInstance.java index 6c308c3e7c..55fef1a033 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CentralRepoCommonAttributeInstance.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CentralRepoCommonAttributeInstance.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.io.File; import java.util.ArrayList; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CentralRepoCommonAttributeInstanceNode.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CentralRepoCommonAttributeInstanceNode.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/CentralRepoCommonAttributeInstanceNode.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CentralRepoCommonAttributeInstanceNode.java index 8ec5ad3a3b..62b0e0fe53 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CentralRepoCommonAttributeInstanceNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CentralRepoCommonAttributeInstanceNode.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.io.File; import java.util.ArrayList; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeCaseSearchResults.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeCaseSearchResults.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeCaseSearchResults.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeCaseSearchResults.java index 66876c190a..0b61923044 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeCaseSearchResults.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeCaseSearchResults.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.Collections; import java.util.HashMap; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeCountSearchResults.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeCountSearchResults.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeCountSearchResults.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeCountSearchResults.java index b39082582c..20751264b7 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeCountSearchResults.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeCountSearchResults.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.ArrayList; import java.util.Collections; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributePanel.form similarity index 89% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributePanel.form index 04df198c0f..74ebe1bd30 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.form +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributePanel.form @@ -158,7 +158,7 @@ - + @@ -166,7 +166,7 @@ - + @@ -178,7 +178,7 @@ - + @@ -191,7 +191,7 @@ - + @@ -222,7 +222,7 @@ - + @@ -233,7 +233,7 @@ - + @@ -249,14 +249,14 @@ - + - + @@ -266,7 +266,7 @@ - + @@ -274,7 +274,7 @@ - + @@ -290,7 +290,7 @@ - + @@ -303,14 +303,14 @@ - + - + diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributePanel.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributePanel.java index 7bf22a7d63..72086983de 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributePanel.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import org.sleuthkit.autopsy.guiutils.DataSourceComboBoxModel; import org.sleuthkit.autopsy.datamodel.utils.DataSourceLoader; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchAction.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeSearchAction.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchAction.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeSearchAction.java index c32f30d4bd..f53b96a38b 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchAction.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeSearchAction.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.awt.event.ActionEvent; import java.util.concurrent.ExecutionException; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResultRootNode.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeSearchResultRootNode.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResultRootNode.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeSearchResultRootNode.java index f24f249255..6576c9219f 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResultRootNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeSearchResultRootNode.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.List; import java.util.Map; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValue.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeValue.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValue.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeValue.java index 254ff26971..d86eff5a4f 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValue.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeValue.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.ArrayList; import java.util.Collection; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValueList.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeValueList.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValueList.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeValueList.java index 01690b357b..513196ed98 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValueList.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeValueList.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.ArrayList; import java.util.Collections; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValueNode.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeValueNode.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValueNode.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeValueNode.java index 3a130c8aaa..d149847d78 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeValueNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeValueNode.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.List; import org.openide.nodes.ChildFactory; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributesSearchResultsViewerTable.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributesSearchResultsViewerTable.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributesSearchResultsViewerTable.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributesSearchResultsViewerTable.java index 5fb0906ac7..095615af7b 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributesSearchResultsViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributesSearchResultsViewerTable.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.Collections; import java.util.Enumeration; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCaseNode.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCaseNode.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCaseNode.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCaseNode.java index 92429437c1..6e8a720d49 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCaseNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCaseNode.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.HashMap; import java.util.List; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCountNode.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCountNode.java index 93f3ab346c..29f817210d 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCountNode.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.HashMap; import java.util.Iterator; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNodeTreeExpansionListener.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCountNodeTreeExpansionListener.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNodeTreeExpansionListener.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCountNodeTreeExpansionListener.java index f016cc3c8f..38094ba0cc 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceCountNodeTreeExpansionListener.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceCountNodeTreeExpansionListener.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeExpansionListener; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceDataSourceNode.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceDataSourceNode.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceDataSourceNode.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceDataSourceNode.java index ea4f8e50e7..8de44c415e 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InstanceDataSourceNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InstanceDataSourceNode.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.List; import org.openide.nodes.ChildFactory; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseCommonAttributeSearcher.java similarity index 97% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCaseCommonAttributeSearcher.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseCommonAttributeSearcher.java index 56e28da3dc..381ccf441c 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseCommonAttributeSearcher.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.form b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.form similarity index 81% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.form rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.form index 167e9acd48..f878323524 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.form +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.form @@ -100,7 +100,7 @@ - + @@ -110,7 +110,7 @@ - + @@ -123,7 +123,7 @@ - + @@ -136,10 +136,10 @@ - + - + @@ -153,10 +153,10 @@ - + - + @@ -168,7 +168,7 @@ - + @@ -180,7 +180,7 @@ - + @@ -191,7 +191,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java index 2cb94571ae..2c6100a42c 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCasePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import org.sleuthkit.autopsy.guiutils.DataSourceComboBoxModel; import java.util.Collections; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCaseSearchResultsProcessor.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseSearchResultsProcessor.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCaseSearchResultsProcessor.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseSearchResultsProcessor.java index 51e968c716..2c54ad65a4 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCaseSearchResultsProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseSearchResultsProcessor.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.sql.ResultSet; import java.sql.SQLException; @@ -34,7 +34,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil; import org.sleuthkit.autopsy.centralrepository.datamodel.InstanceTableCallback; -import org.sleuthkit.autopsy.commonfilesearch.AbstractCommonAttributeInstance.NODE_TYPE; +import org.sleuthkit.autopsy.commonpropertiessearch.AbstractCommonAttributeInstance.NODE_TYPE; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.HashUtility; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/IntraCaseCommonAttributeSearcher.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCaseCommonAttributeSearcher.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/IntraCaseCommonAttributeSearcher.java index b22e77cc61..f48d23d030 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/IntraCaseCommonAttributeSearcher.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.sql.ResultSet; import java.sql.SQLException; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.form b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/IntraCasePanel.form similarity index 83% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.form rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/IntraCasePanel.form index be311f3e46..d4a11098bb 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.form +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/IntraCasePanel.form @@ -89,7 +89,7 @@ - + @@ -100,10 +100,10 @@ - + - + @@ -114,7 +114,7 @@ - + @@ -126,7 +126,7 @@ - + @@ -141,10 +141,10 @@ - + - + @@ -154,7 +154,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/IntraCasePanel.java similarity index 99% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/IntraCasePanel.java index fd8f9becac..d0c7ab1579 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/IntraCasePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/IntraCasePanel.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import org.sleuthkit.autopsy.guiutils.DataSourceComboBoxModel; import java.util.Collections; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleInterCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/SingleInterCaseCommonAttributeSearcher.java similarity index 96% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleInterCaseCommonAttributeSearcher.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/SingleInterCaseCommonAttributeSearcher.java index 7347005425..8129acaf16 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleInterCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/SingleInterCaseCommonAttributeSearcher.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.sql.SQLException; import java.util.HashSet; @@ -30,7 +30,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance.Type; -import static org.sleuthkit.autopsy.commonfilesearch.AbstractCommonAttributeSearcher.MEDIA_PICS_VIDEO_MIME_TYPES; +import static org.sleuthkit.autopsy.commonpropertiessearch.AbstractCommonAttributeSearcher.MEDIA_PICS_VIDEO_MIME_TYPES; /** * diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleIntraCaseCommonAttributeSearcher.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/SingleIntraCaseCommonAttributeSearcher.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleIntraCaseCommonAttributeSearcher.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/SingleIntraCaseCommonAttributeSearcher.java index 7e685d4f53..5d4dbd8c8e 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/SingleIntraCaseCommonAttributeSearcher.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/SingleIntraCaseCommonAttributeSearcher.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.Map; import org.openide.util.NbBundle; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/UserInputErrorManager.java similarity index 98% rename from Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java rename to Core/src/org/sleuthkit/autopsy/commonpropertiessearch/UserInputErrorManager.java index 3e09e32193..c2f4285789 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/UserInputErrorManager.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/UserInputErrorManager.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilesearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.util.HashMap; import java.util.List; diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/PlatformUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/PlatformUtil.java index a785bdf638..88e33c7407 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/PlatformUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/PlatformUtil.java @@ -36,6 +36,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.swing.filechooser.FileSystemView; +import org.apache.commons.io.FilenameUtils; import org.hyperic.sigar.Sigar; import org.hyperic.sigar.ptql.ProcessFinder; import org.openide.modules.InstalledFileLocator; @@ -53,6 +54,7 @@ public class PlatformUtil { private static final String PYTHON_MODULES_SUBDIRECTORY = "python_modules"; //NON-NLS private static final String CLASSIFIERS_SUBDIRECTORY = "object_detection_classifiers"; //NON-NLS private static final String OCR_LANGUAGE_SUBDIRECTORY = "ocr_language_packs"; //NON-NLS + private static final String OCR_LANGUAGE_PACK_EXT = "traineddata"; private static String javaPath = null; public static final String OS_NAME_UNKNOWN = NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.nameUnknown"); public static final String OS_VERSION_UNKNOWN = NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.verUnknown"); @@ -126,6 +128,26 @@ public class PlatformUtil { public static String getOcrLanguagePacksPath() { return getUserDirectory().getAbsolutePath() + File.separator + OCR_LANGUAGE_SUBDIRECTORY; } + + /** + * Get the names of the language packs installed at the user directory. + * + * @return List of language packs base names + */ + public static List getOcrLanguagePacks() { + File languagePackRootDir = new File(getOcrLanguagePacksPath()); + + List languagePacks = new ArrayList<>(); + for (File languagePack : languagePackRootDir.listFiles()) { + String fileExt = FilenameUtils.getExtension(languagePack.getName()); + if (!languagePack.isDirectory() && OCR_LANGUAGE_PACK_EXT.equals(fileExt)) { + String packageName = FilenameUtils.getBaseName(languagePack.getName()); + languagePacks.add(packageName); + } + } + + return languagePacks; + } /** * Get root path where the user's object detection classifiers are stored. diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index f9b7690f4c..bb324bc7bb 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -18,13 +18,13 @@ */ package org.sleuthkit.autopsy.datamodel; -import org.sleuthkit.autopsy.commonfilesearch.CentralRepoCommonAttributeInstanceNode; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeSearchResultRootNode; -import org.sleuthkit.autopsy.commonfilesearch.InstanceCountNode; -import org.sleuthkit.autopsy.commonfilesearch.InstanceCaseNode; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeValueNode; -import org.sleuthkit.autopsy.commonfilesearch.CaseDBCommonAttributeInstanceNode; -import org.sleuthkit.autopsy.commonfilesearch.InstanceDataSourceNode; +import org.sleuthkit.autopsy.commonpropertiessearch.CentralRepoCommonAttributeInstanceNode; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeSearchResultRootNode; +import org.sleuthkit.autopsy.commonpropertiessearch.InstanceCountNode; +import org.sleuthkit.autopsy.commonpropertiessearch.InstanceCaseNode; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeValueNode; +import org.sleuthkit.autopsy.commonpropertiessearch.CaseDBCommonAttributeInstanceNode; +import org.sleuthkit.autopsy.commonpropertiessearch.InstanceDataSourceNode; import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.DeletedContentNode; import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode; import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode; diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index 585111ef49..e097f75a92 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -54,18 +54,18 @@ import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.autopsy.datamodel.FileTypeExtensions; import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesNode; -import org.sleuthkit.autopsy.commonfilesearch.InstanceCountNode; -import org.sleuthkit.autopsy.commonfilesearch.InstanceCaseNode; -import org.sleuthkit.autopsy.commonfilesearch.InstanceDataSourceNode; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeValueNode; -import org.sleuthkit.autopsy.commonfilesearch.CentralRepoCommonAttributeInstanceNode; +import org.sleuthkit.autopsy.commonpropertiessearch.InstanceCountNode; +import org.sleuthkit.autopsy.commonpropertiessearch.InstanceCaseNode; +import org.sleuthkit.autopsy.commonpropertiessearch.InstanceDataSourceNode; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeValueNode; +import org.sleuthkit.autopsy.commonpropertiessearch.CentralRepoCommonAttributeInstanceNode; import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.LocalDirectoryNode; import org.sleuthkit.autopsy.datamodel.NodeSelectionInfo; import org.sleuthkit.autopsy.datamodel.Reports; import org.sleuthkit.autopsy.datamodel.SlackFileNode; -import org.sleuthkit.autopsy.commonfilesearch.CaseDBCommonAttributeInstanceNode; +import org.sleuthkit.autopsy.commonpropertiessearch.CaseDBCommonAttributeInstanceNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import static org.sleuthkit.autopsy.directorytree.Bundle.DataResultFilterNode_viewSourceArtifact_text; import org.sleuthkit.autopsy.modules.embeddedfileextractor.ExtractArchiveWithPasswordAction; diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index fabf317187..d5a2240ca5 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -1102,9 +1102,8 @@ public class IngestManager implements IngestProgressSnapshotProvider { DATA_ADDED, /** * Property change event fired when an ingest module adds new content to - * a case or changes a recorded attribute of existing content. For - * example, if a module adds an extracted or carved file to a case, the - * module should fire this event. The old value of the + * a case. For example, if a module adds an extracted or carved file to + * a case, the module should fire this event. The old value of the * PropertyChangeEvent is a ModuleContentEvent object, and the new value * is set to null. */ diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestServices.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestServices.java index 01e86823c5..386326df10 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestServices.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestServices.java @@ -111,7 +111,8 @@ public final class IngestServices { /** * Fires an event to notify registered listeners that there is new content - * (e.g., files extracted from an archive file, carved files, etc.) + * added to the case. (e.g., files extracted from an archive file, carved + * files, etc.) * * @param moduleContentEvent A module content event, i.e., an event that * encapsulates new content data. diff --git a/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java b/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java index 8ceb99d0d2..0a05a238c4 100644 --- a/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/textextractors/TikaTextExtractor.java @@ -29,7 +29,6 @@ import java.io.InputStream; import java.io.PushbackReader; import java.io.Reader; import java.nio.file.Paths; -import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.Callable; @@ -42,7 +41,6 @@ import java.util.concurrent.TimeoutException; import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.apache.commons.io.FilenameUtils; import org.apache.tika.Tika; import org.apache.tika.metadata.Metadata; import org.apache.tika.parser.AutoDetectParser; @@ -134,8 +132,7 @@ final class TikaTextExtractor implements TextExtractor { private static final String TESSERACT_DIR_NAME = "Tesseract-OCR"; //NON-NLS private static final String TESSERACT_EXECUTABLE = "tesseract.exe"; //NON-NLS private static final File TESSERACT_PATH = locateTesseractExecutable(); - private static final String LANGUAGE_PACKS = getLanguagePacks(); - private static final String TESSERACT_LANGUAGE_PACK_EXT = "traineddata"; //NON-NLS + private String languagePacks = formatLanguagePacks(PlatformUtil.getOcrLanguagePacks()); private static final String TESSERACT_OUTPUT_FILE_NAME = "tess_output"; //NON-NLS private ProcessTerminator processTerminator; @@ -203,7 +200,7 @@ final class TikaTextExtractor implements TextExtractor { String tesseractFolder = TESSERACT_PATH.getParent(); ocrConfig.setTesseractPath(tesseractFolder); - ocrConfig.setLanguage(LANGUAGE_PACKS); + ocrConfig.setLanguage(languagePacks); ocrConfig.setTessdataPath(PlatformUtil.getOcrLanguagePacksPath()); parseContext.set(TesseractOCRConfig.class, ocrConfig); @@ -289,7 +286,7 @@ final class TikaTextExtractor implements TextExtractor { String.format("\"%s\"", outputFilePath), "--tessdata-dir", PlatformUtil.getOcrLanguagePacksPath(), //language pack command flag - "-l", LANGUAGE_PACKS); + "-l", languagePacks); //If the ProcessTerminator was supplied during //configuration apply it here. @@ -443,23 +440,11 @@ final class TikaTextExtractor implements TextExtractor { } /** - * Retrieves all of the installed language packs from their designated - * directory location to be used to configure Tesseract OCR. + * Formats language packs to be parseable from the command line. * * @return String of all language packs available for Tesseract to use */ - private static String getLanguagePacks() { - File languagePackRootDir = new File(PlatformUtil.getOcrLanguagePacksPath()); - - List languagePacks = new ArrayList<>(); - for (File languagePack : languagePackRootDir.listFiles()) { - String fileExt = FilenameUtils.getExtension(languagePack.getName()); - if (!languagePack.isDirectory() && TESSERACT_LANGUAGE_PACK_EXT.equals(fileExt)) { - String packageName = FilenameUtils.getBaseName(languagePack.getName()); - languagePacks.add(packageName); - } - } - + private static String formatLanguagePacks(List languagePacks) { return String.join("+", languagePacks); } @@ -499,8 +484,14 @@ final class TikaTextExtractor implements TextExtractor { public void setExtractionSettings(Lookup context) { if (context != null) { ImageConfig configInstance = context.lookup(ImageConfig.class); - if (configInstance != null && Objects.nonNull(configInstance.getOCREnabled())) { - this.tesseractOCREnabled = configInstance.getOCREnabled(); + if (configInstance != null) { + if(Objects.nonNull(configInstance.getOCREnabled())) { + this.tesseractOCREnabled = configInstance.getOCREnabled(); + } + + if(Objects.nonNull(configInstance.getOCRLanguages())) { + this.languagePacks = formatLanguagePacks(configInstance.getOCRLanguages()); + } } ProcessTerminator terminatorInstance = context.lookup(ProcessTerminator.class); diff --git a/Core/src/org/sleuthkit/autopsy/textextractors/configs/ImageConfig.java b/Core/src/org/sleuthkit/autopsy/textextractors/configs/ImageConfig.java index 33d7987537..3abe178287 100755 --- a/Core/src/org/sleuthkit/autopsy/textextractors/configs/ImageConfig.java +++ b/Core/src/org/sleuthkit/autopsy/textextractors/configs/ImageConfig.java @@ -18,19 +18,22 @@ */ package org.sleuthkit.autopsy.textextractors.configs; +import java.util.List; + /** - * Allows for configuration of OCR on image files. Extractors that use ImageConfig - * can be obtained through TextExtractoryFactory.getExtractor(). + * Allows for configuration of OCR on image files. Extractors that use + * ImageConfig can be obtained through TextExtractoryFactory.getExtractor(). * * @see org.openide.util.Lookup */ public class ImageConfig { private Boolean OCREnabled; + private List ocrLanguages; /** - * Enables OCR to be run on the text reader responsible for handling - * image files. + * Enables OCR to be run on the text reader responsible for handling image + * files. * * @param enabled Flag indicating if OCR is enabled. */ @@ -46,4 +49,24 @@ public class ImageConfig { public boolean getOCREnabled() { return this.OCREnabled; } + + /** + * Sets languages for OCR. + * + * See PlatformUtil for list of installed language packs. + * + * @param languages List of languages to use + */ + public void setOCRLanguages(List languages) { + this.ocrLanguages = languages; + } + + /** + * Gets the list of languages OCR should perform. + * + * @return Collection of OCR languages + */ + public List getOCRLanguages() { + return this.ocrLanguages; + } } diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index b61d82626b..a0608a3e9d 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -150,17 +150,17 @@ public class CentralRepoDatamodelTest extends TestCase { case2 = EamDb.getInstance().newCase(case2); assertTrue("Failed to create test object case2", case2 != null); - dataSource1fromCase1 = new CorrelationDataSource(case1, "dataSource1_deviceID", "dataSource1", CASE_1_DATA_SOURCE_1_ID); + dataSource1fromCase1 = new CorrelationDataSource(case1, "dataSource1_deviceID", "dataSource1", CASE_1_DATA_SOURCE_1_ID, null, null, null); EamDb.getInstance().newDataSource(dataSource1fromCase1); dataSource1fromCase1 = EamDb.getInstance().getDataSource(case1, dataSource1fromCase1.getDataSourceObjectID()); assertTrue("Failed to create test object dataSource1fromCase1", dataSource1fromCase1 != null); - dataSource2fromCase1 = new CorrelationDataSource(case1, "dataSource2_deviceID", "dataSource2", CASE_1_DATA_SOURCE_2_ID); + dataSource2fromCase1 = new CorrelationDataSource(case1, "dataSource2_deviceID", "dataSource2", CASE_1_DATA_SOURCE_2_ID, null, null, null); EamDb.getInstance().newDataSource(dataSource2fromCase1); dataSource2fromCase1 = EamDb.getInstance().getDataSource(case1, dataSource2fromCase1.getDataSourceObjectID()); assertTrue("Failed to create test object dataSource2fromCase1", dataSource2fromCase1 != null); - dataSource1fromCase2 = new CorrelationDataSource(case2, "dataSource3_deviceID", "dataSource3", CASE_2_DATA_SOURCE_1_ID); + dataSource1fromCase2 = new CorrelationDataSource(case2, "dataSource3_deviceID", "dataSource3", CASE_2_DATA_SOURCE_1_ID, null, null, null); EamDb.getInstance().newDataSource(dataSource1fromCase2); dataSource1fromCase2 = EamDb.getInstance().getDataSource(case2, dataSource1fromCase2.getDataSourceObjectID()); assertTrue("Failed to create test object dataSource1fromCase2", dataSource1fromCase2 != null); @@ -866,7 +866,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test adding instance with invalid data source ID try { CorrelationDataSource badDS = new CorrelationDataSource(case1, "badDSUuid", "badDSName", - 0L); + 0L, null, null, null); CorrelationAttributeInstance failAttrInst4 = new CorrelationAttributeInstance(fileType, randomHash(), case1, badDS, BAD_PATH, null, TskData.FileKnown.UNKNOWN, 0L); EamDb.getInstance().addArtifactInstance(failAttrInst4); @@ -2348,7 +2348,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test creating a data source with valid case, name, and ID try { dataSourceA = new CorrelationDataSource(case2, dataSourceAid, dataSourceAname, - 0L); + 0L, null, null, null); EamDb.getInstance().newDataSource(dataSourceA); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); @@ -2359,7 +2359,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test creating a data source with the same case, name, and ID try { CorrelationDataSource temp = new CorrelationDataSource(case2, dataSourceAid, dataSourceAname, - 0L); + 0L, null, null, null); EamDb.getInstance().newDataSource(temp); fail("newDataSource did not throw exception from duplicate data source"); } catch (EamDbException ex) { @@ -2369,7 +2369,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test creating a data source with the same name and ID but different case try { dataSourceB = new CorrelationDataSource(case1, dataSourceAid, dataSourceAname, - 0L); + 0L, null, null, null); EamDb.getInstance().newDataSource(dataSourceB); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); @@ -2381,7 +2381,7 @@ public class CentralRepoDatamodelTest extends TestCase { try { CorrelationCase correlationCase = new CorrelationCase("1", "test"); CorrelationDataSource temp = new CorrelationDataSource(correlationCase, "tempID", "tempName", - 0L); + 0L, null, null, null); EamDb.getInstance().newDataSource(temp); fail("newDataSource did not throw exception from invalid case ID"); } catch (EamDbException ex) { @@ -2392,7 +2392,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test creating a data source with null device ID try { CorrelationDataSource temp = new CorrelationDataSource(case2, null, "tempName", - 0L); + 0L, null, null, null); EamDb.getInstance().newDataSource(temp); fail("newDataSource did not throw exception from null device ID"); } catch (EamDbException ex) { @@ -2403,7 +2403,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test creating a data source with null name try { CorrelationDataSource temp = new CorrelationDataSource(case2, "tempID", null, - 0L); + 0L, null, null, null); EamDb.getInstance().newDataSource(temp); fail("newDataSource did not throw exception from null name"); } catch (EamDbException ex) { diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/CommonAttributeSearchInterCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeSearchInterCaseTests.java similarity index 88% rename from Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/CommonAttributeSearchInterCaseTests.java rename to Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeSearchInterCaseTests.java index 5dca8f4c42..1fd807dcc8 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/CommonAttributeSearchInterCaseTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeSearchInterCaseTests.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilessearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.nio.file.Path; import java.sql.SQLException; @@ -29,14 +29,14 @@ import org.openide.util.Exceptions; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; -import org.sleuthkit.autopsy.commonfilesearch.AbstractCommonAttributeSearcher; -import org.sleuthkit.autopsy.commonfilesearch.AllInterCaseCommonAttributeSearcher; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeCountSearchResults; -import static org.sleuthkit.autopsy.commonfilessearch.InterCaseTestUtils.CASE1; -import static org.sleuthkit.autopsy.commonfilessearch.InterCaseTestUtils.CASE2; -import static org.sleuthkit.autopsy.commonfilessearch.InterCaseTestUtils.CASE3; -import static org.sleuthkit.autopsy.commonfilessearch.InterCaseTestUtils.CASE4; -import static org.sleuthkit.autopsy.commonfilessearch.InterCaseTestUtils.verifyInstanceCount; +import org.sleuthkit.autopsy.commonpropertiessearch.AbstractCommonAttributeSearcher; +import org.sleuthkit.autopsy.commonpropertiessearch.AllInterCaseCommonAttributeSearcher; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeCountSearchResults; +import static org.sleuthkit.autopsy.commonpropertiessearch.InterCaseTestUtils.CASE1; +import static org.sleuthkit.autopsy.commonpropertiessearch.InterCaseTestUtils.CASE2; +import static org.sleuthkit.autopsy.commonpropertiessearch.InterCaseTestUtils.CASE3; +import static org.sleuthkit.autopsy.commonpropertiessearch.InterCaseTestUtils.CASE4; +import static org.sleuthkit.autopsy.commonpropertiessearch.InterCaseTestUtils.verifyInstanceCount; import org.sleuthkit.datamodel.TskCoreException; /** diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/IngestedWithHashAndFileTypeInterCaseTests.java similarity index 97% rename from Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java rename to Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/IngestedWithHashAndFileTypeInterCaseTests.java index b11352175c..acf2cad93a 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeInterCaseTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/IngestedWithHashAndFileTypeInterCaseTests.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilessearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.nio.file.Path; import java.sql.SQLException; @@ -30,11 +30,11 @@ import junit.framework.Assert; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; -import org.sleuthkit.autopsy.commonfilesearch.AbstractCommonAttributeSearcher; -import org.sleuthkit.autopsy.commonfilesearch.AllInterCaseCommonAttributeSearcher; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeCountSearchResults; -import org.sleuthkit.autopsy.commonfilesearch.SingleInterCaseCommonAttributeSearcher; -import static org.sleuthkit.autopsy.commonfilessearch.InterCaseTestUtils.*; +import org.sleuthkit.autopsy.commonpropertiessearch.AbstractCommonAttributeSearcher; +import org.sleuthkit.autopsy.commonpropertiessearch.AllInterCaseCommonAttributeSearcher; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeCountSearchResults; +import org.sleuthkit.autopsy.commonpropertiessearch.SingleInterCaseCommonAttributeSearcher; +import static org.sleuthkit.autopsy.commonpropertiessearch.InterCaseTestUtils.*; import org.sleuthkit.datamodel.TskCoreException; /** diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeIntraCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/IngestedWithHashAndFileTypeIntraCaseTests.java similarity index 98% rename from Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeIntraCaseTests.java rename to Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/IngestedWithHashAndFileTypeIntraCaseTests.java index c69812a84b..51d731517a 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithHashAndFileTypeIntraCaseTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/IngestedWithHashAndFileTypeIntraCaseTests.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilessearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.sql.SQLException; import java.util.ArrayList; @@ -31,11 +31,11 @@ import junit.framework.Assert; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; -import org.sleuthkit.autopsy.commonfilesearch.AbstractCommonAttributeSearcher; -import org.sleuthkit.autopsy.commonfilesearch.AllIntraCaseCommonAttributeSearcher; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeCountSearchResults; -import org.sleuthkit.autopsy.commonfilesearch.SingleIntraCaseCommonAttributeSearcher; -import static org.sleuthkit.autopsy.commonfilessearch.IntraCaseTestUtils.*; +import org.sleuthkit.autopsy.commonpropertiessearch.AbstractCommonAttributeSearcher; +import org.sleuthkit.autopsy.commonpropertiessearch.AllIntraCaseCommonAttributeSearcher; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeCountSearchResults; +import org.sleuthkit.autopsy.commonpropertiessearch.SingleIntraCaseCommonAttributeSearcher; +import static org.sleuthkit.autopsy.commonpropertiessearch.IntraCaseTestUtils.*; import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobSettings.IngestType; import org.sleuthkit.autopsy.ingest.IngestModuleTemplate; diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithNoFileTypesIntraCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/IngestedWithNoFileTypesIntraCaseTests.java similarity index 92% rename from Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithNoFileTypesIntraCaseTests.java rename to Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/IngestedWithNoFileTypesIntraCaseTests.java index 87d220e567..a1f435c45e 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IngestedWithNoFileTypesIntraCaseTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/IngestedWithNoFileTypesIntraCaseTests.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilessearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.sql.SQLException; import java.util.ArrayList; @@ -31,10 +31,10 @@ import org.openide.util.Exceptions; import junit.framework.Assert; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.commonfilesearch.AllIntraCaseCommonAttributeSearcher; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeCountSearchResults; -import org.sleuthkit.autopsy.commonfilesearch.IntraCaseCommonAttributeSearcher; -import org.sleuthkit.autopsy.commonfilesearch.SingleIntraCaseCommonAttributeSearcher; +import org.sleuthkit.autopsy.commonpropertiessearch.AllIntraCaseCommonAttributeSearcher; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeCountSearchResults; +import org.sleuthkit.autopsy.commonpropertiessearch.IntraCaseCommonAttributeSearcher; +import org.sleuthkit.autopsy.commonpropertiessearch.SingleIntraCaseCommonAttributeSearcher; import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestModuleTemplate; import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupModuleFactory; diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseTestUtils.java similarity index 97% rename from Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java rename to Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseTestUtils.java index eb95ff61f0..85d5ad3593 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/InterCaseTestUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseTestUtils.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilessearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.io.File; import java.io.IOException; @@ -51,14 +51,14 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; -import org.sleuthkit.autopsy.commonfilesearch.AbstractCommonAttributeInstance; -import org.sleuthkit.autopsy.commonfilesearch.CaseDBCommonAttributeInstanceNode; -import org.sleuthkit.autopsy.commonfilesearch.CentralRepoCommonAttributeInstance; -import org.sleuthkit.autopsy.commonfilesearch.CentralRepoCommonAttributeInstanceNode; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeCountSearchResults; +import org.sleuthkit.autopsy.commonpropertiessearch.AbstractCommonAttributeInstance; +import org.sleuthkit.autopsy.commonpropertiessearch.CaseDBCommonAttributeInstanceNode; +import org.sleuthkit.autopsy.commonpropertiessearch.CentralRepoCommonAttributeInstance; +import org.sleuthkit.autopsy.commonpropertiessearch.CentralRepoCommonAttributeInstanceNode; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeCountSearchResults; import org.sleuthkit.autopsy.datamodel.utils.DataSourceLoader; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeValue; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeValueList; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeValue; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeValueList; import org.sleuthkit.autopsy.coreutils.TimeStampUtils; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.modules.dataSourceIntegrity.DataSourceIntegrityModuleFactory; diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/IntraCaseTestUtils.java similarity index 95% rename from Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java rename to Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/IntraCaseTestUtils.java index bca017e499..49ff17229c 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/IntraCaseTestUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/IntraCaseTestUtils.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilessearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.nio.file.Path; import java.nio.file.Paths; @@ -32,11 +32,11 @@ import junit.framework.Assert; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.ImageDSProcessor; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.commonfilesearch.AbstractCommonAttributeInstance; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeCountSearchResults; +import org.sleuthkit.autopsy.commonpropertiessearch.AbstractCommonAttributeInstance; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeCountSearchResults; import org.sleuthkit.autopsy.datamodel.utils.DataSourceLoader; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeValue; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeValueList; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeValue; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeValueList; import org.sleuthkit.autopsy.coreutils.TimeStampUtils; import org.sleuthkit.autopsy.testutils.CaseUtils; import org.sleuthkit.autopsy.testutils.IngestUtils; diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/MatchesInAtLeastTwoSourcesIntraCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/MatchesInAtLeastTwoSourcesIntraCaseTests.java similarity index 92% rename from Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/MatchesInAtLeastTwoSourcesIntraCaseTests.java rename to Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/MatchesInAtLeastTwoSourcesIntraCaseTests.java index 8d501ae7a7..8d42a401b9 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/MatchesInAtLeastTwoSourcesIntraCaseTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/MatchesInAtLeastTwoSourcesIntraCaseTests.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilessearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.sql.SQLException; import java.util.ArrayList; @@ -32,10 +32,10 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.ImageDSProcessor; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; -import org.sleuthkit.autopsy.commonfilesearch.AbstractCommonAttributeSearcher; -import org.sleuthkit.autopsy.commonfilesearch.AllIntraCaseCommonAttributeSearcher; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeCountSearchResults; -import static org.sleuthkit.autopsy.commonfilessearch.IntraCaseTestUtils.*; +import org.sleuthkit.autopsy.commonpropertiessearch.AbstractCommonAttributeSearcher; +import org.sleuthkit.autopsy.commonpropertiessearch.AllIntraCaseCommonAttributeSearcher; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeCountSearchResults; +import static org.sleuthkit.autopsy.commonpropertiessearch.IntraCaseTestUtils.*; import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestModuleTemplate; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory; diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/UningestedCasesIntraCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/UningestedCasesIntraCaseTests.java similarity index 86% rename from Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/UningestedCasesIntraCaseTests.java rename to Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/UningestedCasesIntraCaseTests.java index 28030fd492..f042249fe7 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/UningestedCasesIntraCaseTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/UningestedCasesIntraCaseTests.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.commonfilessearch; +package org.sleuthkit.autopsy.commonpropertiessearch; import java.sql.SQLException; import java.util.Map; @@ -28,12 +28,12 @@ import org.netbeans.junit.NbTestCase; import org.openide.util.Exceptions; import junit.framework.Assert; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.commonfilesearch.AllIntraCaseCommonAttributeSearcher; -import org.sleuthkit.autopsy.commonfilesearch.CommonAttributeCountSearchResults; -import org.sleuthkit.autopsy.commonfilesearch.IntraCaseCommonAttributeSearcher; -import org.sleuthkit.autopsy.commonfilesearch.SingleIntraCaseCommonAttributeSearcher; -import static org.sleuthkit.autopsy.commonfilessearch.IntraCaseTestUtils.SET1; -import static org.sleuthkit.autopsy.commonfilessearch.IntraCaseTestUtils.getDataSourceIdByName; +import org.sleuthkit.autopsy.commonpropertiessearch.AllIntraCaseCommonAttributeSearcher; +import org.sleuthkit.autopsy.commonpropertiessearch.CommonAttributeCountSearchResults; +import org.sleuthkit.autopsy.commonpropertiessearch.IntraCaseCommonAttributeSearcher; +import org.sleuthkit.autopsy.commonpropertiessearch.SingleIntraCaseCommonAttributeSearcher; +import static org.sleuthkit.autopsy.commonpropertiessearch.IntraCaseTestUtils.SET1; +import static org.sleuthkit.autopsy.commonpropertiessearch.IntraCaseTestUtils.getDataSourceIdByName; import org.sleuthkit.datamodel.TskCoreException; /** diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index d2a9c40dc0..1a1a384745 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -389,7 +389,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen private void handleRemoteJobCancelledEvent(AutoIngestJobCancelEvent event) { AutoIngestJob job = event.getJob(); if (job != null && job.getProcessingHostName().compareToIgnoreCase(LOCAL_HOST_NAME) == 0) { - sysLogger.log(Level.INFO, "Received cancel job event for data source {0} in case {1} from user {2} on machine {3}", + sysLogger.log(Level.INFO, "Received cancel job event for data source {0} in case {1} from user {2} on machine {3}", new Object[]{job.getManifest().getDataSourceFileName(), job.getManifest().getCaseName(), event.getUserName(), event.getNodeName()}); if (event.getJob().equals(currentJob)) { cancelCurrentJob(); @@ -405,7 +405,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen private void handleRemoteJobReprocessEvent(AutoIngestJobReprocessEvent event) { synchronized (jobsLock) { AutoIngestJob job = event.getJob(); - sysLogger.log(Level.INFO, "Received reprocess job event for data source {0} in case {1} from user {2} on machine {3}", + sysLogger.log(Level.INFO, "Received reprocess job event for data source {0} in case {1} from user {2} on machine {3}", new Object[]{job.getManifest().getDataSourceFileName(), job.getManifest().getCaseName(), event.getUserName(), event.getNodeName()}); if (completedJobs.contains(job)) { // Remove from completed jobs table. @@ -429,27 +429,27 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen private void handleRemoteCasePrioritizationEvent(AutoIngestCasePrioritizedEvent event) { switch (event.getEventType()) { case CASE_PRIORITIZED: - sysLogger.log(Level.INFO, "Received prioritize case event for case {0} from user {1} on machine {2}", + sysLogger.log(Level.INFO, "Received prioritize case event for case {0} from user {1} on machine {2}", new Object[]{event.getCaseName(), event.getUserName(), event.getNodeName()}); break; case CASE_DEPRIORITIZED: - sysLogger.log(Level.INFO, "Received deprioritize case event for case {0} from user {1} on machine {2}", + sysLogger.log(Level.INFO, "Received deprioritize case event for case {0} from user {1} on machine {2}", new Object[]{event.getCaseName(), event.getUserName(), event.getNodeName()}); break; case JOB_PRIORITIZED: - sysLogger.log(Level.INFO, "Received prioritize job event for data source {0} in case {1} from user {2} on machine {3}", + sysLogger.log(Level.INFO, "Received prioritize job event for data source {0} in case {1} from user {2} on machine {3}", new Object[]{event.getDataSources(), event.getCaseName(), event.getUserName(), event.getNodeName()}); break; case JOB_DEPRIORITIZED: - sysLogger.log(Level.INFO, "Received deprioritize job event for data source {0} in case {1} from user {2} on machine {3}", + sysLogger.log(Level.INFO, "Received deprioritize job event for data source {0} in case {1} from user {2} on machine {3}", new Object[]{event.getDataSources(), event.getCaseName(), event.getUserName(), event.getNodeName()}); break; default: - sysLogger.log(Level.WARNING, "Received invalid prioritization event from user {0} on machine {1}", + sysLogger.log(Level.WARNING, "Received invalid prioritization event from user {0} on machine {1}", new Object[]{event.getUserName(), event.getNodeName()}); break; } - + String hostName = event.getNodeName(); hostNamesToLastMsgTime.put(hostName, Instant.now()); scanInputDirsNow(); @@ -464,8 +464,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen * @param event A case deleted event from another auto ingest node. */ private void handleRemoteCaseDeletedEvent(AutoIngestCaseDeletedEvent event) { - sysLogger.log(Level.INFO, "Received delete case event for case {0} from user {1} on machine {2}", - new Object[]{event.getCaseName(), event.getUserName(), event.getNodeName()}); + sysLogger.log(Level.INFO, "Received delete case event for case {0} from user {1} on machine {2}", + new Object[]{event.getCaseName(), event.getUserName(), event.getNodeName()}); String hostName = event.getNodeName(); hostNamesToLastMsgTime.put(hostName, Instant.now()); scanInputDirsNow(); @@ -483,7 +483,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen private void handleRemoteNodeControlEvent(AutoIngestNodeControlEvent event) { if (event.getTargetNodeName().compareToIgnoreCase(LOCAL_HOST_NAME) == 0) { - sysLogger.log(Level.INFO, "Received {0} event from user {1} on machine {2}", new Object[] {event.getControlEventType().toString(), event.getUserName(), event.getOriginatingNodeName()}); + sysLogger.log(Level.INFO, "Received {0} event from user {1} on machine {2}", new Object[]{event.getControlEventType().toString(), event.getUserName(), event.getOriginatingNodeName()}); switch (event.getControlEventType()) { case PAUSE: pause(); @@ -658,15 +658,15 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen } jobProcessingTask.requestResume(); } - + /** * Get the name of the currently logged in user - * @return + * + * @return */ static String getSystemUserNameProperty() { return System.getProperty("user.name"); } - /** * Removes the priority (set to zero) of all pending ingest jobs for a @@ -708,7 +708,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen if (!jobsToDeprioritize.isEmpty()) { new Thread(() -> { eventPublisher.publishRemotely(new AutoIngestCasePrioritizedEvent(LOCAL_HOST_NAME, caseName, - getSystemUserNameProperty(), AutoIngestCasePrioritizedEvent.EventType.CASE_DEPRIORITIZED, "")); + getSystemUserNameProperty(), AutoIngestCasePrioritizedEvent.EventType.CASE_DEPRIORITIZED, "")); }).start(); } } @@ -758,7 +758,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen if (!jobsToPrioritize.isEmpty()) { new Thread(() -> { eventPublisher.publishRemotely(new AutoIngestCasePrioritizedEvent(LOCAL_HOST_NAME, caseName, - getSystemUserNameProperty(), AutoIngestCasePrioritizedEvent.EventType.CASE_PRIORITIZED, "")); + getSystemUserNameProperty(), AutoIngestCasePrioritizedEvent.EventType.CASE_PRIORITIZED, "")); }).start(); } } @@ -811,7 +811,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen final String dataSourceName = jobToDeprioritize.getManifest().getDataSourceFileName(); new Thread(() -> { eventPublisher.publishRemotely(new AutoIngestCasePrioritizedEvent(LOCAL_HOST_NAME, caseName, - getSystemUserNameProperty(), AutoIngestCasePrioritizedEvent.EventType.JOB_DEPRIORITIZED, dataSourceName)); + getSystemUserNameProperty(), AutoIngestCasePrioritizedEvent.EventType.JOB_DEPRIORITIZED, dataSourceName)); }).start(); } } @@ -869,7 +869,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen final String dataSourceName = jobToPrioritize.getManifest().getDataSourceFileName(); new Thread(() -> { eventPublisher.publishRemotely(new AutoIngestCasePrioritizedEvent(LOCAL_HOST_NAME, caseName, - getSystemUserNameProperty(), AutoIngestCasePrioritizedEvent.EventType.JOB_PRIORITIZED, dataSourceName)); + getSystemUserNameProperty(), AutoIngestCasePrioritizedEvent.EventType.JOB_PRIORITIZED, dataSourceName)); }).start(); } } @@ -1488,87 +1488,79 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen /* * Try to get an exclusive lock on the coordination service node for * the job. If the lock cannot be obtained, another host in the auto - * ingest cluster is already doing the recovery. + * ingest cluster is already doing the recovery, so there is nothing + * to do. */ String manifestPath = manifest.getFilePath().toString(); try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifestPath)) { if (null != manifestLock) { sysLogger.log(Level.SEVERE, "Attempting crash recovery for {0}", manifestPath); - try { - Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName()); + Path caseDirectoryPath = PathUtils.findCaseDirectory(rootOutputDirectory, manifest.getCaseName()); - /* - * Create the recovery job. - */ - AutoIngestJob job = new AutoIngestJob(jobNodeData); - int numberOfCrashes = job.getNumberOfCrashes(); + /* + * Create the recovery job. + */ + AutoIngestJob job = new AutoIngestJob(jobNodeData); + int numberOfCrashes = job.getNumberOfCrashes(); + if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { + ++numberOfCrashes; + job.setNumberOfCrashes(numberOfCrashes); if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { - ++numberOfCrashes; - job.setNumberOfCrashes(numberOfCrashes); - if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { - job.setCompletedDate(new Date(0)); - } else { - job.setCompletedDate(Date.from(Instant.now())); - } + job.setCompletedDate(new Date(0)); + } else { + job.setCompletedDate(Date.from(Instant.now())); } + } + if (null != caseDirectoryPath) { + job.setCaseDirectoryPath(caseDirectoryPath); + job.setErrorsOccurred(true); + try { + setCaseNodeDataErrorsOccurred(caseDirectoryPath); + } catch (CaseNodeData.InvalidDataException ex) { + sysLogger.log(Level.SEVERE, String.format("Error attempting to get case node data for %s", caseDirectoryPath), ex); + } + } else { + job.setErrorsOccurred(false); + } + + if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { + job.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING); if (null != caseDirectoryPath) { - job.setCaseDirectoryPath(caseDirectoryPath); - job.setErrorsOccurred(true); try { - setCaseNodeDataErrorsOccurred(caseDirectoryPath); - } catch (CaseNodeData.InvalidDataException ex) { - sysLogger.log(Level.SEVERE, String.format("Error attempting to get case node data for %s", caseDirectoryPath), ex); - } - } else { - job.setErrorsOccurred(false); - } - - if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { - job.setProcessingStatus(AutoIngestJob.ProcessingStatus.PENDING); - if (null != caseDirectoryPath) { - try { - new AutoIngestJobLogger(manifest.getFilePath(), manifest.getDataSourceFileName(), caseDirectoryPath).logCrashRecoveryWithRetry(); - } catch (AutoIngestJobLoggerException ex) { - sysLogger.log(Level.SEVERE, String.format("Error creating case auto ingest log entry for crashed job for %s", manifestPath), ex); - } - } - } else { - job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED); - if (null != caseDirectoryPath) { - try { - new AutoIngestJobLogger(manifest.getFilePath(), manifest.getDataSourceFileName(), caseDirectoryPath).logCrashRecoveryNoRetry(); - } catch (AutoIngestJobLoggerException ex) { - sysLogger.log(Level.SEVERE, String.format("Error creating case auto ingest log entry for crashed job for %s", manifestPath), ex); - } + new AutoIngestJobLogger(manifest.getFilePath(), manifest.getDataSourceFileName(), caseDirectoryPath).logCrashRecoveryWithRetry(); + } catch (AutoIngestJobLoggerException ex) { + sysLogger.log(Level.SEVERE, String.format("Error creating case auto ingest log entry for crashed job for %s", manifestPath), ex); } } - - /* - * Update the coordination service node for the job. If - * this fails, leave the recovery to another host. - */ - try { - updateCoordinationServiceManifestNode(job); - } catch (CoordinationServiceException ex) { - sysLogger.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifestPath), ex); - return; + } else { + job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED); + if (null != caseDirectoryPath) { + try { + new AutoIngestJobLogger(manifest.getFilePath(), manifest.getDataSourceFileName(), caseDirectoryPath).logCrashRecoveryNoRetry(); + } catch (AutoIngestJobLoggerException ex) { + sysLogger.log(Level.SEVERE, String.format("Error creating case auto ingest log entry for crashed job for %s", manifestPath), ex); + } } + } - jobNodeData = new AutoIngestJobNodeData(job); + /* + * Update the coordination service node for the job. If this + * fails, leave the recovery to another host. + */ + try { + updateCoordinationServiceManifestNode(job); + } catch (CoordinationServiceException ex) { + sysLogger.log(Level.SEVERE, String.format("Error attempting to set node data for %s", manifestPath), ex); + return; + } - if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { - newPendingJobsList.add(job); - } else { - newCompletedJobsList.add(new AutoIngestJob(jobNodeData)); - } + jobNodeData = new AutoIngestJobNodeData(job); - } finally { - try { - manifestLock.release(); - } catch (CoordinationServiceException ex) { - sysLogger.log(Level.SEVERE, String.format("Error attempting to release exclusive lock for %s", manifestPath), ex); - } + if (numberOfCrashes <= AutoIngestUserPreferences.getMaxNumTimesToProcessImage()) { + newPendingJobsList.add(job); + } else { + newCompletedJobsList.add(new AutoIngestJob(jobNodeData)); } } } catch (CoordinationServiceException ex) { @@ -1619,11 +1611,11 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen job.setProcessingStatus(AutoIngestJob.ProcessingStatus.COMPLETED); /* - * Try to upgrade/update the coordination service manifest - * node data for the job. It is possible that two hosts will - * both try to obtain the lock to do the upgrade operation - * at the same time. If this happens, the host that is - * holding the lock will complete the upgrade operation. + * Try to upgrade/update the coordination service manifest node + * data for the job. It is possible that two hosts will both try + * to obtain the lock to do the upgrade operation at the same + * time. If this happens, the host that is holding the lock will + * complete the upgrade operation. */ try (Lock manifestLock = coordinationService.tryGetExclusiveLock(CoordinationService.CategoryNode.MANIFESTS, manifest.getFilePath().toString())) { if (null != manifestLock) { @@ -2456,7 +2448,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen throw new CaseManagementException(String.format("Error creating solr settings file for case %s for %s", caseName, manifest.getFilePath()), ex); } catch (CaseActionException ex) { throw new CaseManagementException(String.format("Error creating or opening case %s for %s", caseName, manifest.getFilePath()), ex); - } + } } else { throw new CaseManagementException(String.format("Timed out acquiring case name lock for %s for %s", caseName, manifest.getFilePath())); } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index 1fcce60cde..88bcb3ae8b 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -50,6 +50,7 @@ import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import java.nio.file.Path; +import static java.util.TimeZone.getTimeZone; import org.openide.util.Lookup; import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException; import org.sleuthkit.autopsy.ingest.IngestServices; @@ -79,6 +80,9 @@ class ExtractRegistry extends Extract { final private static UsbDeviceIdMapper USB_MAPPER = new UsbDeviceIdMapper(); final private static String RIP_EXE = "rip.exe"; final private static String RIP_PL = "rip.pl"; + final private static int MS_IN_SEC = 1000; + final private static String NEVER_DATE = "Never"; + final private static String SECTION_DIVIDER = "-------------------------"; private final List rrCmd = new ArrayList<>(); private final List rrFullCmd = new ArrayList<>(); @@ -228,6 +232,14 @@ class ExtractRegistry extends Extract { // create a report for the full output if (!regOutputFiles.fullPlugins.isEmpty()) { + //parse the full regripper output from SAM hive files + if (regFileNameLocal.toLowerCase().contains("sam")) { + if (parseSamPluginOutput(regOutputFiles.fullPlugins, regFile) == false) { + this.addErrorMessage( + NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults", + this.getName(), regFileName)); + } + } try { Report report = currentCase.addReport(regOutputFiles.fullPlugins, NbBundle.getMessage(this.getClass(), "ExtractRegistry.parentModuleName.noSpace"), @@ -287,6 +299,7 @@ class ExtractRegistry extends Extract { autopsyType = "autopsyntuser"; //NON-NLS fullType = "ntuser"; //NON-NLS } else if (regFilePath.toLowerCase().contains("sam")) { //NON-NLS + //fullType sam output files are parsed for user information fullType = "sam"; //NON-NLS } else if (regFilePath.toLowerCase().contains("security")) { //NON-NLS fullType = "security"; //NON-NLS @@ -349,8 +362,6 @@ class ExtractRegistry extends Extract { private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) { FileInputStream fstream = null; try { - SleuthkitCase tempDb = currentCase.getSleuthkitCase(); - // Read the file in and create a Document and elements File regfile = new File(regFilePath); fstream = new FileInputStream(regfile); @@ -390,7 +401,7 @@ class ExtractRegistry extends Extract { Long epochtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(etime).getTime(); mtime = epochtime; String Tempdate = mtime.toString(); - mtime = Long.valueOf(Tempdate) / 1000; + mtime = Long.valueOf(Tempdate) / MS_IN_SEC; } catch (ParseException ex) { logger.log(Level.WARNING, "Failed to parse epoch time when parsing the registry."); //NON-NLS } @@ -449,7 +460,7 @@ class ExtractRegistry extends Extract { Long epochtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(value).getTime(); installtime = epochtime; String Tempdate = installtime.toString(); - installtime = Long.valueOf(Tempdate) / 1000; + installtime = Long.valueOf(Tempdate) / MS_IN_SEC; } catch (ParseException e) { logger.log(Level.SEVERE, "RegRipper::Conversion on DateTime -> ", e); //NON-NLS } @@ -471,7 +482,7 @@ class ExtractRegistry extends Extract { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg)); // Check if there is already an OS_INFO artifact for this file, and add to that if possible. - ArrayList results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); + ArrayList results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); if (results.isEmpty()) { BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); bbart.addAttributes(bbattributes); @@ -524,7 +535,7 @@ class ExtractRegistry extends Extract { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir)); // Check if there is already an OS_INFO artifact for this file and add to that if possible - ArrayList results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); + ArrayList results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); if (results.isEmpty()) { BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); bbart.addAttributes(bbattributes); @@ -563,7 +574,7 @@ class ExtractRegistry extends Extract { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain)); // Check if there is already an OS_INFO artifact for this file and add to that if possible - ArrayList results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); + ArrayList results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); if (results.isEmpty()) { BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); bbart.addAttributes(bbattributes); @@ -589,7 +600,7 @@ class ExtractRegistry extends Extract { switch (dataType) { case "recentdocs": //NON-NLS - // BlackboardArtifact bbart = tempDb.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT); + // BlackboardArtifact bbart = tskCase.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT); // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", dataType, mtime)); // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", dataType, mtimeItem)); // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "RecentActivity", dataType, value)); @@ -633,7 +644,7 @@ class ExtractRegistry extends Extract { try { Long epochtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(artnode.getAttribute("mtime")).getTime(); //NON-NLS itemMtime = epochtime; - itemMtime = itemMtime / 1000; + itemMtime = itemMtime / MS_IN_SEC; } catch (ParseException e) { logger.log(Level.WARNING, "Failed to parse epoch time for installed program artifact."); //NON-NLS } @@ -794,7 +805,7 @@ class ExtractRegistry extends Extract { } return true; } catch (FileNotFoundException ex) { - logger.log(Level.SEVERE, "Error finding the registry file."); //NON-NLS + logger.log(Level.SEVERE, "Error finding the registry file.", ex); //NON-NLS } catch (SAXException ex) { logger.log(Level.SEVERE, "Error parsing the registry XML: {0}", ex); //NON-NLS } catch (IOException ex) { @@ -812,10 +823,253 @@ class ExtractRegistry extends Extract { return false; } + /** + * Parse the output of the SAM regripper plugin to get additional Account + * information + * + * @param regFilePath the path to the registry file being parsed + * @param regAbstractFile the file to associate newly created artifacts with + * + * @return true if successful, false if parsing failed at some point + */ + private boolean parseSamPluginOutput(String regFilePath, AbstractFile regAbstractFile) { + File regfile = new File(regFilePath); + String parentModuleName = NbBundle.getMessage(this.getClass(), "ExtractRegistry.parentModuleName.noSpace"); + SimpleDateFormat regRipperTimeFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy 'Z'"); + regRipperTimeFormat.setTimeZone(getTimeZone("GMT")); + try (BufferedReader bufferedReader = new BufferedReader(new FileReader(regfile))) { + // Read the file in and create a Document and elements + String userInfoSection = "User Information"; + String previousLine = null; + String line = bufferedReader.readLine(); + Set userSet = new HashSet<>(); + while (line != null) { + if (line.contains(SECTION_DIVIDER) && previousLine != null) { + if (previousLine.contains(userInfoSection)) { + readUsers(bufferedReader, userSet); + } + } + previousLine = line; + line = bufferedReader.readLine(); + } + Map userInfoMap = new HashMap<>(); + //load all the user info which was read into a map + for (UserInfo userInfo : userSet) { + userInfoMap.put(userInfo.getUserSid(), userInfo); + } + //get all existing OS account artifacts + List existingOsAccounts = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT); + for (BlackboardArtifact osAccount : existingOsAccounts) { + //if the OS Account artifact was from the same data source check the user id + if (osAccount.getDataSource().getId() == regAbstractFile.getDataSourceObjectId()) { + BlackboardAttribute existingUserId = osAccount.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID)); + if (existingUserId != null) { + UserInfo userInfo = userInfoMap.remove(existingUserId.getValueString().trim()); + //if the existing user id matches a user id which we parsed information for check if that information exists and if it doesn't add it + if (userInfo != null) { + Collection bbattributes = new ArrayList<>(); + if (userInfo.getAccountCreatedDate() != null && !userInfo.getAccountCreatedDate().equals(NEVER_DATE)) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, + parentModuleName, regRipperTimeFormat.parse(userInfo.getAccountCreatedDate()).getTime() / MS_IN_SEC)); + } + if (userInfo.getLastLoginDate() != null && !userInfo.getLastLoginDate().equals(NEVER_DATE)) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, + parentModuleName, regRipperTimeFormat.parse(userInfo.getLastLoginDate()).getTime() / MS_IN_SEC)); + } + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT, + parentModuleName, userInfo.getLoginCount())); + osAccount.addAttributes(bbattributes); + } + } + } + } + //add remaining userinfos as accounts; + for (String userId : userInfoMap.keySet()) { + UserInfo userInfo = userInfoMap.get(userId); + Collection bbattributes = new ArrayList<>(); + BlackboardArtifact bbart = regAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, + parentModuleName, userInfo.getUserName())); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID, + parentModuleName, userId)); + if (userInfo.getAccountCreatedDate() != null && !userInfo.getAccountCreatedDate().equals(NEVER_DATE)) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, + parentModuleName, regRipperTimeFormat.parse(userInfo.getAccountCreatedDate()).getTime() / MS_IN_SEC)); + } + if (userInfo.getLastLoginDate() != null && !userInfo.getLastLoginDate().equals(NEVER_DATE)) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, + parentModuleName, regRipperTimeFormat.parse(userInfo.getLastLoginDate()).getTime() / MS_IN_SEC)); + } + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT, + parentModuleName, userInfo.getLoginCount())); + bbart.addAttributes(bbattributes); + // index the artifact for keyword search + this.indexArtifact(bbart); + } + //store set of attributes to make artifact for later in collection of artifact like objects + return true; + } catch (FileNotFoundException ex) { + logger.log(Level.SEVERE, "Error finding the registry file.", ex); //NON-NLS + } catch (IOException ex) { + logger.log(Level.SEVERE, "Error building the document parser: {0}", ex); //NON-NLS + } catch (ParseException ex) { + logger.log(Level.SEVERE, "Error parsing the the date from the registry file", ex); //NON-NLS + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error updating TSK_OS_ACCOUNT artifacts to include newly parsed data.", ex); //NON-NLS + } + return false; + } + + /** + * Read the User Information section of the SAM regripper plugin's output + * and collect user account information from the file. + * + * @param bufferedReader a buffered reader for the file which contains the + * user information + * @param users the set to add UserInfo objects representing the + * users found to + * + * @throws IOException + */ + private void readUsers(BufferedReader bufferedReader, Set users) throws IOException { + String userNameLabel = "Username :"; + String sidLabel = "SID :"; + String accountCreatedLabel = "Account Created :"; + String loginCountLabel = "Login Count :"; + String lastLoginLabel = "Last Login Date :"; + String line = bufferedReader.readLine(); + //read until end of file or next section divider + String userName = ""; + while (line != null && !line.contains(SECTION_DIVIDER)) { + //when a user name field exists read the name and id number + if (line.contains(userNameLabel)) { + String userNameAndIdString = line.replace(userNameLabel, ""); + userName = userNameAndIdString.substring(0, userNameAndIdString.lastIndexOf('[')).trim(); + } + else if (line.contains(sidLabel) && !userName.isEmpty()){ + String sid = line.replace(sidLabel, "").trim(); + UserInfo userInfo = new UserInfo(userName, sid); + //continue reading this users information until end of file or a blank line between users + line = bufferedReader.readLine(); + while (line != null && !line.isEmpty()) { + if (line.contains(accountCreatedLabel)) { + userInfo.setAccountCreatedDate(line.replace(accountCreatedLabel, "").trim()); + } else if (line.contains(loginCountLabel)) { + userInfo.setLoginCount(Integer.parseInt(line.replace(loginCountLabel, "").trim())); + } else if (line.contains(lastLoginLabel)) { + userInfo.setLastLoginDate(line.replace(lastLoginLabel, "").trim()); + } + line = bufferedReader.readLine(); + } + users.add(userInfo); + userName = ""; + } + line = bufferedReader.readLine(); + } + } + @Override public void process(Content dataSource, IngestJobContext context) { this.dataSource = dataSource; this.context = context; analyzeRegistryFiles(); + + } + + /** + * Class for organizing information associated with a TSK_OS_ACCOUNT before + * the artifact is created. + */ + private class UserInfo { + + private final String userName; + private final String userSid; + private String lastLoginDate; + private String accountCreatedDate; + private int loginCount = 0; + + /** + * Create a UserInfo object + * + * @param name - the os user account name + * @param userIdString - the SID for the user account + */ + private UserInfo(String name, String userSidString) { + userName = name; + userSid = userSidString; + } + + /** + * Get the user name. + * + * @return the userName + */ + String getUserName() { + return userName; + } + + /** + * Get the user SID. + * + * @return the user SID + */ + String getUserSid() { + return userSid; + } + + /** + * Get the last login date for the user + * + * @return the lastLoginDate + */ + String getLastLoginDate() { + return lastLoginDate; + } + + /** + * Set the last login date for the users + * + * @param lastLoginDate the lastLoginDate to set + */ + void setLastLoginDate(String lastLoginDate) { + this.lastLoginDate = lastLoginDate; + } + + /** + * Get the account creation date. + * + * @return the accountCreatedDate + */ + String getAccountCreatedDate() { + return accountCreatedDate; + } + + /** + * Set the account creation date. + * + * @param accountCreatedDate the accountCreatedDate to set + */ + void setAccountCreatedDate(String accountCreatedDate) { + this.accountCreatedDate = accountCreatedDate; + } + + /** + * Get the number of times the user logged in. + * + * @return the loginCount + */ + int getLoginCount() { + return loginCount; + } + + /** + * Set the number of times the user logged in. + * + * @param loginCount the loginCount to set + */ + void setLoginCount(int loginCount) { + this.loginCount = loginCount; + } + } } diff --git a/test/script/tskdbdiff.py b/test/script/tskdbdiff.py index ab18341865..1dbfe2a180 100644 --- a/test/script/tskdbdiff.py +++ b/test/script/tskdbdiff.py @@ -333,7 +333,7 @@ class TskDbDiff(object): for line in postgreSQL_db: line = line.strip('\r\n ') # Deal with pg_dump result file - if line.startswith('--') or line.lower().startswith('alter') or "pg_catalog" in line or "idle_in_transaction_session_timeout" in line or not line: # It's comment or alter statement or catalog entry or set idle entry or empty line + if (line.startswith('--') or line.lower().startswith('alter') or "pg_catalog" in line or "idle_in_transaction_session_timeout" in line or not line or "image_gallery_groups_seen" in line): # It's comment or alter statement or catalog entry or set idle entry or empty line continue elif not line.endswith(';'): # Statement not finished dump_line += line @@ -352,6 +352,8 @@ class TskDbDiff(object): # Write to the database dump with codecs.open(dump_file, "wb", "utf_8") as db_log: for line in conn.iterdump(): + if "image_gallery_groups_seen" in line: + continue line = normalize_db_entry(line, id_obj_path_table, id_vs_parts_table, id_vs_info_table, id_fs_info_table, id_objects_table, id_reports_table) db_log.write('%s\n' % line) # Now sort the file diff --git a/thirdparty/rr-full/plugins/sam b/thirdparty/rr-full/plugins/sam index f91679f4b7..b89d6e6259 100644 --- a/thirdparty/rr-full/plugins/sam +++ b/thirdparty/rr-full/plugins/sam @@ -1,3 +1,3 @@ # 20161213 *ALL* Plugins that apply on SAM hive, alphabetical order samparse -samparse_ltn +samparse_tln diff --git a/thirdparty/rr-full/plugins/samparse.pl b/thirdparty/rr-full/plugins/samparse.pl index bdcfedf571..8046708b3b 100644 --- a/thirdparty/rr-full/plugins/samparse.pl +++ b/thirdparty/rr-full/plugins/samparse.pl @@ -79,6 +79,24 @@ sub pluginmain { ::rptMsg("-" x 25); my $key_path = 'SAM\\Domains\\Account\\Users'; my $key; + my $local_sid = ""; + my $account_key = $root_key->get_subkey("SAM\\Domains\\Account"); + if (defined $account_key) { + my $account_value = $account_key->get_value("V"); + if (defined $account_value) { + my $account_data = $account_value->get_data(); + if (defined $account_data) { + my $data_len = length($account_data); + if ($data_len >= 12) { + my @vArray = unpack("VVV",substr($account_data, $data_len-12, 12)); + my $vArray_len = @vArray; + if ($vArray_len == 3) { + $local_sid = "S-1-5-21-".$vArray[0]."-".$vArray[1]."-".$vArray[2]; + } + } + } + } + } if ($key = $root_key->get_subkey($key_path)) { my @user_list = $key->get_list_of_subkeys(); if (scalar(@user_list) > 0) { @@ -102,6 +120,7 @@ sub pluginmain { }; ::rptMsg("Username : ".$v_val{name}." [".$rid."]"); + ::rptMsg("SID : ".$local_sid."-".$rid); ::rptMsg("Full Name : ".$v_val{fullname}); ::rptMsg("User Comment : ".$v_val{comment}); ::rptMsg("Account Type : ".$v_val{type}); diff --git a/thirdparty/rr/plugins/autopsysoftware b/thirdparty/rr/plugins/autopsysoftware index bcb168f4b0..1ea0564b4b 100644 --- a/thirdparty/rr/plugins/autopsysoftware +++ b/thirdparty/rr/plugins/autopsysoftware @@ -1,4 +1,4 @@ - List of plugins for the Registry Ripper +# List of plugins for the Registry Ripper #------------------------------------- # SOFTWARE diff --git a/thirdparty/rr/plugins/officedocs.pl b/thirdparty/rr/plugins/officedocs.pl index c7ee407a7f..707a5c254f 100644 --- a/thirdparty/rr/plugins/officedocs.pl +++ b/thirdparty/rr/plugins/officedocs.pl @@ -125,7 +125,7 @@ sub pluginmain { # Print sorted content to report file foreach my $u (sort {$a <=> $b} keys %files) { my ($val,$data) = split(/:/,$files{$u},2); - ::rptMsg("".$data . "".$data . ""); } } else { @@ -140,12 +140,13 @@ sub pluginmain { #::rptMsg("Could not access ".$key_path); #::logMsg("Could not access ".$key_path); } + ::rptMsg(""); } else { #::logMsg("MSOffice version not found."); #::rptMsg("MSOffice version not found."); } -::rptMsg(""); +::rptMsg(""); } 1;