diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml
index 7a89519e34..04732e7873 100644
--- a/Core/nbproject/project.xml
+++ b/Core/nbproject/project.xml
@@ -338,7 +338,7 @@
org.sleuthkit.autopsy.modules.vmextractororg.sleuthkit.autopsy.progressorg.sleuthkit.autopsy.report
- org.sleuthkit.autopsy.tabulardatareader
+ org.sleuthkit.autopsy.texttranslationorg.sleuthkit.datamodel
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java
index c6301bfb89..191d1c3bc6 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java
@@ -127,7 +127,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
}
} else if (jmi.equals(showCommonalityMenuItem)) {
showCommonalityDetails();
- }
+ }
}
};
@@ -419,7 +419,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
}
// we can correlate based on the MD5 if it is enabled
- if (this.file != null && EamDb.isEnabled()) {
+ if (this.file != null && EamDb.isEnabled() && this.file.getSize() > 0) {
try {
List artifactTypes = EamDb.getInstance().getDefinedCorrelationTypes();
@@ -430,13 +430,14 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
CorrelationCase corCase = EamDb.getInstance().getCase(Case.getCurrentCase());
try {
ret.add(new CorrelationAttributeInstance(
- md5,
aType,
+ md5,
corCase,
CorrelationDataSource.fromTSKDataSource(corCase, file.getDataSource()),
file.getParentPath() + file.getName(),
"",
- file.getKnown()));
+ file.getKnown(),
+ file.getId()));
} catch (CorrelationAttributeNormalizationException ex) {
LOGGER.log(Level.INFO, String.format("Unable to check create CorrelationAttribtueInstance for value %s and type %s.", md5, aType.toString()), ex);
}
@@ -447,27 +448,23 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
} catch (EamDbException | TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
}
-
- } else {
-
- // If EamDb not enabled, get the Files default correlation type to allow Other Occurances to be enabled.
- if (this.file != null) {
- String md5 = this.file.getMd5Hash();
- if (md5 != null && !md5.isEmpty()) {
- try {
- final CorrelationAttributeInstance.Type fileAttributeType
- = CorrelationAttributeInstance.getDefaultCorrelationTypes()
- .stream()
- .filter(attrType -> attrType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID)
- .findAny()
- .get();
-
- ret.add(new CorrelationAttributeInstance(fileAttributeType, md5));
- } catch (EamDbException ex) {
- LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
- } catch (CorrelationAttributeNormalizationException ex) {
- LOGGER.log(Level.INFO, String.format("Unable to create CorrelationAttributeInstance for value %s", md5), ex); // NON-NLS
- }
+ // If EamDb not enabled, get the Files default correlation type to allow Other Occurances to be enabled.
+ } else if (this.file != null && this.file.getSize() > 0) {
+ String md5 = this.file.getMd5Hash();
+ if (md5 != null && !md5.isEmpty()) {
+ try {
+ final CorrelationAttributeInstance.Type fileAttributeType
+ = CorrelationAttributeInstance.getDefaultCorrelationTypes()
+ .stream()
+ .filter(attrType -> attrType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID)
+ .findAny()
+ .get();
+ //The Central Repository is not enabled
+ ret.add(new CorrelationAttributeInstance(fileAttributeType, md5, null, null, "", "", TskData.FileKnown.UNKNOWN, this.file.getId()));
+ } catch (EamDbException ex) {
+ LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
+ } catch (CorrelationAttributeNormalizationException ex) {
+ LOGGER.log(Level.INFO, String.format("Unable to create CorrelationAttributeInstance for value %s", md5), ex); // NON-NLS
}
}
}
@@ -515,9 +512,9 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
* artifact. If the central repo is not enabled, this will only return files
* from the current case with matching MD5 hashes.
*
- * @param corAttr CorrelationAttribute to query for
+ * @param corAttr CorrelationAttribute to query for
* @param dataSourceName Data source to filter results
- * @param deviceId Device Id to filter results
+ * @param deviceId Device Id to filter results
*
* @return A collection of correlated artifact instances
*/
@@ -580,7 +577,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
* Get all other abstract files in the current case with the same MD5 as the
* selected node.
*
- * @param corAttr The CorrelationAttribute containing the MD5 to search for
+ * @param corAttr The CorrelationAttribute containing the MD5 to search for
* @param openCase The current case
*
* @return List of matching AbstractFile objects
@@ -657,11 +654,9 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
// - The central repo is disabled and the backing file has a valid MD5 hash
this.file = this.getAbstractFileFromNode(node);
if (EamDb.isEnabled()) {
- return this.file != null
- && this.file.getSize() > 0
- && !getCorrelationAttributesFromNode(node).isEmpty();
+ return !getCorrelationAttributesFromNode(node).isEmpty();
} else {
- return this.file != null
+ return this.file != null
&& this.file.getSize() > 0
&& ((this.file.getMd5Hash() != null) && (!this.file.getMd5Hash().isEmpty()));
}
@@ -733,8 +728,8 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
* Adjust a given column for the text provided.
*
* @param columnIndex The index of the column to adjust.
- * @param text The text whose length will be used to adjust the column
- * width.
+ * @param text The text whose length will be used to adjust the
+ * column width.
*/
private void setColumnWidthToText(int columnIndex, String text) {
TableColumn column = otherCasesTable.getColumnModel().getColumn(columnIndex);
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java
index 836f47ea85..c2b10f8295 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java
@@ -808,9 +808,9 @@ abstract class AbstractSqlEamDb implements EamDb {
String sql
= "INSERT INTO "
+ tableName
- + "(case_id, data_source_id, value, file_path, known_status, comment) "
+ + "(case_id, data_source_id, value, file_path, known_status, comment, file_obj_id) "
+ "VALUES ((SELECT id FROM cases WHERE case_uid=? LIMIT 1), "
- + "(SELECT id FROM data_sources WHERE device_id=? AND case_id=? LIMIT 1), ?, ?, ?, ?) "
+ + "(SELECT id FROM data_sources WHERE device_id=? AND case_id=? LIMIT 1), ?, ?, ?, ?, ?) "
+ getConflictClause();
try {
@@ -824,11 +824,13 @@ abstract class AbstractSqlEamDb implements EamDb {
preparedStatement.setString(4, eamArtifact.getCorrelationValue());
preparedStatement.setString(5, eamArtifact.getFilePath().toLowerCase());
preparedStatement.setByte(6, eamArtifact.getKnownStatus().getFileKnownValue());
+
if ("".equals(eamArtifact.getComment())) {
preparedStatement.setNull(7, Types.INTEGER);
} else {
preparedStatement.setString(7, eamArtifact.getComment());
}
+ preparedStatement.setLong(8, eamArtifact.getFileObjectId());
preparedStatement.executeUpdate();
}
@@ -900,6 +902,8 @@ abstract class AbstractSqlEamDb implements EamDb {
+ ".id,"
+ tableName
+ ".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 FROM "
+ tableName
+ " LEFT JOIN cases ON "
@@ -963,6 +967,8 @@ abstract class AbstractSqlEamDb implements EamDb {
+ ".id, "
+ tableName
+ ".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 FROM "
+ tableName
+ " LEFT JOIN cases ON "
@@ -1229,9 +1235,9 @@ abstract class AbstractSqlEamDb implements EamDb {
String sql
= "INSERT INTO "
+ tableName
- + " (case_id, data_source_id, value, file_path, known_status, comment) "
+ + " (case_id, data_source_id, value, file_path, known_status, comment, file_obj_id) "
+ "VALUES ((SELECT id FROM cases WHERE case_uid=? LIMIT 1), "
- + "(SELECT id FROM data_sources WHERE device_id=? AND case_id=? LIMIT 1), ?, ?, ?, ?) "
+ + "(SELECT id FROM data_sources WHERE device_id=? AND case_id=? LIMIT 1), ?, ?, ?, ?, ?) "
+ getConflictClause();
bulkPs = conn.prepareStatement(sql);
@@ -1275,6 +1281,7 @@ abstract class AbstractSqlEamDb implements EamDb {
} else {
bulkPs.setString(7, eamArtifact.getComment());
}
+ bulkPs.setLong(8, eamArtifact.getFileObjectId());
bulkPs.addBatch();
} else {
logger.log(Level.WARNING, ("Artifact value too long for central repository."
@@ -1439,6 +1446,68 @@ abstract class AbstractSqlEamDb implements EamDb {
}
}
+ /**
+ * Find a correlation attribute in the Central Repository database given the
+ * instance type, case, data source, object id.
+ *
+ * @param type The type of instance.
+ * @param correlationCase The case tied to the instance.
+ * @param correlationDataSource The data source tied to the instance.
+ * @param objectID The object id of the file tied to the
+ * instance.
+ *
+ * @return The correlation attribute if it exists; otherwise null.
+ *
+ * @throws EamDbException
+ */
+ @Override
+ public CorrelationAttributeInstance getCorrelationAttributeInstance(CorrelationAttributeInstance.Type type, CorrelationCase correlationCase,
+ CorrelationDataSource correlationDataSource, long objectID) throws EamDbException, CorrelationAttributeNormalizationException {
+
+ if (correlationCase == null) {
+ throw new EamDbException("Correlation case is null");
+ }
+
+ Connection conn = connect();
+
+ PreparedStatement preparedStatement = null;
+ ResultSet resultSet = null;
+ CorrelationAttributeInstance correlationAttributeInstance = null;
+
+ try {
+
+ String tableName = EamDbUtil.correlationTypeToInstanceTableName(type);
+ String sql
+ = "SELECT id, value, file_path, known_status, comment FROM "
+ + tableName
+ + " WHERE case_id=?"
+ + " AND file_obj_id=?";
+
+ preparedStatement = conn.prepareStatement(sql);
+ preparedStatement.setInt(1, correlationCase.getID());
+ preparedStatement.setInt(2, (int) objectID);
+ resultSet = preparedStatement.executeQuery();
+ if (resultSet.next()) {
+ int instanceId = resultSet.getInt(1);
+ String value = resultSet.getString(2);
+ String filePath = resultSet.getString(3);
+ int knownStatus = resultSet.getInt(4);
+ String comment = resultSet.getString(5);
+
+ correlationAttributeInstance = new CorrelationAttributeInstance(type, value,
+ instanceId, correlationCase, correlationDataSource, filePath, comment, TskData.FileKnown.valueOf((byte) knownStatus), objectID);
+ }
+ } catch (SQLException ex) {
+ throw new EamDbException("Error getting notable artifact instances.", ex); // NON-NLS
+ } finally {
+ EamDbUtil.closeStatement(preparedStatement);
+ EamDbUtil.closeResultSet(resultSet);
+ EamDbUtil.closeConnection(conn);
+ }
+
+ return correlationAttributeInstance;
+ }
+
/**
* Find a correlation attribute in the Central Repository database given the
* instance type, case, data source, value, and file path.
@@ -1495,9 +1564,9 @@ abstract class AbstractSqlEamDb implements EamDb {
int instanceId = resultSet.getInt(1);
int knownStatus = resultSet.getInt(2);
String comment = resultSet.getString(3);
-
+ //null objectId used because we only fall back to using this method when objectID was not available
correlationAttributeInstance = new CorrelationAttributeInstance(type, value,
- instanceId, correlationCase, correlationDataSource, filePath, comment, TskData.FileKnown.valueOf((byte) knownStatus));
+ instanceId, correlationCase, correlationDataSource, filePath, comment, TskData.FileKnown.valueOf((byte) knownStatus), null);
}
} catch (SQLException ex) {
throw new EamDbException("Error getting notable artifact instances.", ex); // NON-NLS
@@ -1637,6 +1706,8 @@ abstract class AbstractSqlEamDb implements EamDb {
+ ".id, "
+ tableName
+ ".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 FROM "
+ tableName
+ " LEFT JOIN cases ON "
@@ -1694,7 +1765,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 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 FROM "
+ tableName
+ " LEFT JOIN cases ON "
+ tableName
@@ -2960,11 +3031,10 @@ abstract class AbstractSqlEamDb implements EamDb {
resultSet.getString("poc_phone"));
}
- CorrelationCase eamCase = new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), eamOrg, resultSet.getString("case_name"),
- resultSet.getString("creation_date"), resultSet.getString("case_number"), resultSet.getString("examiner_name"),
+ CorrelationCase eamCase = new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), eamOrg, resultSet.getString("case_name"),
+ resultSet.getString("creation_date"), resultSet.getString("case_number"), resultSet.getString("examiner_name"),
resultSet.getString("examiner_email"), resultSet.getString("examiner_phone"), resultSet.getString("notes"));
-
return eamCase;
}
@@ -3021,8 +3091,8 @@ abstract class AbstractSqlEamDb implements EamDb {
new CorrelationDataSource(resultSet.getInt("case_id"), resultSet.getInt("data_source_id"), resultSet.getString("device_id"), resultSet.getString("name")),
resultSet.getString("file_path"),
resultSet.getString("comment"),
- TskData.FileKnown.valueOf(resultSet.getByte("known_status"))
- );
+ TskData.FileKnown.valueOf(resultSet.getByte("known_status")),
+ resultSet.getLong("file_obj_id"));
}
private EamOrganization getEamOrganizationFromResultSet(ResultSet resultSet) throws SQLException {
@@ -3070,6 +3140,18 @@ abstract class AbstractSqlEamDb implements EamDb {
);
}
+ /**
+ * Determine if a specific column already exists in a specific table
+ *
+ * @param tableName the table to check for the specified column
+ * @param columnName the name of the column to check for
+ *
+ * @return true if the column exists, false if the column does not exist
+ *
+ * @throws EamDbException
+ */
+ abstract boolean doesColumnExist(Connection conn, String tableName, String columnName) throws SQLException;
+
/**
* Upgrade the schema of the database (if needed)
*
@@ -3080,6 +3162,7 @@ abstract class AbstractSqlEamDb implements EamDb {
ResultSet resultSet = null;
Statement statement = null;
+ PreparedStatement preparedStatement = null;
Connection conn = null;
try {
@@ -3114,6 +3197,10 @@ abstract class AbstractSqlEamDb implements EamDb {
logger.log(Level.INFO, "Central Repository is up to date");
return;
}
+ if (dbSchemaVersion.compareTo(CURRENT_DB_SCHEMA_VERSION) > 0) {
+ logger.log(Level.INFO, "Central Repository is of newer version than software creates");
+ return;
+ }
// Update from 1.0 to 1.1
if (dbSchemaVersion.compareTo(new CaseDbSchemaVersionNumber(1, 1)) < 0) {
@@ -3126,7 +3213,71 @@ abstract class AbstractSqlEamDb implements EamDb {
// regardless of whether this succeeds.
EamDbUtil.insertDefaultOrganization(conn);
}
+ //Update to 1.2
+ if (dbSchemaVersion.compareTo(new CaseDbSchemaVersionNumber(1, 2)) < 0) {
+ EamDbPlatformEnum selectedPlatform = EamDbPlatformEnum.getSelectedPlatform();
+ final String addObjectIdColumnTemplate = "ALTER TABLE %s ADD COLUMN file_obj_id INTEGER;"; //NON-NLS
+ final String addSsidTableTemplate;
+ final String addCaseIdIndexTemplate;
+ final String addDataSourceIdIndexTemplate;
+ final String addValueIndexTemplate;
+ final String addKnownStatusIndexTemplate;
+ final String addObjectIdIndexTemplate;
+
+ final String addAttributeSql;
+ //get the data base specific code for creating a new _instance table
+ switch (selectedPlatform) {
+ case POSTGRESQL:
+ addAttributeSql = "INSERT INTO correlation_types(id, display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?, ?) " + getConflictClause(); //NON-NLS
+
+ addSsidTableTemplate = PostgresEamDbSettings.getCreateArtifactInstancesTableTemplate();
+ addCaseIdIndexTemplate = PostgresEamDbSettings.getAddCaseIdIndexTemplate();
+ addDataSourceIdIndexTemplate = PostgresEamDbSettings.getAddDataSourceIdIndexTemplate();
+ addValueIndexTemplate = PostgresEamDbSettings.getAddValueIndexTemplate();
+ addKnownStatusIndexTemplate = PostgresEamDbSettings.getAddKnownStatusIndexTemplate();
+ addObjectIdIndexTemplate = PostgresEamDbSettings.getAddObjectIdIndexTemplate();
+ break;
+ case SQLITE:
+ addAttributeSql = "INSERT OR IGNORE INTO correlation_types(id, display_name, db_table_name, supported, enabled) VALUES (?, ?, ?, ?, ?)"; //NON-NLS
+
+ addSsidTableTemplate = SqliteEamDbSettings.getCreateArtifactInstancesTableTemplate();
+ addCaseIdIndexTemplate = SqliteEamDbSettings.getAddCaseIdIndexTemplate();
+ addDataSourceIdIndexTemplate = SqliteEamDbSettings.getAddDataSourceIdIndexTemplate();
+ addValueIndexTemplate = SqliteEamDbSettings.getAddValueIndexTemplate();
+ addKnownStatusIndexTemplate = SqliteEamDbSettings.getAddKnownStatusIndexTemplate();
+ addObjectIdIndexTemplate = SqliteEamDbSettings.getAddObjectIdIndexTemplate();
+ break;
+ default:
+ throw new EamDbException("Currently selected database platform \"" + selectedPlatform.name() + "\" can not be upgraded.");
+ }
+ //update central repository to be able to store new correlation attributes
+ final String wirelessNetworsDbTableName = "wireless_networks";
+ final String wirelessNetworksTableInstanceName = wirelessNetworsDbTableName + "_instances";
+ //add the wireless_networks attribute to the correlation_types table
+ preparedStatement = conn.prepareStatement(addAttributeSql);
+ preparedStatement.setInt(1, CorrelationAttributeInstance.SSID_TYPE_ID);
+ preparedStatement.setString(2, Bundle.CorrelationType_SSID_displayName());
+ preparedStatement.setString(3, wirelessNetworsDbTableName);
+ preparedStatement.setInt(4, 1);
+ preparedStatement.setInt(5, 1);
+ preparedStatement.execute();
+ //create a new wireless_networks_instances table and add indexes for its columns
+ statement.execute(String.format(addSsidTableTemplate, wirelessNetworksTableInstanceName, wirelessNetworksTableInstanceName));
+ statement.execute(String.format(addCaseIdIndexTemplate, wirelessNetworksTableInstanceName, wirelessNetworksTableInstanceName));
+ statement.execute(String.format(addDataSourceIdIndexTemplate, wirelessNetworksTableInstanceName, wirelessNetworksTableInstanceName));
+ statement.execute(String.format(addValueIndexTemplate, wirelessNetworksTableInstanceName, wirelessNetworksTableInstanceName));
+ statement.execute(String.format(addKnownStatusIndexTemplate, wirelessNetworksTableInstanceName, wirelessNetworksTableInstanceName));
+ //add file_obj_id column to _instances table which do not already have it
+ String instance_type_dbname;
+ for (CorrelationAttributeInstance.Type type : CorrelationAttributeInstance.getDefaultCorrelationTypes()) {
+ instance_type_dbname = EamDbUtil.correlationTypeToInstanceTableName(type);
+ if (!doesColumnExist(conn, instance_type_dbname, "file_obj_id")) {
+ statement.execute(String.format(addObjectIdColumnTemplate, instance_type_dbname)); //NON-NLS
+ }
+ statement.execute(String.format(addObjectIdIndexTemplate, instance_type_dbname, instance_type_dbname));
+ }
+ }
if (!updateSchemaVersion(conn)) {
throw new EamDbException("Error updating schema version");
}
@@ -3144,6 +3295,7 @@ abstract class AbstractSqlEamDb implements EamDb {
throw ex;
} finally {
EamDbUtil.closeResultSet(resultSet);
+ EamDbUtil.closeStatement(preparedStatement);
EamDbUtil.closeStatement(statement);
EamDbUtil.closeConnection(conn);
}
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java
index c26134c5b8..8fd6b4170e 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java
@@ -48,46 +48,18 @@ public class CorrelationAttributeInstance implements Serializable {
private String filePath;
private String comment;
private TskData.FileKnown knownStatus;
+ private Long objectId;
public CorrelationAttributeInstance(
- String correlationValue,
CorrelationAttributeInstance.Type correlationType,
- CorrelationCase eamCase,
- CorrelationDataSource eamDataSource,
- String filePath
- ) throws EamDbException, CorrelationAttributeNormalizationException {
- this(correlationType, correlationValue, -1, eamCase, eamDataSource, filePath, null, TskData.FileKnown.UNKNOWN);
- }
-
- public CorrelationAttributeInstance(
String correlationValue,
- CorrelationAttributeInstance.Type correlationType,
CorrelationCase eamCase,
CorrelationDataSource eamDataSource,
String filePath,
String comment,
- TskData.FileKnown knownStatus
- ) throws EamDbException, CorrelationAttributeNormalizationException {
- this(correlationType, correlationValue, -1, eamCase, eamDataSource, filePath, comment, knownStatus);
- }
-
- public CorrelationAttributeInstance(
- Type correlationType,
- String correlationValue,
- CorrelationCase correlationCase,
- CorrelationDataSource fromTSKDataSource,
- String string) throws EamDbException, CorrelationAttributeNormalizationException {
- this(correlationType, correlationValue, -1, correlationCase, fromTSKDataSource, string, "", TskData.FileKnown.UNKNOWN);
- }
-
- /**
- * NOTE: Only used for when EamDB is NOT enabled.
- *
- * @param aType CorrelationAttributeInstance.Type
- * @param value correlation value
- */
- public CorrelationAttributeInstance(Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
- this(aType, value, -1, null, null, "", "", TskData.FileKnown.UNKNOWN);
+ TskData.FileKnown knownStatus,
+ long fileObjectId) throws EamDbException, CorrelationAttributeNormalizationException {
+ this(correlationType, correlationValue, -1, eamCase, eamDataSource, filePath, comment, knownStatus, fileObjectId);
}
CorrelationAttributeInstance(
@@ -98,7 +70,8 @@ public class CorrelationAttributeInstance implements Serializable {
CorrelationDataSource eamDataSource,
String filePath,
String comment,
- TskData.FileKnown knownStatus
+ TskData.FileKnown knownStatus,
+ Long fileObjectId
) throws EamDbException, CorrelationAttributeNormalizationException {
if (filePath == null) {
throw new EamDbException("file path is null");
@@ -113,6 +86,7 @@ public class CorrelationAttributeInstance implements Serializable {
this.filePath = filePath.toLowerCase();
this.comment = comment;
this.knownStatus = knownStatus;
+ this.objectId = fileObjectId;
}
public Boolean equals(CorrelationAttributeInstance otherInstance) {
@@ -145,14 +119,6 @@ public class CorrelationAttributeInstance implements Serializable {
return correlationValue;
}
- /**
- * @param correlationValue the correlationValue to set
- */
- public void setCorrelationValue(String correlationValue) {
- // Lower-case all values to normalize and improve correlation hits, going forward make sure this makes sense for all correlation types
- this.correlationValue = correlationValue.toLowerCase();
- }
-
/**
* @return the correlation Type
*/
@@ -160,18 +126,11 @@ public class CorrelationAttributeInstance implements Serializable {
return correlationType;
}
- /**
- * @param correlationType the correlation Type to set
- */
- public void setCorrelationType(Type correlationType) {
- this.correlationType = correlationType;
- }
-
/**
* Is this a database instance?
*
* @return True if the instance ID is greater or equal to zero; otherwise
- * false.
+ * false.
*/
public boolean isDatabaseInstance() {
return (ID >= 0);
@@ -234,30 +193,42 @@ public class CorrelationAttributeInstance implements Serializable {
* as notable and should never be set to KNOWN.
*
* @param knownStatus Should be BAD if the item is tagged as notable,
- * UNKNOWN otherwise
+ * UNKNOWN otherwise
*/
public void setKnownStatus(TskData.FileKnown knownStatus) {
this.knownStatus = knownStatus;
}
+ /**
+ * Get the objectId of the file associated with the correlation attribute or
+ * NULL if the objectId is not available.
+ *
+ * @return the objectId of the file
+ */
+ public Long getFileObjectId() {
+ return objectId;
+ }
+
// Type ID's for Default Correlation Types
public static final int FILES_TYPE_ID = 0;
public static final int DOMAIN_TYPE_ID = 1;
public static final int EMAIL_TYPE_ID = 2;
public static final int PHONE_TYPE_ID = 3;
public static final int USBID_TYPE_ID = 4;
+ public static final int SSID_TYPE_ID = 5;
/**
* Load the default correlation types
*
* @throws EamDbException if the Type's dbTableName has invalid
- * characters/format
+ * characters/format
*/
@Messages({"CorrelationType.FILES.displayName=Files",
"CorrelationType.DOMAIN.displayName=Domains",
"CorrelationType.EMAIL.displayName=Email Addresses",
"CorrelationType.PHONE.displayName=Phone Numbers",
- "CorrelationType.USBID.displayName=USB Devices"})
+ "CorrelationType.USBID.displayName=USB Devices",
+ "CorrelationType.SSID.displayName=Wireless Networks"})
public static List getDefaultCorrelationTypes() throws EamDbException {
List DEFAULT_CORRELATION_TYPES = new ArrayList<>();
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(FILES_TYPE_ID, Bundle.CorrelationType_FILES_displayName(), "file", true, true)); // NON-NLS
@@ -265,6 +236,7 @@ public class CorrelationAttributeInstance implements Serializable {
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(EMAIL_TYPE_ID, Bundle.CorrelationType_EMAIL_displayName(), "email_address", true, true)); // NON-NLS
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(PHONE_TYPE_ID, Bundle.CorrelationType_PHONE_displayName(), "phone_number", true, true)); // NON-NLS
DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(USBID_TYPE_ID, Bundle.CorrelationType_USBID_displayName(), "usb_devices", true, true)); // NON-NLS
+ DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(SSID_TYPE_ID, Bundle.CorrelationType_SSID_displayName(), "wireless_networks", true, true)); // NON-NLS
return DEFAULT_CORRELATION_TYPES;
}
@@ -283,13 +255,14 @@ public class CorrelationAttributeInstance implements Serializable {
/**
*
- * @param typeId Unique ID for this Correlation Type
+ * @param typeId Unique ID for this Correlation Type
* @param displayName Name of this type displayed in the UI.
* @param dbTableName Central repository db table where data of this
- * type is stored. Must start with a lowercase letter and only contain
- * lowercase letters, numbers, and '_' characters.
- * @param supported Is this Type currently supported
- * @param enabled Is this Type currently enabled.
+ * type is stored. Must start with a lowercase letter
+ * and only contain lowercase letters, numbers, and
+ * '_' characters.
+ * @param supported Is this Type currently supported
+ * @param enabled Is this Type currently enabled.
*/
public Type(int typeId, String displayName, String dbTableName, Boolean supported, Boolean enabled) throws EamDbException {
if (dbTableName == null) {
@@ -312,10 +285,11 @@ public class CorrelationAttributeInstance implements Serializable {
*
* @param displayName Name of this type displayed in the UI.
* @param dbTableName Central repository db table where data of this
- * type is stored Must start with a lowercase letter and only contain
- * lowercase letters, numbers, and '_' characters.
- * @param supported Is this Type currently supported
- * @param enabled Is this Type currently enabled.
+ * type is stored Must start with a lowercase letter
+ * and only contain lowercase letters, numbers, and
+ * '_' characters.
+ * @param supported Is this Type currently supported
+ * @param enabled Is this Type currently enabled.
*/
public Type(String displayName, String dbTableName, Boolean supported, Boolean enabled) throws EamDbException {
this(-1, displayName, dbTableName, supported, enabled);
@@ -477,8 +451,8 @@ public class CorrelationAttributeInstance implements Serializable {
* custom_instances)
*
* @param dbTableName the dbTableName to set. Must start with lowercase
- * letter and can only contain lowercase letters, numbers, and '_'
- * characters.
+ * letter and can only contain lowercase letters,
+ * numbers, and '_' characters.
*
* @throws EamDbException if dbTableName contains invalid characters
*/
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java
index 772e1c517e..4ce04769c8 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java
@@ -63,6 +63,8 @@ final public class CorrelationAttributeNormalizer {
return normalizePhone(data);
case CorrelationAttributeInstance.USBID_TYPE_ID:
return normalizeUsbId(data);
+ case CorrelationAttributeInstance.SSID_TYPE_ID:
+ return data;
default:
final String errorMessage = String.format(
"Validator function not found for attribute type: %s",
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java
index 30d539e87f..7d098fc590 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java
@@ -54,9 +54,9 @@ public class EamArtifactUtil {
* EamArtifact with a single EamArtifactInstance within. If not, return
* null.
*
- * @param bbArtifact BlackboardArtifact to examine
+ * @param bbArtifact BlackboardArtifact to examine
* @param checkEnabled If true, only create a CorrelationAttribute if it is
- * enabled
+ * enabled
*
* @return List of EamArtifacts
*/
@@ -93,10 +93,10 @@ public class EamArtifactUtil {
* based on the data in the blackboard artifact.
*
* @param correlationType The Central Repository artifact type to create
- * @param bbArtifact The blackboard artifact to pull data from
+ * @param bbArtifact The blackboard artifact to pull data from
*
* @return the new EamArtifact, or null if one was not created because
- * bbArtifact did not contain the needed data
+ * bbArtifact did not contain the needed data
*/
private static CorrelationAttributeInstance makeInstanceFromBlackboardArtifact(CorrelationAttributeInstance.Type correlationType,
BlackboardArtifact bbArtifact) throws EamDbException {
@@ -159,13 +159,14 @@ public class EamArtifactUtil {
return null;
}
}
-
} else if (correlationType.getId() == CorrelationAttributeInstance.USBID_TYPE_ID
&& BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID() == artifactTypeID) {
value = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID)).getValueString();
+ } else if (correlationType.getId() == CorrelationAttributeInstance.SSID_TYPE_ID
+ && BlackboardArtifact.ARTIFACT_TYPE.TSK_WIFI_NETWORK.getTypeID() == artifactTypeID) {
+ value = bbArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SSID)).getValueString();
}
-
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting attribute while getting type from BlackboardArtifact.", ex); // NON-NLS
return null;
@@ -185,9 +186,10 @@ public class EamArtifactUtil {
* Uses the determined type and vallue, then looks up instance details to
* create proper CorrelationAttributeInstance.
*
- * @param bbArtifact the blackboard artifatc
+ * @param bbArtifact the blackboard artifact
* @param correlationType the given type
- * @param value the artifact value
+ * @param value the artifact value
+ *
* @return CorrelationAttributeInstance from details
*/
private static CorrelationAttributeInstance makeCorrelationAttributeInstanceUsingTypeValue(BlackboardArtifact bbArtifact, CorrelationAttributeInstance.Type correlationType, String value) {
@@ -205,14 +207,14 @@ public class EamArtifactUtil {
correlationCase = EamDb.getInstance().newCase(Case.getCurrentCaseThrows());
}
return new CorrelationAttributeInstance(
- value,
correlationType,
+ value,
correlationCase,
CorrelationDataSource.fromTSKDataSource(correlationCase, bbSourceFile.getDataSource()),
bbSourceFile.getParentPath() + bbSourceFile.getName(),
"",
- TskData.FileKnown.UNKNOWN
- );
+ TskData.FileKnown.UNKNOWN,
+ bbSourceFile.getId());
} catch (TskCoreException | EamDbException | CorrelationAttributeNormalizationException ex) {
logger.log(Level.SEVERE, "Error creating artifact instance.", ex); // NON-NLS
@@ -245,8 +247,6 @@ public class EamArtifactUtil {
CorrelationAttributeInstance.Type type;
CorrelationCase correlationCase;
CorrelationDataSource correlationDataSource;
- String value;
- String filePath;
try {
type = EamDb.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID);
@@ -256,8 +256,6 @@ public class EamArtifactUtil {
return null;
}
correlationDataSource = CorrelationDataSource.fromTSKDataSource(correlationCase, file.getDataSource());
- value = file.getMd5Hash();
- filePath = (file.getParentPath() + file.getName()).toLowerCase();
} catch (TskCoreException | EamDbException ex) {
logger.log(Level.SEVERE, "Error retrieving correlation attribute.", ex);
return null;
@@ -268,13 +266,26 @@ public class EamArtifactUtil {
CorrelationAttributeInstance correlationAttributeInstance;
try {
- correlationAttributeInstance = EamDb.getInstance().getCorrelationAttributeInstance(type, correlationCase, correlationDataSource, value, filePath);
+ correlationAttributeInstance = EamDb.getInstance().getCorrelationAttributeInstance(type, correlationCase, correlationDataSource, file.getId());
} catch (EamDbException | CorrelationAttributeNormalizationException ex) {
logger.log(Level.WARNING, String.format(
"Correlation attribute could not be retrieved for '%s' (id=%d): %s",
content.getName(), content.getId(), ex.getMessage()));
return null;
}
+ //if there was no correlation attribute found for the item using object_id then check for attributes added with schema 1,1 which lack object_id
+ if (correlationAttributeInstance == null) {
+ String value = file.getMd5Hash();
+ String filePath = (file.getParentPath() + file.getName()).toLowerCase();
+ try {
+ correlationAttributeInstance = EamDb.getInstance().getCorrelationAttributeInstance(type, correlationCase, correlationDataSource, value, filePath);
+ } catch (EamDbException | CorrelationAttributeNormalizationException ex) {
+ logger.log(Level.WARNING, String.format(
+ "Correlation attribute could not be retrieved for '%s' (id=%d): %s",
+ content.getName(), content.getId(), ex.getMessage()));
+ return null;
+ }
+ }
return correlationAttributeInstance;
}
@@ -317,12 +328,16 @@ public class EamArtifactUtil {
if (null == correlationCase) {
correlationCase = EamDb.getInstance().newCase(Case.getCurrentCaseThrows());
}
+
return new CorrelationAttributeInstance(
filesType,
af.getMd5Hash(),
correlationCase,
CorrelationDataSource.fromTSKDataSource(correlationCase, af.getDataSource()),
- af.getParentPath() + af.getName());
+ af.getParentPath() + af.getName(),
+ "",
+ TskData.FileKnown.UNKNOWN,
+ af.getId());
} catch (TskCoreException | EamDbException | CorrelationAttributeNormalizationException ex) {
logger.log(Level.SEVERE, "Error making correlation attribute.", ex);
@@ -340,7 +355,7 @@ public class EamArtifactUtil {
* @param file The file to test
*
* @return true if the file should be added to the central repo, false
- * otherwise
+ * otherwise
*/
public static boolean isSupportedAbstractFileType(AbstractFile file) {
if (file == null) {
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java
index c7e385928d..95584d0ebe 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java
@@ -31,11 +31,10 @@ import org.sleuthkit.datamodel.CaseDbSchemaVersionNumber;
*/
public interface EamDb {
- public static final int SCHEMA_VERSION = 1;
+ public static final int SCHEMA_VERSION = 2;
public static final CaseDbSchemaVersionNumber CURRENT_DB_SCHEMA_VERSION
- = new CaseDbSchemaVersionNumber(1, 1);
-
-
+ = new CaseDbSchemaVersionNumber(1, 2);
+
/**
* Get the instance
*
@@ -183,13 +182,14 @@ public interface EamDb {
* @return The retrieved case
*/
CorrelationCase getCaseById(int caseId) throws EamDbException;
+
/**
* Retrieves cases that are in DB.
*
* @return List of cases
*/
List getCases() throws EamDbException;
-
+
/**
* Creates new Data Source in the database
*
@@ -208,18 +208,17 @@ public interface EamDb {
*/
CorrelationDataSource getDataSource(CorrelationCase correlationCase, String dataSourceDeviceId) throws EamDbException;
-
/**
* Retrieves Data Source details based on data source ID
*
- * @param correlationCase the current CorrelationCase used for ensuring
- * uniqueness of DataSource
- * @param dataSourceId the data source ID number
+ * @param correlationCase the current CorrelationCase used for ensuring
+ * uniqueness of DataSource
+ * @param dataSourceId the data source ID number
*
* @return The data source
*/
CorrelationDataSource getDataSourceById(CorrelationCase correlationCase, int dataSourceId) throws EamDbException;
-
+
/**
* Retrieves data sources that are in DB
*
@@ -245,7 +244,7 @@ public interface EamDb {
* @return List of artifact instances for a given type/value
*/
List getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException;
-
+
/**
* Retrieves eamArtifact instances from the database that are associated
* with the aType and filePath
@@ -314,8 +313,8 @@ public interface EamDb {
/**
* Adds an eamArtifact to an internal list to be later added to DB. Artifact
- can have 1 or more Artifact Instances. Insert will be triggered by a
- threshold or a call to commitAttributeInstancesBulk().
+ * can have 1 or more Artifact Instances. Insert will be triggered by a
+ * threshold or a call to commitAttributeInstancesBulk().
*
* @param eamArtifact The artifact to add
*/
@@ -323,7 +322,7 @@ public interface EamDb {
/**
* Executes a bulk insert of the eamArtifacts added from the
- addAttributeInstanceBulk() method
+ * addAttributeInstanceBulk() method
*/
void commitAttributeInstancesBulk() throws EamDbException;
@@ -346,6 +345,9 @@ public interface EamDb {
/**
* Find a correlation attribute in the Central Repository database given the
* instance type, case, data source, value, and file path.
+ *
+ * Method exists to support instances added using Central Repository version 1,1 and
+ * older
*
* @param type The type of instance.
* @param correlationCase The case tied to the instance.
@@ -354,12 +356,28 @@ public interface EamDb {
* @param filePath The file path tied to the instance.
*
* @return The correlation attribute if it exists; otherwise null.
- *
+ *
* @throws EamDbException
*/
CorrelationAttributeInstance getCorrelationAttributeInstance(CorrelationAttributeInstance.Type type, CorrelationCase correlationCase,
CorrelationDataSource correlationDataSource, String value, String filePath) throws EamDbException, CorrelationAttributeNormalizationException;
+ /**
+ * Find a correlation attribute in the Central Repository database given the
+ * instance type, case, data source, object id.
+ *
+ * @param type The type of instance.
+ * @param correlationCase The case tied to the instance.
+ * @param correlationDataSource The data source tied to the instance.
+ * @param objectID The object id of the file tied to the instance.
+ *
+ * @return The correlation attribute if it exists; otherwise null.
+ *
+ * @throws EamDbException
+ */
+ CorrelationAttributeInstance getCorrelationAttributeInstance(CorrelationAttributeInstance.Type type, CorrelationCase correlationCase,
+ CorrelationDataSource correlationDataSource, long objectID) throws EamDbException, CorrelationAttributeNormalizationException;
+
/**
* Sets an eamArtifact instance to the given known status. If eamArtifact
* exists, it is updated. If eamArtifact does not exist nothing happens
@@ -383,12 +401,15 @@ public interface EamDb {
/**
* Gets list of matching eamArtifact instances that have knownStatus =
* "Bad".
- *
+ *
* @param aType EamArtifact.Type to search for
+ *
* @return List with 0 or more matching eamArtifact instances.
+ *
* @throws EamDbException
*/
List getArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType) throws EamDbException;
+
/**
* Count matching eamArtifacts instances that have knownStatus = "Bad".
*
@@ -490,7 +511,7 @@ public interface EamDb {
*
* @param eamOrg The organization to add
*
- * @return The organization with the org ID set.
+ * @return The organization with the org ID set.
*
* @throws EamDbException
*/
@@ -700,18 +721,20 @@ public interface EamDb {
/**
* Process the Artifact instance in the EamDb
*
- * @param type EamArtifact.Type to search for
+ * @param type EamArtifact.Type to search for
* @param instanceTableCallback callback to process the instance
+ *
* @throws EamDbException
*/
void processInstanceTable(CorrelationAttributeInstance.Type type, InstanceTableCallback instanceTableCallback) throws EamDbException;
-
+
/**
* Process the Artifact instance in the EamDb
*
- * @param type EamArtifact.Type to search for
+ * @param type EamArtifact.Type to search for
* @param instanceTableCallback callback to process the instance
- * @param whereClause query string to execute
+ * @param whereClause query string to execute
+ *
* @throws EamDbException
*/
void processInstanceTableWhere(CorrelationAttributeInstance.Type type, String whereClause, InstanceTableCallback instanceTableCallback) throws EamDbException;
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java
index 97abd1dec9..769b49bfd3 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java
@@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.centralrepository.datamodel;
import java.sql.Connection;
+import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.TimeUnit;
@@ -29,8 +30,7 @@ import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
- * Central Repository database implementation using Postgres as a
- * backend
+ * Central Repository database implementation using Postgres as a backend
*/
final class PostgresEamDb extends AbstractSqlEamDb {
@@ -47,10 +47,11 @@ final class PostgresEamDb extends AbstractSqlEamDb {
/**
* Get the singleton instance of PostgresEamDb
- *
+ *
* @return the singleton instance of PostgresEamDb
- *
- * @throws EamDbException if one or more default correlation type(s) have an invalid db table name.
+ *
+ * @throws EamDbException if one or more default correlation type(s) have an
+ * invalid db table name.
*/
public synchronized static PostgresEamDb getInstance() throws EamDbException {
if (instance == null) {
@@ -61,9 +62,10 @@ final class PostgresEamDb extends AbstractSqlEamDb {
}
/**
- *
- * @throws EamDbException if the AbstractSqlEamDb class has one or more default
- * correlation type(s) having an invalid db table name.
+ *
+ * @throws EamDbException if the AbstractSqlEamDb class has one or more
+ * default correlation type(s) having an invalid db
+ * table name.
*/
private PostgresEamDb() throws EamDbException {
dbSettings = new PostgresEamDbSettings();
@@ -73,8 +75,8 @@ final class PostgresEamDb extends AbstractSqlEamDb {
@Override
public void shutdownConnections() throws EamDbException {
try {
- synchronized(this) {
- if(connectionPool != null){
+ synchronized (this) {
+ if (connectionPool != null) {
connectionPool.close();
connectionPool = null; // force it to be re-created on next connect()
}
@@ -148,7 +150,7 @@ final class PostgresEamDb extends AbstractSqlEamDb {
connectionURL.append(dbSettings.getPort());
connectionURL.append("/");
connectionURL.append(dbSettings.getDbName());
-
+
connectionPool.setUrl(connectionURL.toString());
connectionPool.setUsername(dbSettings.getUserName());
connectionPool.setPassword(dbSettings.getPassword());
@@ -189,31 +191,34 @@ final class PostgresEamDb extends AbstractSqlEamDb {
protected String getConflictClause() {
return CONFLICT_CLAUSE;
}
-
+
/**
- * Gets an exclusive lock (if applicable).
- * Will return the lock if successful, null if unsuccessful because locking
- * isn't supported, and throw an exception if we should have been able to get the
- * lock but failed (meaning the database is in use).
+ * Gets an exclusive lock (if applicable). Will return the lock if
+ * successful, null if unsuccessful because locking isn't supported, and
+ * throw an exception if we should have been able to get the lock but failed
+ * (meaning the database is in use).
+ *
* @return the lock, or null if locking is not supported
- * @throws EamDbException if the coordination service is running but we fail to get the lock
+ *
+ * @throws EamDbException if the coordination service is running but we fail
+ * to get the lock
*/
@Override
- public CoordinationService.Lock getExclusiveMultiUserDbLock() throws EamDbException{
+ public CoordinationService.Lock getExclusiveMultiUserDbLock() throws EamDbException {
try {
// First check if multi user mode is enabled - if not there's no point trying to get a lock
- if( ! UserPreferences.getIsMultiUserModeEnabled()){
+ if (!UserPreferences.getIsMultiUserModeEnabled()) {
return null;
}
-
+
String databaseNodeName = dbSettings.getHost() + "_" + dbSettings.getDbName();
CoordinationService.Lock lock = CoordinationService.getInstance().tryGetExclusiveLock(CoordinationService.CategoryNode.CENTRAL_REPO, databaseNodeName, 5, TimeUnit.MINUTES);
- if(lock != null){
+ if (lock != null) {
return lock;
}
throw new EamDbException("Error acquiring database lock");
- } catch (InterruptedException ex){
+ } catch (InterruptedException ex) {
throw new EamDbException("Error acquiring database lock");
} catch (CoordinationService.CoordinationServiceException ex) {
// This likely just means the coordination service isn't running, which is ok
@@ -221,4 +226,23 @@ final class PostgresEamDb extends AbstractSqlEamDb {
}
}
+ @Override
+ boolean doesColumnExist(Connection conn, String tableName, String columnName) throws SQLException {
+ final String objectIdColumnExistsTemplate = "SELECT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='%s' AND column_name='%s')"; //NON-NLS
+ ResultSet resultSet = null;
+ Statement statement = null;
+ boolean columnExists = false;
+ try {
+ statement = conn.createStatement();
+ resultSet = statement.executeQuery(String.format(objectIdColumnExistsTemplate, tableName, columnName));
+ if (resultSet.next()) {
+ columnExists = resultSet.getBoolean(1);
+ }
+ } finally {
+ EamDbUtil.closeResultSet(resultSet);
+ EamDbUtil.closeStatement(statement);
+ }
+ return columnExists;
+ }
+
}
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java
index 77ab8c23db..8183f445e3 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java
@@ -35,8 +35,9 @@ import org.sleuthkit.autopsy.coreutils.TextConverterException;
/**
* Settings for the Postgres implementation of the Central Repository database
- *
- * NOTE: This is public scope because the options panel calls it directly to set/get
+ *
+ * NOTE: This is public scope because the options panel calls it directly to
+ * set/get
*/
public final class PostgresEamDbSettings {
@@ -266,7 +267,7 @@ public final class PostgresEamDbSettings {
return true;
}
-
+
public boolean deleteDatabase() {
Connection conn = getEphemeralConnection(true);
if (null == conn) {
@@ -391,26 +392,13 @@ public final class PostgresEamDbSettings {
createCorrelationTypesTable.append("CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)");
createCorrelationTypesTable.append(")");
- // Each "%s" will be replaced with the relevant TYPE_instances table name.
- StringBuilder createArtifactInstancesTableTemplate = new StringBuilder();
- createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
- createArtifactInstancesTableTemplate.append("id SERIAL PRIMARY KEY,");
- createArtifactInstancesTableTemplate.append("case_id integer NOT NULL,");
- createArtifactInstancesTableTemplate.append("data_source_id integer NOT NULL,");
- createArtifactInstancesTableTemplate.append("value text NOT NULL,");
- createArtifactInstancesTableTemplate.append("file_path text NOT NULL,");
- createArtifactInstancesTableTemplate.append("known_status integer NOT NULL,");
- createArtifactInstancesTableTemplate.append("comment text,");
- createArtifactInstancesTableTemplate.append("CONSTRAINT %s_multi_unique_ UNIQUE (data_source_id, value, file_path),");
- createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,");
- createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL");
- createArtifactInstancesTableTemplate.append(")");
+ String createArtifactInstancesTableTemplate = getCreateArtifactInstancesTableTemplate();
- // Each "%s" will be replaced with the relevant TYPE_instances table name.
- String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)";
- String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
- String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
- String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
+ String instancesCaseIdIdx = getAddCaseIdIndexTemplate();
+ String instancesDatasourceIdIdx = getAddDataSourceIdIndexTemplate();
+ String instancesValueIdx = getAddValueIndexTemplate();
+ String instancesKnownStatusIdx = getAddKnownStatusIndexTemplate();
+ String instancesObjectIdIdx = getAddObjectIdIndexTemplate();
StringBuilder createDbInfoTable = new StringBuilder();
createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info (");
@@ -447,25 +435,26 @@ public final class PostgresEamDbSettings {
// Create a separate instance and reference table for each correlation type
List DEFAULT_CORRELATION_TYPES = CorrelationAttributeInstance.getDefaultCorrelationTypes();
-
+
String reference_type_dbname;
String instance_type_dbname;
for (CorrelationAttributeInstance.Type type : DEFAULT_CORRELATION_TYPES) {
reference_type_dbname = EamDbUtil.correlationTypeToReferenceTableName(type);
instance_type_dbname = EamDbUtil.correlationTypeToInstanceTableName(type);
-
- stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), instance_type_dbname, instance_type_dbname));
- stmt.execute(String.format(instancesIdx1, instance_type_dbname, instance_type_dbname));
- stmt.execute(String.format(instancesIdx2, instance_type_dbname, instance_type_dbname));
- stmt.execute(String.format(instancesIdx3, instance_type_dbname, instance_type_dbname));
- stmt.execute(String.format(instancesIdx4, instance_type_dbname, instance_type_dbname));
+
+ stmt.execute(String.format(createArtifactInstancesTableTemplate, instance_type_dbname, instance_type_dbname));
+ stmt.execute(String.format(instancesCaseIdIdx, instance_type_dbname, instance_type_dbname));
+ stmt.execute(String.format(instancesDatasourceIdIdx, instance_type_dbname, instance_type_dbname));
+ stmt.execute(String.format(instancesValueIdx, instance_type_dbname, instance_type_dbname));
+ stmt.execute(String.format(instancesKnownStatusIdx, instance_type_dbname, instance_type_dbname));
+ stmt.execute(String.format(instancesObjectIdIdx, instance_type_dbname, instance_type_dbname));
// FUTURE: allow more than the FILES type
if (type.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
stmt.execute(String.format(createReferenceTypesTableTemplate.toString(), reference_type_dbname, reference_type_dbname));
stmt.execute(String.format(referenceTypesIdx1, reference_type_dbname, reference_type_dbname));
stmt.execute(String.format(referenceTypesIdx2, reference_type_dbname, reference_type_dbname));
- }
+ }
}
} catch (SQLException ex) {
@@ -480,6 +469,97 @@ public final class PostgresEamDbSettings {
return true;
}
+ /**
+ * Get the template String for creating a new _instances table in a Postgres
+ * central repository. %s will exist in the template where the name of the
+ * new table will be addedd.
+ *
+ * @return a String which is a template for cretating a new _instances table
+ */
+ static String getCreateArtifactInstancesTableTemplate() {
+ // Each "%s" will be replaced with the relevant TYPE_instances table name.
+ StringBuilder createArtifactInstancesTableTemplate = new StringBuilder();
+ createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
+ createArtifactInstancesTableTemplate.append("id SERIAL PRIMARY KEY,");
+ createArtifactInstancesTableTemplate.append("case_id integer NOT NULL,");
+ createArtifactInstancesTableTemplate.append("data_source_id integer NOT NULL,");
+ createArtifactInstancesTableTemplate.append("value text NOT NULL,");
+ createArtifactInstancesTableTemplate.append("file_path text NOT NULL,");
+ createArtifactInstancesTableTemplate.append("known_status integer NOT NULL,");
+ createArtifactInstancesTableTemplate.append("comment text,");
+ createArtifactInstancesTableTemplate.append("file_obj_id integer,");
+ createArtifactInstancesTableTemplate.append("CONSTRAINT %s_multi_unique_ UNIQUE (data_source_id, value, file_path),");
+ createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,");
+ createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL");
+ createArtifactInstancesTableTemplate.append(")");
+ return createArtifactInstancesTableTemplate.toString();
+ }
+
+ /**
+ * Get the template for creating an index on the case_id column of an
+ * instance table. %s will exist in the template where the name of the new
+ * table will be addedd.
+ *
+ * @return a String which is a template for adding an index to the case_id
+ * column of a _instances table
+ */
+ static String getAddCaseIdIndexTemplate() {
+ // Each "%s" will be replaced with the relevant TYPE_instances table name.
+ return "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)";
+ }
+
+ /**
+ * Get the template for creating an index on the data_source_id column of an
+ * instance table. %s will exist in the template where the name of the new
+ * table will be addedd.
+ *
+ * @return a String which is a template for adding an index to the
+ * data_source_id column of a _instances table
+ */
+ static String getAddDataSourceIdIndexTemplate() {
+ // Each "%s" will be replaced with the relevant TYPE_instances table name.
+ return "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
+ }
+
+ /**
+ * Get the template for creating an index on the value column of an instance
+ * table. %s will exist in the template where the name of the new table will
+ * be addedd.
+ *
+ * @return a String which is a template for adding an index to the value
+ * column of a _instances table
+ */
+ static String getAddValueIndexTemplate() {
+ // Each "%s" will be replaced with the relevant TYPE_instances table name.
+ return "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
+ }
+
+ /**
+ * Get the template for creating an index on the known_status column of an
+ * instance table. %s will exist in the template where the name of the new
+ * table will be addedd.
+ *
+ * @return a String which is a template for adding an index to the
+ * known_status column of a _instances table
+ */
+ static String getAddKnownStatusIndexTemplate() {
+ // Each "%s" will be replaced with the relevant TYPE_instances table name.
+ return "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
+ }
+
+ /**
+ * Get the template for creating an index on the file_obj_id column of an
+ * instance table. %s will exist in the template where the name of the new
+ * table will be addedd.
+ *
+ * @return a String which is a template for adding an index to the file_obj_id
+ * column of a _instances table
+ */
+ static String getAddObjectIdIndexTemplate() {
+ // Each "%s" will be replaced with the relevant TYPE_instances table name.
+ return "CREATE INDEX IF NOT EXISTS %s_file_obj_id ON %s (file_obj_id)";
+ }
+
public boolean insertDefaultDatabaseContent() {
Connection conn = getEphemeralConnection(false);
if (null == conn) {
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java
index a75f4648ff..6468801a57 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java
@@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.centralrepository.datamodel;
import java.sql.Connection;
+import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
@@ -57,7 +58,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* @return the singleton instance of SqliteEamDb
*
* @throws EamDbException if one or more default correlation type(s) have an
- * invalid db table name.
+ * invalid db table name.
*/
public synchronized static SqliteEamDb getInstance() throws EamDbException {
if (instance == null) {
@@ -70,7 +71,8 @@ final class SqliteEamDb extends AbstractSqlEamDb {
/**
*
* @throws EamDbException if the AbstractSqlEamDb class has one or more
- * default correlation type(s) having an invalid db table name.
+ * default correlation type(s) having an invalid db
+ * table name.
*/
private SqliteEamDb() throws EamDbException {
dbSettings = new SqliteEamDbSettings();
@@ -205,7 +207,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
/**
* Add a new name/value pair in the db_info table.
*
- * @param name Key to set
+ * @param name Key to set
* @param value Value to set
*
* @throws EamDbException
@@ -242,7 +244,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
/**
* Update the value for a name in the name/value db_info table.
*
- * @param name Name to find
+ * @param name Name to find
* @param value Value to assign to name.
*
* @throws EamDbException
@@ -372,8 +374,8 @@ final class SqliteEamDb extends AbstractSqlEamDb {
/**
* Retrieves Data Source details based on data source device ID
*
- * @param correlationCase the current CorrelationCase used for ensuring
- * uniqueness of DataSource
+ * @param correlationCase the current CorrelationCase used for ensuring
+ * uniqueness of DataSource
* @param dataSourceDeviceId the data source device ID number
*
* @return The data source
@@ -387,13 +389,13 @@ final class SqliteEamDb extends AbstractSqlEamDb {
releaseSharedLock();
}
}
-
+
/**
* Retrieves Data Source details based on data source ID
*
- * @param correlationCase the current CorrelationCase used for ensuring
- * uniqueness of DataSource
- * @param dataSourceId the data source ID number
+ * @param correlationCase the current CorrelationCase used for ensuring
+ * uniqueness of DataSource
+ * @param dataSourceId the data source ID number
*
* @return The data source
*/
@@ -461,7 +463,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* Retrieves eamArtifact instances from the database that are associated
* with the aType and filePath
*
- * @param aType EamArtifact.Type to search for
+ * @param aType EamArtifact.Type to search for
* @param filePath File path to search for
*
* @return List of 0 or more EamArtifactInstances
@@ -486,7 +488,8 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* @param value The value to search for
*
* @return Number of artifact instances having ArtifactType and
- * ArtifactValue.
+ * ArtifactValue.
+ *
* @throws EamDbException
*/
@Override
@@ -518,6 +521,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* @param value The value to search for
*
* @return Number of unique tuples
+ *
* @throws EamDbException
*/
@Override
@@ -545,11 +549,11 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* associated with the caseDisplayName and dataSource of the given
* eamArtifact instance.
*
- * @param caseUUID Case ID to search for
+ * @param caseUUID Case ID to search for
* @param dataSourceID Data source ID to search for
*
* @return Number of artifact instances having caseDisplayName and
- * dataSource
+ * dataSource
*/
@Override
public Long getCountArtifactInstancesByCaseDataSource(String caseUUID, String dataSourceID) throws EamDbException {
@@ -563,7 +567,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
/**
* Executes a bulk insert of the eamArtifacts added from the
- addAttributeInstanceBulk() method
+ * addAttributeInstanceBulk() method
*/
@Override
public void commitAttributeInstancesBulk() throws EamDbException {
@@ -596,7 +600,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
*
* @param eamArtifact Artifact containing exactly one (1) ArtifactInstance.
* @param knownStatus The status to change the artifact to. Should never be
- * KNOWN
+ * KNOWN
*/
@Override
public void setAttributeInstanceKnownStatus(CorrelationAttributeInstance eamArtifact, TskData.FileKnown knownStatus) throws EamDbException {
@@ -633,7 +637,9 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* "Bad".
*
* @param aType EamArtifact.Type to search for
+ *
* @return List with 0 or more matching eamArtifact instances.
+ *
* @throws EamDbException
*/
@Override
@@ -672,7 +678,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* @param value Value to search for
*
* @return List of cases containing this artifact with instances marked as
- * bad
+ * bad
*
* @throws EamDbException
*/
@@ -690,6 +696,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* Remove a reference set and all values contained in it.
*
* @param referenceSetID
+ *
* @throws EamDbException
*/
@Override
@@ -708,6 +715,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* @param value
* @param referenceSetID
* @param correlationTypeID
+ *
* @return true if the hash is found in the reference set
*/
@Override
@@ -723,8 +731,9 @@ final class SqliteEamDb extends AbstractSqlEamDb {
/**
* Process the Artifact instance in the EamDb
*
- * @param type EamArtifact.Type to search for
+ * @param type EamArtifact.Type to search for
* @param instanceTableCallback callback to process the instance
+ *
* @throws EamDbException
*/
@Override
@@ -736,12 +745,13 @@ final class SqliteEamDb extends AbstractSqlEamDb {
releaseSharedLock();
}
}
-
+
/**
* Process the Artifact instance in the EamDb
*
- * @param type EamArtifact.Type to search for
+ * @param type EamArtifact.Type to search for
* @param instanceTableCallback callback to process the instance
+ *
* @throws EamDbException
*/
@Override
@@ -752,7 +762,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
} finally {
releaseSharedLock();
}
- }
+ }
/**
* Check whether a reference set with the given name/version is in the
@@ -761,7 +771,9 @@ final class SqliteEamDb extends AbstractSqlEamDb {
*
* @param referenceSetName
* @param version
+ *
* @return true if a matching set is found
+ *
* @throws EamDbException
*/
@Override
@@ -928,7 +940,8 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* Add a new reference instance
*
* @param eamGlobalFileInstance The reference instance to add
- * @param correlationType Correlation Type that this Reference Instance is
+ * @param correlationType Correlation Type that this Reference
+ * Instance is
*
* @throws EamDbException
*/
@@ -960,7 +973,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
/**
* Get all reference entries having a given correlation type and value
*
- * @param aType Type to use for matching
+ * @param aType Type to use for matching
* @param aValue Value to use for matching
*
* @return List of all global file instances with a type and value
@@ -1001,7 +1014,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* artifacts.
*
* @return List of EamArtifact.Type's. If none are defined in the database,
- * the default list will be returned.
+ * the default list will be returned.
*
* @throws EamDbException
*/
@@ -1020,7 +1033,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* artifacts.
*
* @return List of enabled EamArtifact.Type's. If none are defined in the
- * database, the default list will be returned.
+ * database, the default list will be returned.
*
* @throws EamDbException
*/
@@ -1039,7 +1052,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* correlate artifacts.
*
* @return List of supported EamArtifact.Type's. If none are defined in the
- * database, the default list will be returned.
+ * database, the default list will be returned.
*
* @throws EamDbException
*/
@@ -1111,8 +1124,9 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* (meaning the database is in use).
*
* @return the lock, or null if locking is not supported
+ *
* @throws EamDbException if the coordination service is running but we fail
- * to get the lock
+ * to get the lock
*/
@Override
public CoordinationService.Lock getExclusiveMultiUserDbLock() throws EamDbException {
@@ -1156,4 +1170,26 @@ final class SqliteEamDb extends AbstractSqlEamDb {
rwLock.readLock().unlock();
}
+ @Override
+ boolean doesColumnExist(Connection conn, String tableName, String columnName) throws SQLException {
+ final String tableInfoQueryTemplate = "PRAGMA table_info(%s)"; //NON-NLS
+ ResultSet resultSet = null;
+ Statement statement = null;
+ boolean columnExists = false;
+ try {
+ statement = conn.createStatement();
+ resultSet = statement.executeQuery(String.format(tableInfoQueryTemplate, tableName));
+ while (resultSet.next()) {
+ // the second value ( 2 ) is the column name
+ if (resultSet.getString(2).equals(columnName)) {
+ columnExists = true;
+ break;
+ }
+ }
+ } finally {
+ EamDbUtil.closeResultSet(resultSet);
+ EamDbUtil.closeStatement(statement);
+ }
+ return columnExists;
+ }
}
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java
index 4894a570e6..8b034149fc 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java
@@ -35,8 +35,9 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil;
/**
* Settings for the sqlite implementation of the Central Repository database
- *
- * NOTE: This is public scope because the options panel calls it directly to set/get
+ *
+ * NOTE: This is public scope because the options panel calls it directly to
+ * set/get
*/
public final class SqliteEamDbSettings {
@@ -95,7 +96,7 @@ public final class SqliteEamDbSettings {
ModuleSettings.setConfigSetting("CentralRepository", "db.sqlite.dbDirectory", getDbDirectory()); // NON-NLS
ModuleSettings.setConfigSetting("CentralRepository", "db.sqlite.bulkThreshold", Integer.toString(getBulkThreshold())); // NON-NLS
}
-
+
/**
* Verify that the db file exists.
*
@@ -103,11 +104,11 @@ public final class SqliteEamDbSettings {
*/
public boolean dbFileExists() {
File dbFile = new File(getFileNameWithPath());
- if(! dbFile.exists()){
+ if (!dbFile.exists()) {
return false;
}
// It's unlikely, but make sure the file isn't actually a directory
- return ( ! dbFile.isDirectory());
+ return (!dbFile.isDirectory());
}
/**
@@ -148,10 +149,11 @@ public final class SqliteEamDbSettings {
return true;
}
-
+
/**
* Delete the database
- * @return
+ *
+ * @return
*/
public boolean deleteDatabase() {
File dbFile = new File(this.getFileNameWithPath());
@@ -333,27 +335,14 @@ public final class SqliteEamDbSettings {
createCorrelationTypesTable.append("CONSTRAINT correlation_types_names UNIQUE (display_name, db_table_name)");
createCorrelationTypesTable.append(")");
- // Each "%s" will be replaced with the relevant TYPE_instances table name.
- StringBuilder createArtifactInstancesTableTemplate = new StringBuilder();
- createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
- createArtifactInstancesTableTemplate.append("id integer primary key autoincrement NOT NULL,");
- createArtifactInstancesTableTemplate.append("case_id integer NOT NULL,");
- createArtifactInstancesTableTemplate.append("data_source_id integer NOT NULL,");
- createArtifactInstancesTableTemplate.append("value text NOT NULL,");
- createArtifactInstancesTableTemplate.append("file_path text NOT NULL,");
- createArtifactInstancesTableTemplate.append("known_status integer NOT NULL,");
- createArtifactInstancesTableTemplate.append("comment text,");
- createArtifactInstancesTableTemplate.append("CONSTRAINT %s_multi_unique UNIQUE(data_source_id, value, file_path) ON CONFLICT IGNORE,");
- createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,");
- createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL");
- createArtifactInstancesTableTemplate.append(")");
-
- // Each "%s" will be replaced with the relevant TYPE_instances table name.
- String instancesIdx1 = "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)";
- String instancesIdx2 = "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
- String instancesIdx3 = "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
- String instancesIdx4 = "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
+ String createArtifactInstancesTableTemplate = getCreateArtifactInstancesTableTemplate();
+ String instancesCaseIdIdx = getAddCaseIdIndexTemplate();
+ String instancesDatasourceIdIdx = getAddDataSourceIdIndexTemplate();
+ String instancesValueIdx = getAddValueIndexTemplate();
+ String instancesKnownStatusIdx = getAddKnownStatusIndexTemplate();
+ String instancesObjectIdIdx = getAddObjectIdIndexTemplate();
+
StringBuilder createDbInfoTable = new StringBuilder();
createDbInfoTable.append("CREATE TABLE IF NOT EXISTS db_info (");
createDbInfoTable.append("id integer primary key NOT NULL,");
@@ -402,11 +391,12 @@ public final class SqliteEamDbSettings {
reference_type_dbname = EamDbUtil.correlationTypeToReferenceTableName(type);
instance_type_dbname = EamDbUtil.correlationTypeToInstanceTableName(type);
- stmt.execute(String.format(createArtifactInstancesTableTemplate.toString(), instance_type_dbname, instance_type_dbname));
- stmt.execute(String.format(instancesIdx1, instance_type_dbname, instance_type_dbname));
- stmt.execute(String.format(instancesIdx2, instance_type_dbname, instance_type_dbname));
- stmt.execute(String.format(instancesIdx3, instance_type_dbname, instance_type_dbname));
- stmt.execute(String.format(instancesIdx4, instance_type_dbname, instance_type_dbname));
+ stmt.execute(String.format(createArtifactInstancesTableTemplate, instance_type_dbname, instance_type_dbname));
+ stmt.execute(String.format(instancesCaseIdIdx, instance_type_dbname, instance_type_dbname));
+ stmt.execute(String.format(instancesDatasourceIdIdx, instance_type_dbname, instance_type_dbname));
+ stmt.execute(String.format(instancesValueIdx, instance_type_dbname, instance_type_dbname));
+ stmt.execute(String.format(instancesKnownStatusIdx, instance_type_dbname, instance_type_dbname));
+ stmt.execute(String.format(instancesObjectIdIdx, instance_type_dbname, instance_type_dbname));
// FUTURE: allow more than the FILES type
if (type.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
@@ -426,6 +416,97 @@ public final class SqliteEamDbSettings {
}
return true;
}
+
+ /**
+ * Get the template String for creating a new _instances table in a Sqlite
+ * central repository. %s will exist in the template where the name of the
+ * new table will be addedd.
+ *
+ * @return a String which is a template for cretating a new _instances table
+ */
+ static String getCreateArtifactInstancesTableTemplate() {
+ // Each "%s" will be replaced with the relevant TYPE_instances table name.
+ StringBuilder createArtifactInstancesTableTemplate = new StringBuilder();
+ createArtifactInstancesTableTemplate.append("CREATE TABLE IF NOT EXISTS %s (");
+ createArtifactInstancesTableTemplate.append("id integer primary key autoincrement NOT NULL,");
+ createArtifactInstancesTableTemplate.append("case_id integer NOT NULL,");
+ createArtifactInstancesTableTemplate.append("data_source_id integer NOT NULL,");
+ createArtifactInstancesTableTemplate.append("value text NOT NULL,");
+ createArtifactInstancesTableTemplate.append("file_path text NOT NULL,");
+ createArtifactInstancesTableTemplate.append("known_status integer NOT NULL,");
+ createArtifactInstancesTableTemplate.append("comment text,");
+ createArtifactInstancesTableTemplate.append("file_obj_id integer,");
+ createArtifactInstancesTableTemplate.append("CONSTRAINT %s_multi_unique UNIQUE(data_source_id, value, file_path) ON CONFLICT IGNORE,");
+ createArtifactInstancesTableTemplate.append("foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL,");
+ createArtifactInstancesTableTemplate.append("foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL");
+ createArtifactInstancesTableTemplate.append(")");
+ return createArtifactInstancesTableTemplate.toString();
+ }
+
+ /**
+ * Get the template for creating an index on the case_id column of an
+ * instance table. %s will exist in the template where the name of the new
+ * table will be addedd.
+ *
+ * @return a String which is a template for adding an index to the case_id
+ * column of a _instances table
+ */
+ static String getAddCaseIdIndexTemplate() {
+ // Each "%s" will be replaced with the relevant TYPE_instances table name.
+ return "CREATE INDEX IF NOT EXISTS %s_case_id ON %s (case_id)";
+ }
+
+ /**
+ * Get the template for creating an index on the data_source_id column of an
+ * instance table. %s will exist in the template where the name of the new
+ * table will be addedd.
+ *
+ * @return a String which is a template for adding an index to the
+ * data_source_id column of a _instances table
+ */
+ static String getAddDataSourceIdIndexTemplate() {
+ // Each "%s" will be replaced with the relevant TYPE_instances table name.
+ return "CREATE INDEX IF NOT EXISTS %s_data_source_id ON %s (data_source_id)";
+ }
+
+ /**
+ * Get the template for creating an index on the value column of an instance
+ * table. %s will exist in the template where the name of the new table will
+ * be addedd.
+ *
+ * @return a String which is a template for adding an index to the value
+ * column of a _instances table
+ */
+ static String getAddValueIndexTemplate() {
+ // Each "%s" will be replaced with the relevant TYPE_instances table name.
+ return "CREATE INDEX IF NOT EXISTS %s_value ON %s (value)";
+ }
+
+ /**
+ * Get the template for creating an index on the known_status column of an
+ * instance table. %s will exist in the template where the name of the new
+ * table will be addedd.
+ *
+ * @return a String which is a template for adding an index to the
+ * known_status column of a _instances table
+ */
+ static String getAddKnownStatusIndexTemplate() {
+ // Each "%s" will be replaced with the relevant TYPE_instances table name.
+ return "CREATE INDEX IF NOT EXISTS %s_value_known_status ON %s (value, known_status)";
+ }
+
+ /**
+ * Get the template for creating an index on the file_obj_id column of an
+ * instance table. %s will exist in the template where the name of the new
+ * table will be addedd.
+ *
+ * @return a String which is a template for adding an index to the file_obj_id
+ * column of a _instances table
+ */
+ static String getAddObjectIdIndexTemplate() {
+ // Each "%s" will be replaced with the relevant TYPE_instances table name.
+ return "CREATE INDEX IF NOT EXISTS %s_file_obj_id ON %s (file_obj_id)";
+ }
public boolean insertDefaultDatabaseContent() {
Connection conn = getEphemeralConnection();
@@ -490,8 +571,6 @@ public final class SqliteEamDbSettings {
}
}
-
-
/**
* @return the dbDirectory
*/
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java
index cdfc282b7e..34436380e2 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java
@@ -183,7 +183,10 @@ public class IngestEventsListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
- if (getCeModuleInstanceCount() > 0) {
+ //if ingest is running we want there to check if there is a Correlation Engine module running
+ //sometimes artifacts are generated by DSPs or other sources while ingest is not running
+ //in these cases we still want to create correlation attributes for those artifacts when appropriate
+ if (!IngestManager.getInstance().isIngestRunning() || getCeModuleInstanceCount() > 0) {
EamDb dbManager;
try {
dbManager = EamDb.getInstance();
@@ -193,7 +196,9 @@ public class IngestEventsListener {
}
switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) {
case DATA_ADDED: {
- jobProcessingExecutor.submit(new DataAddedTask(dbManager, evt, isFlagNotableItems()));
+ //if ingest isn't running create the interesting items otherwise use the ingest module setting to determine if we create interesting items
+ boolean flagNotable = !IngestManager.getInstance().isIngestRunning() || isFlagNotableItems();
+ jobProcessingExecutor.submit(new DataAddedTask(dbManager, evt, flagNotable));
break;
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java
index 05fb3e4c8c..e7894c7916 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java
@@ -70,7 +70,6 @@ final class IngestModule implements FileIngestModule {
private CorrelationDataSource eamDataSource;
private Blackboard blackboard;
private CorrelationAttributeInstance.Type filesType;
-
private final boolean flagTaggedNotableItems;
/**
@@ -152,14 +151,14 @@ final class IngestModule implements FileIngestModule {
// insert this file into the central repository
try {
CorrelationAttributeInstance cefi = new CorrelationAttributeInstance(
+ filesType,
md5,
- filesType,
eamCase,
eamDataSource,
abstractFile.getParentPath() + abstractFile.getName(),
null,
TskData.FileKnown.UNKNOWN // NOTE: Known status in the CR is based on tagging, not hashes like the Case Database.
- );
+, abstractFile.getId());
dbManager.addAttributeInstanceBulk(cefi);
} catch (EamDbException ex) {
logger.log(Level.SEVERE, "Error adding artifact to bulk artifacts.", ex); // NON-NLS
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties
index 0fc1951593..aae9fa321d 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties
@@ -34,7 +34,7 @@ AddNewOrganizationDialog.bnOK.text=OK
AddNewOrganizationDialog.tfName.tooltip=POC Name
ManageTagsDialog.okButton.text=OK
ManageTagsDialog.cancelButton.text=Cancel
-ManageArtifactTypesDialog.taInstructionsMsg.text=Enable one or more correlation properties to use for correlation during ingest. Note, these properties are global and impact all users of the central repository.
+ManageArtifactTypesDialog.taInstructionsMsg.text=Enable one or more correlation properties to use for correlation during ingest. Note, these properties are global and impact all users of the Central Repository.
EamSqliteSettingsDialog.bnOk.text=OK
EamPostgresSettingsDialog.bnSave.text=Save
EamDbSettingsDialog.bnDatabasePathFileOpen.text=Browse...
@@ -58,11 +58,10 @@ ManageCorrelationPropertiesDialog.okButton.text=OK
GlobalSettingsPanel.bnManageProperties.text=Manage Correlation Properties
EamDbSettingsDialog.lbDatabaseDesc.text=Database File:
EamDbSettingsDialog.lbFullDbPath.text=
-GlobalSettingsPanel.cbUseCentralRepo.text=Use a central repository
-GlobalSettingsPanel.correlationPropertiesTextArea.text=Choose which file and result properties to store in the central repository for later correlation.\n
-GlobalSettingsPanel.organizationTextArea.text=Organization information can be tracked in the central repository.
+GlobalSettingsPanel.cbUseCentralRepo.text=Use a Central Repository
+GlobalSettingsPanel.organizationTextArea.text=Organization information can be tracked in the Central Repository.
GlobalSettingsPanel.manageOrganizationButton.text=Manage Organizations
-GlobalSettingsPanel.lbCentralRepository.text=A central repository allows you to correlate files and results between cases.
+GlobalSettingsPanel.lbCentralRepository.text=A Central Repository allows you to correlate files and results between cases.
GlobalSettingsPanel.pnCorrelationProperties.border.title=Correlation Properties
GlobalSettingsPanel.organizationPanel.border.title=Organizations
GlobalSettingsPanel.casesPanel.border.title=Case Details
@@ -74,8 +73,9 @@ ShowCasesDialog.caseDetailsTable.toolTipText=Click column name to sort. Right-cl
ShowCasesDialog.title=Case Details
GlobalSettingsPanel.Case\ Details.AccessibleContext.accessibleName=Cases Details
ShowCasesDialog.caseDetailsTable.AccessibleContext.accessibleDescription=Click column name to sort.
-GlobalSettingsPanel.casesTextArea.text=Display table that lists central repository case details.
-GlobalSettingsPanel.ingestRunningWarningLabel.text=Cannot make changes to central repository settings when ingest is running!
+GlobalSettingsPanel.casesTextArea.text=Display table that lists Central Repository case details.
+GlobalSettingsPanel.ingestRunningWarningLabel.text=Cannot make changes to Central Repository settings when ingest is running!
+GlobalSettingsPanel.correlationPropertiesTextArea.text=Choose which file and result properties to store in the Central Repository for later correlation.\n
ManageCasesDialog.examinerPhoneLabel.text=Examiner Phone:
ManageCasesDialog.examinerNameLabel.text=Examiner Name:
ManageCasesDialog.examinerEmailLabel.text=Examiner Email:
@@ -84,4 +84,4 @@ ManageCasesDialog.orgLabel.text=Organization:
ManageCasesDialog.closeButton.text=Close
ManageCasesDialog.notesLabel.text=Notes:
ManageCasesDialog.dataSourcesLabel.text=Data Sources:
-ManageCasesDialog.caseInfoLabel.text=Case Info:
+ManageCasesDialog.caseInfoLabel.text=Case Info:
\ No newline at end of file
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java
index c504f666e4..826e66ecbc 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java
@@ -102,7 +102,7 @@ public class EamDbSettingsDialog extends JDialog {
@Override
public String getDescription() {
- return "Directories and central repository databases";
+ return "Directories and Central Repository databases";
}
});
cbDatabaseType.setSelectedItem(selectedPlatform);
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form
index c3a8f678d6..0a8c7dcc64 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form
@@ -57,7 +57,7 @@
-
+
@@ -67,7 +67,7 @@
-
+
@@ -89,13 +89,13 @@
-
+
-
+
-
+
-
+
@@ -242,14 +242,14 @@
-
-
+
+
-
-
+
+
@@ -258,8 +258,7 @@
-
-
+
@@ -301,7 +300,7 @@
-
+
@@ -334,7 +333,7 @@
-
+
diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java
index e24fe70ea8..a4d6ef5cc0 100644
--- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java
@@ -222,7 +222,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
correlationPropertiesTextArea.setColumns(20);
correlationPropertiesTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
correlationPropertiesTextArea.setLineWrap(true);
- correlationPropertiesTextArea.setRows(2);
+ correlationPropertiesTextArea.setRows(1);
correlationPropertiesTextArea.setText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.correlationPropertiesTextArea.text")); // NOI18N
correlationPropertiesTextArea.setToolTipText("");
correlationPropertiesTextArea.setWrapStyleWord(true);
@@ -236,17 +236,16 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
.addGroup(pnCorrelationPropertiesLayout.createSequentialGroup()
.addContainerGap()
.addGroup(pnCorrelationPropertiesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(correlationPropertiesScrollPane)
.addGroup(pnCorrelationPropertiesLayout.createSequentialGroup()
.addComponent(bnManageTypes)
- .addGap(0, 0, Short.MAX_VALUE)))
+ .addGap(0, 0, Short.MAX_VALUE))
+ .addComponent(correlationPropertiesScrollPane))
.addContainerGap())
);
pnCorrelationPropertiesLayout.setVerticalGroup(
pnCorrelationPropertiesLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnCorrelationPropertiesLayout.createSequentialGroup()
- .addGap(7, 7, 7)
- .addComponent(correlationPropertiesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(correlationPropertiesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 32, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bnManageTypes)
.addGap(8, 8, 8))
@@ -281,7 +280,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
.addGroup(organizationPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(organizationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(organizationScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 992, Short.MAX_VALUE)
+ .addComponent(organizationScrollPane)
.addGroup(organizationPanelLayout.createSequentialGroup()
.addComponent(manageOrganizationButton)
.addGap(0, 0, Short.MAX_VALUE)))
@@ -356,7 +355,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(lbCentralRepository, javax.swing.GroupLayout.DEFAULT_SIZE, 1022, Short.MAX_VALUE)
+ .addComponent(lbCentralRepository, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
@@ -366,7 +365,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(cbUseCentralRepo, javax.swing.GroupLayout.PREFERRED_SIZE, 162, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
- .addComponent(ingestRunningWarningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addComponent(ingestRunningWarningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 844, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, 974, javax.swing.GroupLayout.PREFERRED_SIZE)))
@@ -382,13 +381,13 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i
.addComponent(ingestRunningWarningLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGap(0, 0, 0)
.addComponent(pnCorrelationProperties, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGap(0, 0, 0)
.addComponent(organizationPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGap(0, 0, 0)
.addComponent(casesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGap(0, 0, 0)
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CaseDBCommonAttributeInstanceNode.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CaseDBCommonAttributeInstanceNode.java
index b4f8ee525e..504aa45b97 100644
--- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CaseDBCommonAttributeInstanceNode.java
+++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CaseDBCommonAttributeInstanceNode.java
@@ -18,17 +18,16 @@
*/
package org.sleuthkit.autopsy.commonfilesearch;
-import java.util.List;
-import org.apache.commons.lang3.StringUtils;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
import org.openide.nodes.Sheet;
-import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
-import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil;
-import org.sleuthkit.autopsy.core.UserPreferences;
+import org.openide.util.NbBundle;
+import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.autopsy.datamodel.NodeProperty;
import org.sleuthkit.datamodel.AbstractFile;
-import org.sleuthkit.datamodel.ContentTag;
/**
* Node that wraps CaseDBCommonAttributeInstance to represent a file instance
@@ -75,33 +74,25 @@ public class CaseDBCommonAttributeInstanceNode extends FileNode {
@Override
protected Sheet createSheet() {
- Sheet sheet = new Sheet();
+ Sheet sheet = super.createSheet();
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
- if (sheetSet == null) {
- sheetSet = Sheet.createPropertiesSet();
- sheet.put(sheetSet);
+ Set keepProps = new HashSet<>(Arrays.asList(
+ NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.nameColLbl"),
+ NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.score.name"),
+ NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.comment.name"),
+ NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.count.name"),
+ NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.mimeType")));
+
+ for(Property> p : sheetSet.getProperties()) {
+ if(!keepProps.contains(p.getName())){
+ sheetSet.remove(p.getName());
+ }
}
- List tags = getContentTagsFromDatabase();
-
final String NO_DESCR = Bundle.CommonFilesSearchResultsViewerTable_noDescText();
-
- sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), Bundle.CommonFilesSearchResultsViewerTable_filesColLbl(), NO_DESCR, this.getContent().getName()));
- addScoreProperty(sheetSet, tags);
-
- CorrelationAttributeInstance correlationAttribute = null;
- if (EamDbUtil.useCentralRepo() && UserPreferences.hideCentralRepoCommentsAndOccurrences()== false) {
- correlationAttribute = getCorrelationAttributeInstance();
- }
- addCommentProperty(sheetSet, tags, correlationAttribute);
-
- if (EamDbUtil.useCentralRepo() && UserPreferences.hideCentralRepoCommentsAndOccurrences()== false) {
- addCountProperty(sheetSet, correlationAttribute);
- }
- sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_pathColLbl(), Bundle.CommonFilesSearchResultsViewerTable_pathColLbl(), NO_DESCR, this.getContent().getParentPath()));
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_dataSourceColLbl(), Bundle.CommonFilesSearchResultsViewerTable_dataSourceColLbl(), NO_DESCR, this.getDataSource()));
- sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_mimeTypeColLbl(), Bundle.CommonFilesSearchResultsViewerTable_mimeTypeColLbl(), NO_DESCR, StringUtils.defaultString(this.getContent().getMIMEType())));
sheetSet.put(new NodeProperty<>(Bundle.CommonFilesSearchResultsViewerTable_caseColLbl1(), Bundle.CommonFilesSearchResultsViewerTable_caseColLbl1(), NO_DESCR, caseName));
+
return sheet;
}
}
\ No newline at end of file
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java
index d88b5ac2fb..72343ec616 100755
--- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java
@@ -67,19 +67,19 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
initComponents();
Utilities.configureTextPaneAsHtml(jTextPane1);
}
-
+
@Override
public void setNode(Node node) {
if ((node == null) || (!isSupported(node))) {
resetComponent();
return;
}
-
+
StringBuilder html = new StringBuilder();
-
+
BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
Content sourceFile = null;
-
+
try {
if (artifact != null) {
/*
@@ -100,32 +100,32 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
"Exception while trying to retrieve a Content instance from the BlackboardArtifact '%s' (id=%d).",
artifact.getDisplayName(), artifact.getArtifactID()), ex);
}
-
+
if (artifact != null) {
populateTagData(html, artifact, sourceFile);
} else {
populateTagData(html, sourceFile);
}
-
+
if (sourceFile instanceof AbstractFile) {
populateCentralRepositoryData(html, artifact, (AbstractFile) sourceFile);
}
-
+
setText(html.toString());
jTextPane1.setCaretPosition(0);
}
-
+
/**
* Populate the "Selected Item" sections with tag data for the supplied
* content.
- *
+ *
* @param html The HTML text to update.
* @param content Selected content.
*/
private void populateTagData(StringBuilder html, Content content) {
try {
SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
-
+
startSection(html, "Selected Item");
List fileTagsList = tskCase.getContentTagsByContent(content);
if (fileTagsList.isEmpty()) {
@@ -142,11 +142,11 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS
}
}
-
+
/**
* Populate the "Selected Item" and "Source File" sections with tag data for
* a supplied artifact.
- *
+ *
* @param html The HTML text to update.
* @param artifact A selected artifact.
* @param sourceFile The source content of the selected artifact.
@@ -154,7 +154,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
private void populateTagData(StringBuilder html, BlackboardArtifact artifact, Content sourceFile) {
try {
SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
-
+
startSection(html, "Selected Item");
List artifactTagsList = tskCase.getBlackboardArtifactTagsByArtifact(artifact);
if (artifactTagsList.isEmpty()) {
@@ -165,7 +165,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
}
}
endSection(html);
-
+
if (sourceFile != null) {
startSection(html, "Source File");
List fileTagsList = tskCase.getContentTagsByContent(sourceFile);
@@ -184,10 +184,10 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS
}
}
-
+
/**
* Populate the "Central Repository Comments" section with data.
- *
+ *
* @param html The HTML text to update.
* @param artifact A selected artifact (can be null).
* @param sourceFile A selected file, or a source file of the selected
@@ -208,23 +208,24 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
if (attributeType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
CorrelationCase correlationCase = EamDb.getInstance().getCase(Case.getCurrentCase());
instancesList.add(new CorrelationAttributeInstance(
- md5,
attributeType,
+ md5,
correlationCase,
CorrelationDataSource.fromTSKDataSource(correlationCase, sourceFile.getDataSource()),
sourceFile.getParentPath() + sourceFile.getName(),
"",
- sourceFile.getKnown()));
+ sourceFile.getKnown(),
+ sourceFile.getId()));
break;
}
}
}
boolean commentDataFound = false;
-
+
for (CorrelationAttributeInstance instance : instancesList) {
- List correlatedInstancesList =
- EamDb.getInstance().getArtifactInstancesByTypeValue(instance.getCorrelationType(), instance.getCorrelationValue());
+ List correlatedInstancesList
+ = EamDb.getInstance().getArtifactInstancesByTypeValue(instance.getCorrelationType(), instance.getCorrelationValue());
for (CorrelationAttributeInstance correlatedInstance : correlatedInstancesList) {
if (correlatedInstance.getComment() != null && correlatedInstance.getComment().isEmpty() == false) {
commentDataFound = true;
@@ -232,7 +233,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
}
}
}
-
+
if (commentDataFound == false) {
addMessage(html, "There is no comment data for the selected content in the Central Repository.");
}
@@ -247,16 +248,16 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
/**
* Set the text of the text panel.
- *
+ *
* @param text The text to set to the text panel.
*/
private void setText(String text) {
jTextPane1.setText("" + text + ""); //NON-NLS
}
-
+
/**
* Start a new data section.
- *
+ *
* @param html The HTML text to add the section to.
* @param sectionName The name of the section.
*/
@@ -265,10 +266,10 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
.append(sectionName)
.append("
"); //NON-NLS
}
-
+
/**
* Add a message.
- *
+ *
* @param html The HTML text to add the message to.
* @param message The message text.
*/
@@ -277,10 +278,10 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
.append(message)
.append(" "); //NON-NLS
}
-
+
/**
* Add a data table containing information about a tag.
- *
+ *
* @param html The HTML text to add the table to.
* @param tag The tag whose information will be used to populate the table.
*/
@@ -296,11 +297,11 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
addRow(html, Bundle.AnnotationsContentViewer_tagEntryDataLabel_comment(), formatHtmlString(tag.getComment()));
endTable(html);
}
-
+
/**
* Add a data table containing information about a correlation attribute
* instance in the Central Repository.
- *
+ *
* @param html The HTML text to add the table to.
* @param attributeInstance The attribute instance whose information will be
* used to populate the table.
@@ -319,10 +320,10 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_path(), attributeInstance.getFilePath());
endTable(html);
}
-
+
/**
* Start a data table.
- *
+ *
* @param html The HTML text to add the table to.
*/
private void startTable(StringBuilder html) {
@@ -331,7 +332,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
/**
* Add a data row to a table.
- *
+ *
* @param html The HTML text to add the row to.
* @param key The key for the left column of the data row.
* @param value The value for the right column of the data row.
@@ -343,10 +344,10 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
html.append(value);
html.append(""); //NON-NLS
}
-
+
/**
* End a data table.
- *
+ *
* @param html The HTML text on which to end a table.
*/
private void endTable(StringBuilder html) {
@@ -355,18 +356,19 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
/**
* End a data section.
- *
+ *
* @param html The HTML text on which to end a section.
*/
private void endSection(StringBuilder html) {
html.append(" "); //NON-NLS
}
-
+
/**
* Apply escape sequence to special characters. Line feed and carriage
* return character combinations will be converted to HTML line breaks.
- *
+ *
* @param text The text to format.
+ *
* @return The formatted text.
*/
private String formatHtmlString(String text) {
@@ -428,7 +430,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
@Override
public boolean isSupported(Node node) {
BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
-
+
try {
if (artifact != null) {
if (artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID()) != null) {
@@ -444,7 +446,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
"Exception while trying to retrieve a Content instance from the BlackboardArtifact '%s' (id=%d).",
artifact.getDisplayName(), artifact.getArtifactID()), ex);
}
-
+
return false;
}
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java
index e1565c3b89..bf319bde0c 100644
--- a/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/MessageContentViewer.java
@@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.contentviewers;
import java.awt.Component;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@@ -43,6 +44,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.autopsy.corecomponents.DataResultPanel;
import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.autopsy.datamodel.NodeProperty;
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
@@ -721,31 +723,23 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
@Override
protected Sheet createSheet() {
- Sheet sheet = new Sheet();
+ Sheet sheet = super.createSheet();
+ Set keepProps = new HashSet<>(Arrays.asList(
+ NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.nameColLbl"),
+ NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.score.name"),
+ NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.comment.name"),
+ NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.createSheet.count.name"),
+ NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.sizeColLbl"),
+ NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.mimeType"),
+ NbBundle.getMessage(AbstractAbstractFileNode.class, "AbstractAbstractFileNode.knownColLbl")));
+
+ //Remove all other props except for the ones above
Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
- if (sheetSet == null) {
- sheetSet = Sheet.createPropertiesSet();
- sheet.put(sheetSet);
+ for(Property> p : sheetSet.getProperties()) {
+ if(!keepProps.contains(p.getName())){
+ sheetSet.remove(p.getName());
+ }
}
- List tags = getContentTagsFromDatabase();
-
- AbstractFile file = getContent();
- sheetSet.put(new NodeProperty<>("Name", "Name", "Name", file.getName()));
-
- addScoreProperty(sheetSet, tags);
-
- CorrelationAttributeInstance correlationAttribute = null;
- if (EamDbUtil.useCentralRepo() && UserPreferences.hideCentralRepoCommentsAndOccurrences()== false) {
- correlationAttribute = getCorrelationAttributeInstance();
- }
- addCommentProperty(sheetSet, tags, correlationAttribute);
-
- if (EamDbUtil.useCentralRepo() && UserPreferences.hideCentralRepoCommentsAndOccurrences()== false) {
- addCountProperty(sheetSet, correlationAttribute);
- }
- sheetSet.put(new NodeProperty<>("Size", "Size", "Size", file.getSize()));
- sheetSet.put(new NodeProperty<>("Mime Type", "Mime Type", "Mime Type", StringUtils.defaultString(file.getMIMEType())));
- sheetSet.put(new NodeProperty<>("Known", "Known", "Known", file.getKnown().getName()));
return sheet;
}
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/PListViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/PListViewer.java
index 506084f0c3..dd73b6f6ca 100644
--- a/Core/src/org/sleuthkit/autopsy/contentviewers/PListViewer.java
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/PListViewer.java
@@ -74,7 +74,7 @@ class PListViewer extends javax.swing.JPanel implements FileTypeViewer, Explorer
private final Outline outline;
private ExplorerManager explorerManager;
- private NSDictionary rootDict;
+ private NSObject rootDict;
/**
* Creates new form PListViewer
@@ -415,22 +415,35 @@ class PListViewer extends javax.swing.JPanel implements FileTypeViewer, Explorer
}
/**
- * Parses given binary stream and extracts Plist key/value
+ * Parses given binary stream and extracts Plist key/value.
*
- * @param plistbytes
+ * @param plistbytes The byte array containing the Plist data.
*
* @return list of PropKeyValue
*/
private List parsePList(final byte[] plistbytes) throws IOException, PropertyListFormatException, ParseException, ParserConfigurationException, SAXException {
final List plist = new ArrayList<>();
- rootDict = (NSDictionary) PropertyListParser.parse(plistbytes);
+ rootDict = PropertyListParser.parse(plistbytes);
- final String[] keys = rootDict.allKeys();
- for (final String key : keys) {
- final PropKeyValue pkv = parseProperty(key, rootDict.objectForKey(key));
- if (null != pkv) {
- plist.add(pkv);
+ /*
+ * Parse the data if the root is an NSArray or NSDictionary. Anything
+ * else is unexpected and will be ignored.
+ */
+ if (rootDict instanceof NSArray) {
+ for (int i=0; i < ((NSArray)rootDict).count(); i++) {
+ final PropKeyValue pkv = parseProperty("", ((NSArray)rootDict).objectAtIndex(i));
+ if (null != pkv) {
+ plist.add(pkv);
+ }
+ }
+ } else if (rootDict instanceof NSDictionary) {
+ final String[] keys = ((NSDictionary)rootDict).allKeys();
+ for (final String key : keys) {
+ final PropKeyValue pkv = parseProperty(key, ((NSDictionary)rootDict).objectForKey(key));
+ if (null != pkv) {
+ plist.add(pkv);
+ }
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java
index f2be8c90c4..f2db7c2532 100755
--- a/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java
+++ b/Core/src/org/sleuthkit/autopsy/contentviewers/SQLiteViewer.java
@@ -24,21 +24,15 @@ import java.awt.Cursor;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.function.Consumer;
import java.util.logging.Level;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
@@ -48,11 +42,11 @@ import org.apache.commons.io.FilenameUtils;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case;
-import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
+import org.sleuthkit.autopsy.coreutils.SQLiteTableReaderException;
import org.sleuthkit.autopsy.coreutils.Logger;
-import org.sleuthkit.datamodel.AbstractFile;
-import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
+import org.sleuthkit.datamodel.AbstractFile;
+import org.sleuthkit.autopsy.coreutils.SQLiteTableReader;
/**
* A file content viewer for SQLite database files.
@@ -66,8 +60,14 @@ class SQLiteViewer extends javax.swing.JPanel implements FileTypeViewer {
private static final Logger logger = Logger.getLogger(FileViewer.class.getName());
private final SQLiteTableView selectedTableView = new SQLiteTableView();
private AbstractFile sqliteDbFile;
- private File tmpDbFile;
- private Connection connection;
+
+ private SQLiteTableReader viewReader;
+
+ private Map row = new LinkedHashMap<>();
+ private List