Merge pull request #5379 from rcordovano/rc-data-src-deletion-integration

5511 Delete data sources from Image Gallery database tables
This commit is contained in:
Richard Cordovano 2019-10-28 17:02:56 -04:00 committed by GitHub
commit 2b55a6837b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 264 additions and 216 deletions

View File

@ -37,7 +37,7 @@ public class DataSourceDeletedEvent extends AutopsyEvent implements Serializable
* @param dataSourceId The object ID of the data source that was deleted. * @param dataSourceId The object ID of the data source that was deleted.
*/ */
public DataSourceDeletedEvent(Long dataSourceId) { public DataSourceDeletedEvent(Long dataSourceId) {
super(Case.Events.DATA_SOURCE_DELETED.toString(), null, dataSourceId); super(Case.Events.DATA_SOURCE_DELETED.toString(), dataSourceId, null);
this.dataSourceID = dataSourceId; this.dataSourceID = dataSourceId;
} }

View File

@ -23,6 +23,7 @@ import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.sql.SQLException;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -55,6 +56,7 @@ import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import org.sleuthkit.autopsy.casemodule.events.DataSourceDeletedEvent;
import org.sleuthkit.autopsy.coreutils.History; import org.sleuthkit.autopsy.coreutils.History;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined;
@ -102,7 +104,8 @@ public final class ImageGalleryController {
Case.Events.CURRENT_CASE, Case.Events.CURRENT_CASE,
Case.Events.DATA_SOURCE_ADDED, Case.Events.DATA_SOURCE_ADDED,
Case.Events.CONTENT_TAG_ADDED, Case.Events.CONTENT_TAG_ADDED,
Case.Events.CONTENT_TAG_DELETED Case.Events.CONTENT_TAG_DELETED,
Case.Events.DATA_SOURCE_DELETED
); );
/* /*
@ -802,6 +805,17 @@ public final class ImageGalleryController {
} }
} }
break; break;
case DATA_SOURCE_DELETED:
if (((AutopsyEvent) event).getSourceType() == AutopsyEvent.SourceType.LOCAL) {
final DataSourceDeletedEvent dataSourceDeletedEvent = (DataSourceDeletedEvent) event;
long dataSourceObjId = dataSourceDeletedEvent.getDataSourceId();
try {
drawableDB.deleteDataSource(dataSourceObjId);
} catch (SQLException | TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Failed to delete data source (obj_id = %d)", dataSourceObjId), ex); //NON-NLS
}
}
break;
case CONTENT_TAG_ADDED: case CONTENT_TAG_ADDED:
final ContentTagAddedEvent tagAddedEvent = (ContentTagAddedEvent) event; final ContentTagAddedEvent tagAddedEvent = (ContentTagAddedEvent) event;
long objId = tagAddedEvent.getAddedTag().getContent().getId(); long objId = tagAddedEvent.getAddedTag().getContent().getId();

View File

@ -106,8 +106,8 @@ public final class DrawableDB {
private static final String IG_CREATION_SCHEMA_MAJOR_VERSION_KEY = "IG_CREATION_SCHEMA_MAJOR_VERSION"; private static final String IG_CREATION_SCHEMA_MAJOR_VERSION_KEY = "IG_CREATION_SCHEMA_MAJOR_VERSION";
private static final String IG_CREATION_SCHEMA_MINOR_VERSION_KEY = "IG_CREATION_SCHEMA_MINOR_VERSION"; private static final String IG_CREATION_SCHEMA_MINOR_VERSION_KEY = "IG_CREATION_SCHEMA_MINOR_VERSION";
private static final VersionNumber IG_STARTING_SCHEMA_VERSION = new VersionNumber(1, 0, 0); // IG Schema Starting version private static final VersionNumber IG_STARTING_SCHEMA_VERSION = new VersionNumber(1, 0, 0); // IG Schema Starting version - DO NOT CHANGE
private static final VersionNumber IG_SCHEMA_VERSION = new VersionNumber(1, 1, 0); // IG Schema Current version private static final VersionNumber IG_SCHEMA_VERSION = new VersionNumber(1, 2, 0); // IG Schema Current version
private PreparedStatement insertHashSetStmt; private PreparedStatement insertHashSetStmt;
@ -146,6 +146,8 @@ public final class DrawableDB {
private PreparedStatement pathGroupFilterByDataSrcStmt; private PreparedStatement pathGroupFilterByDataSrcStmt;
private PreparedStatement deleteDataSourceStmt;
/** /**
* map from {@link DrawableAttribute} to the {@link PreparedStatement} that * map from {@link DrawableAttribute} to the {@link PreparedStatement} that
* is used to select groups for that attribute * is used to select groups for that attribute
@ -263,6 +265,7 @@ public final class DrawableDB {
selectHashSetStmt = prepareStatement("SELECT hash_set_id FROM hash_sets WHERE hash_set_name = ?"); //NON-NLS selectHashSetStmt = prepareStatement("SELECT hash_set_id FROM hash_sets WHERE hash_set_name = ?"); //NON-NLS
insertHashHitStmt = prepareStatement("INSERT OR IGNORE INTO hash_set_hits (hash_set_id, obj_id) VALUES (?,?)"); //NON-NLS insertHashHitStmt = prepareStatement("INSERT OR IGNORE INTO hash_set_hits (hash_set_id, obj_id) VALUES (?,?)"); //NON-NLS
removeHashHitStmt = prepareStatement("DELETE FROM hash_set_hits WHERE obj_id = ?"); //NON-NLS removeHashHitStmt = prepareStatement("DELETE FROM hash_set_hits WHERE obj_id = ?"); //NON-NLS
deleteDataSourceStmt = prepareStatement("DELETE FROM datasources where ds_obj_id = ?"); //NON-NLS
return true; return true;
} catch (TskCoreException | SQLException ex) { } catch (TskCoreException | SQLException ex) {
logger.log(Level.SEVERE, "Failed to prepare all statements", ex); //NON-NLS logger.log(Level.SEVERE, "Failed to prepare all statements", ex); //NON-NLS
@ -406,6 +409,7 @@ public final class DrawableDB {
* Checks if the specified table exists in Drawable DB * Checks if the specified table exists in Drawable DB
* *
* @param tableName table to check * @param tableName table to check
*
* @return true if the table exists in the database * @return true if the table exists in the database
* *
* @throws SQLException * @throws SQLException
@ -421,8 +425,7 @@ public final class DrawableDB {
break; break;
} }
} }
} } finally {
finally {
if (tableQueryResults != null) { if (tableQueryResults != null) {
tableQueryResults.close(); tableQueryResults.close();
} }
@ -475,7 +478,7 @@ public final class DrawableDB {
//allow to query while in transaction - no need read locks //allow to query while in transaction - no need read locks
statement.execute("PRAGMA read_uncommitted = True;"); //NON-NLS statement.execute("PRAGMA read_uncommitted = True;"); //NON-NLS
//TODO: do we need this? //used for data source deletion
statement.execute("PRAGMA foreign_keys = ON"); //NON-NLS statement.execute("PRAGMA foreign_keys = ON"); //NON-NLS
//TODO: test this //TODO: test this
@ -537,19 +540,19 @@ public final class DrawableDB {
drawableDbTablesExist = doesTableExist("drawable_files"); drawableDbTablesExist = doesTableExist("drawable_files");
if (false == doesTableExist(IG_DB_INFO_TABLE)) { if (false == doesTableExist(IG_DB_INFO_TABLE)) {
try { try {
VersionNumber ig_creation_schema_version = drawableDbTablesExist VersionNumber ig_creation_schema_version = drawableDbTablesExist
? IG_STARTING_SCHEMA_VERSION ? IG_STARTING_SCHEMA_VERSION
: IG_SCHEMA_VERSION; : IG_SCHEMA_VERSION;
stmt.execute("CREATE TABLE IF NOT EXISTS " + IG_DB_INFO_TABLE + " (name TEXT PRIMARY KEY, value TEXT NOT NULL)"); stmt.execute("CREATE TABLE IF NOT EXISTS " + IG_DB_INFO_TABLE + " (name TEXT PRIMARY KEY, value TEXT NOT NULL)");
// backfill creation schema ver // backfill creation schema ver
stmt.execute(String.format("INSERT INTO %s (name, value) VALUES ('%s', '%s')", IG_DB_INFO_TABLE, IG_CREATION_SCHEMA_MAJOR_VERSION_KEY, ig_creation_schema_version.getMajor() )); stmt.execute(String.format("INSERT INTO %s (name, value) VALUES ('%s', '%s')", IG_DB_INFO_TABLE, IG_CREATION_SCHEMA_MAJOR_VERSION_KEY, ig_creation_schema_version.getMajor()));
stmt.execute(String.format("INSERT INTO %s (name, value) VALUES ('%s', '%s')", IG_DB_INFO_TABLE, IG_CREATION_SCHEMA_MINOR_VERSION_KEY, ig_creation_schema_version.getMinor() )); stmt.execute(String.format("INSERT INTO %s (name, value) VALUES ('%s', '%s')", IG_DB_INFO_TABLE, IG_CREATION_SCHEMA_MINOR_VERSION_KEY, ig_creation_schema_version.getMinor()));
// set current schema ver: at DB initialization - current version is same as starting version // set current schema ver: at DB initialization - current version is same as starting version
stmt.execute(String.format("INSERT INTO %s (name, value) VALUES ('%s', '%s')", IG_DB_INFO_TABLE, IG_SCHEMA_MAJOR_VERSION_KEY, ig_creation_schema_version.getMajor() )); stmt.execute(String.format("INSERT INTO %s (name, value) VALUES ('%s', '%s')", IG_DB_INFO_TABLE, IG_SCHEMA_MAJOR_VERSION_KEY, ig_creation_schema_version.getMajor()));
stmt.execute(String.format("INSERT INTO %s (name, value) VALUES ('%s', '%s')", IG_DB_INFO_TABLE, IG_SCHEMA_MINOR_VERSION_KEY, ig_creation_schema_version.getMinor() )); stmt.execute(String.format("INSERT INTO %s (name, value) VALUES ('%s', '%s')", IG_DB_INFO_TABLE, IG_SCHEMA_MINOR_VERSION_KEY, ig_creation_schema_version.getMinor()));
} catch (SQLException ex) { } catch (SQLException ex) {
logger.log(Level.SEVERE, "Failed to create ig_db_info table", ex); //NON-NLS logger.log(Level.SEVERE, "Failed to create ig_db_info table", ex); //NON-NLS
@ -578,7 +581,8 @@ public final class DrawableDB {
+ " modified_time integer, " //NON-NLS + " modified_time integer, " //NON-NLS
+ " make TEXT DEFAULT NULL, " //NON-NLS + " make TEXT DEFAULT NULL, " //NON-NLS
+ " model TEXT DEFAULT NULL, " //NON-NLS + " model TEXT DEFAULT NULL, " //NON-NLS
+ " analyzed integer DEFAULT 0)"; //NON-NLS + " analyzed integer DEFAULT 0, " //NON-NLS
+ " FOREIGN KEY (data_source_obj_id) REFERENCES datasources(ds_obj_id) ON DELETE CASCADE)"; //NON-NLS
stmt.execute(sql); stmt.execute(sql);
} catch (SQLException ex) { } catch (SQLException ex) {
logger.log(Level.SEVERE, "Failed to create drawable_files table", ex); //NON-NLS logger.log(Level.SEVERE, "Failed to create drawable_files table", ex); //NON-NLS
@ -598,8 +602,9 @@ public final class DrawableDB {
try { try {
String sql = "CREATE TABLE if not exists hash_set_hits " //NON-NLS String sql = "CREATE TABLE if not exists hash_set_hits " //NON-NLS
+ "(hash_set_id INTEGER REFERENCES hash_sets(hash_set_id) not null, " //NON-NLS + "(hash_set_id INTEGER REFERENCES hash_sets(hash_set_id) not null, " //NON-NLS
+ " obj_id BIGINT REFERENCES drawable_files(obj_id) not null, " //NON-NLS + " obj_id BIGINT NOT NULL, " //NON-NLS
+ " PRIMARY KEY (hash_set_id, obj_id))"; //NON-NLS + " PRIMARY KEY (hash_set_id, obj_id), " //NON-NLS
+ " FOREIGN KEY (obj_id) REFERENCES drawable_files(obj_id) ON DELETE CASCADE)"; //NON-NLS
stmt.execute(sql); stmt.execute(sql);
} catch (SQLException ex) { } catch (SQLException ex) {
logger.log(Level.SEVERE, "Failed to create hash_set_hits table", ex); //NON-NLS logger.log(Level.SEVERE, "Failed to create hash_set_hits table", ex); //NON-NLS
@ -651,43 +656,43 @@ public final class DrawableDB {
String autogenKeyType = (DbType.POSTGRESQL == tskCase.getDatabaseType()) ? "BIGSERIAL" : "INTEGER"; String autogenKeyType = (DbType.POSTGRESQL == tskCase.getDatabaseType()) ? "BIGSERIAL" : "INTEGER";
try { try {
boolean caseDbTablesExist = tskCase.getCaseDbAccessManager().tableExists(GROUPS_TABLENAME); boolean caseDbTablesExist = tskCase.getCaseDbAccessManager().tableExists(GROUPS_TABLENAME);
VersionNumber ig_creation_schema_version = caseDbTablesExist VersionNumber ig_creation_schema_version = caseDbTablesExist
? IG_STARTING_SCHEMA_VERSION ? IG_STARTING_SCHEMA_VERSION
: IG_SCHEMA_VERSION; : IG_SCHEMA_VERSION;
String tableSchema = "( id " + autogenKeyType + " PRIMARY KEY, " String tableSchema = "( id " + autogenKeyType + " PRIMARY KEY, "
+ " name TEXT UNIQUE NOT NULL," + " name TEXT UNIQUE NOT NULL,"
+ " value TEXT NOT NULL )"; + " value TEXT NOT NULL )";
tskCase.getCaseDbAccessManager().createTable(IG_DB_INFO_TABLE, tableSchema); tskCase.getCaseDbAccessManager().createTable(IG_DB_INFO_TABLE, tableSchema);
// backfill creation version // backfill creation version
String creationMajorVerSQL = String.format(" (name, value) VALUES ('%s', '%s')", IG_CREATION_SCHEMA_MAJOR_VERSION_KEY, ig_creation_schema_version.getMajor()); String creationMajorVerSQL = String.format(" (name, value) VALUES ('%s', '%s')", IG_CREATION_SCHEMA_MAJOR_VERSION_KEY, ig_creation_schema_version.getMajor());
String creationMinorVerSQL = String.format(" (name, value) VALUES ('%s', '%s')", IG_CREATION_SCHEMA_MINOR_VERSION_KEY, ig_creation_schema_version.getMinor()); String creationMinorVerSQL = String.format(" (name, value) VALUES ('%s', '%s')", IG_CREATION_SCHEMA_MINOR_VERSION_KEY, ig_creation_schema_version.getMinor());
// set current version - at the onset, current version is same as creation version // set current version - at the onset, current version is same as creation version
String currentMajorVerSQL = String.format(" (name, value) VALUES ('%s', '%s')", IG_SCHEMA_MAJOR_VERSION_KEY, ig_creation_schema_version.getMajor()); String currentMajorVerSQL = String.format(" (name, value) VALUES ('%s', '%s')", IG_SCHEMA_MAJOR_VERSION_KEY, ig_creation_schema_version.getMajor());
String currentMinorVerSQL = String.format(" (name, value) VALUES ('%s', '%s')", IG_SCHEMA_MINOR_VERSION_KEY, ig_creation_schema_version.getMinor()); String currentMinorVerSQL = String.format(" (name, value) VALUES ('%s', '%s')", IG_SCHEMA_MINOR_VERSION_KEY, ig_creation_schema_version.getMinor());
if (DbType.POSTGRESQL == tskCase.getDatabaseType()) { if (DbType.POSTGRESQL == tskCase.getDatabaseType()) {
creationMajorVerSQL += " ON CONFLICT DO NOTHING "; creationMajorVerSQL += " ON CONFLICT DO NOTHING ";
creationMinorVerSQL += " ON CONFLICT DO NOTHING "; creationMinorVerSQL += " ON CONFLICT DO NOTHING ";
currentMajorVerSQL += " ON CONFLICT DO NOTHING "; currentMajorVerSQL += " ON CONFLICT DO NOTHING ";
currentMinorVerSQL += " ON CONFLICT DO NOTHING "; currentMinorVerSQL += " ON CONFLICT DO NOTHING ";
}
tskCase.getCaseDbAccessManager().insert(IG_DB_INFO_TABLE, creationMajorVerSQL);
tskCase.getCaseDbAccessManager().insert(IG_DB_INFO_TABLE, creationMinorVerSQL);
tskCase.getCaseDbAccessManager().insert(IG_DB_INFO_TABLE, currentMajorVerSQL);
tskCase.getCaseDbAccessManager().insert(IG_DB_INFO_TABLE, currentMinorVerSQL);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to create ig_db_info table in Case database", ex); //NON-NLS
return false;
} }
tskCase.getCaseDbAccessManager().insert(IG_DB_INFO_TABLE, creationMajorVerSQL);
tskCase.getCaseDbAccessManager().insert(IG_DB_INFO_TABLE, creationMinorVerSQL);
tskCase.getCaseDbAccessManager().insert(IG_DB_INFO_TABLE, currentMajorVerSQL);
tskCase.getCaseDbAccessManager().insert(IG_DB_INFO_TABLE, currentMinorVerSQL);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to create ig_db_info table in Case database", ex); //NON-NLS
return false;
}
try { try {
String tableSchema String tableSchema
= "( group_id " + autogenKeyType + " PRIMARY KEY, " //NON-NLS = "( group_id " + autogenKeyType + " PRIMARY KEY, " //NON-NLS
@ -710,7 +715,7 @@ public final class DrawableDB {
+ " examiner_id integer not null, " //NON-NLS + " examiner_id integer not null, " //NON-NLS
+ " seen integer DEFAULT 0, " //NON-NLS + " seen integer DEFAULT 0, " //NON-NLS
+ " UNIQUE(group_id, examiner_id)," + " UNIQUE(group_id, examiner_id),"
+ " FOREIGN KEY(group_id) REFERENCES " + GROUPS_TABLENAME + "(group_id)," + " FOREIGN KEY(group_id) REFERENCES " + GROUPS_TABLENAME + "(group_id) ON DELETE CASCADE,"
+ " FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id)" + " FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id)"
+ " )"; //NON-NLS + " )"; //NON-NLS
@ -731,6 +736,7 @@ public final class DrawableDB {
* Gets the Schema version from DrawableDB * Gets the Schema version from DrawableDB
* *
* @return image gallery schema version in DrawableDB * @return image gallery schema version in DrawableDB
*
* @throws SQLException * @throws SQLException
* @throws TskCoreException * @throws TskCoreException
*/ */
@ -742,7 +748,7 @@ public final class DrawableDB {
try { try {
int majorVersion = -1; int majorVersion = -1;
String majorVersionStr = null; String majorVersionStr = null;
resultSet = statement.executeQuery(String.format("SELECT value FROM %s WHERE name='%s'", IG_DB_INFO_TABLE, IG_SCHEMA_MAJOR_VERSION_KEY)); resultSet = statement.executeQuery(String.format("SELECT value FROM %s WHERE name='%s'", IG_DB_INFO_TABLE, IG_SCHEMA_MAJOR_VERSION_KEY));
if (resultSet.next()) { if (resultSet.next()) {
majorVersionStr = resultSet.getString("value"); majorVersionStr = resultSet.getString("value");
try { try {
@ -751,12 +757,12 @@ public final class DrawableDB {
throw new TskCoreException("Bad value for schema major version = " + majorVersionStr, ex); throw new TskCoreException("Bad value for schema major version = " + majorVersionStr, ex);
} }
} else { } else {
throw new TskCoreException("Failed to read schema major version from ig_db_info table"); throw new TskCoreException("Failed to read schema major version from ig_db_info table");
} }
int minorVersion = -1; int minorVersion = -1;
String minorVersionStr = null; String minorVersionStr = null;
resultSet = statement.executeQuery(String.format("SELECT value FROM %s WHERE name='%s'", IG_DB_INFO_TABLE, IG_SCHEMA_MINOR_VERSION_KEY)); resultSet = statement.executeQuery(String.format("SELECT value FROM %s WHERE name='%s'", IG_DB_INFO_TABLE, IG_SCHEMA_MINOR_VERSION_KEY));
if (resultSet.next()) { if (resultSet.next()) {
minorVersionStr = resultSet.getString("value"); minorVersionStr = resultSet.getString("value");
try { try {
@ -768,9 +774,8 @@ public final class DrawableDB {
throw new TskCoreException("Failed to read schema minor version from ig_db_info table"); throw new TskCoreException("Failed to read schema minor version from ig_db_info table");
} }
return new VersionNumber(majorVersion, minorVersion, 0 ); return new VersionNumber(majorVersion, minorVersion, 0);
} } finally {
finally {
if (resultSet != null) { if (resultSet != null) {
resultSet.close(); resultSet.close();
} }
@ -784,6 +789,7 @@ public final class DrawableDB {
* Gets the ImageGallery schema version from CaseDB * Gets the ImageGallery schema version from CaseDB
* *
* @return image gallery schema version in CaseDB * @return image gallery schema version in CaseDB
*
* @throws SQLException * @throws SQLException
* @throws TskCoreException * @throws TskCoreException
*/ */
@ -802,7 +808,7 @@ public final class DrawableDB {
public void process(ResultSet resultSet) { public void process(ResultSet resultSet) {
try { try {
if (resultSet.next()) { if (resultSet.next()) {
String versionStr = resultSet.getString("value"); String versionStr = resultSet.getString("value");
try { try {
version = Integer.parseInt(versionStr); version = Integer.parseInt(versionStr);
} catch (NumberFormatException ex) { } catch (NumberFormatException ex) {
@ -811,8 +817,7 @@ public final class DrawableDB {
} else { } else {
logger.log(Level.SEVERE, "Failed to get version"); logger.log(Level.SEVERE, "Failed to get version");
} }
} } catch (SQLException ex) {
catch (SQLException ex) {
logger.log(Level.SEVERE, "Failed to get version", ex); //NON-NLS logger.log(Level.SEVERE, "Failed to get version", ex); //NON-NLS
} }
} }
@ -831,7 +836,7 @@ public final class DrawableDB {
/** /**
* Updates the IG schema version in the Drawable DB * Updates the IG schema version in the Drawable DB
* *
* @param version new version number * @param version new version number
* @param transaction transaction under which the update happens * @param transaction transaction under which the update happens
* *
* @throws SQLException * @throws SQLException
@ -839,7 +844,7 @@ public final class DrawableDB {
private void updateDrawableDbIgSchemaVersion(VersionNumber version, DrawableTransaction transaction) throws SQLException, TskCoreException { private void updateDrawableDbIgSchemaVersion(VersionNumber version, DrawableTransaction transaction) throws SQLException, TskCoreException {
if (transaction == null) { if (transaction == null) {
throw new TskCoreException("Schema version update must be done in a transaction"); throw new TskCoreException("Schema version update must be done in a transaction");
} }
dbWriteLock(); dbWriteLock();
@ -847,12 +852,11 @@ public final class DrawableDB {
Statement statement = con.createStatement(); Statement statement = con.createStatement();
// update schema version // update schema version
statement.execute(String.format("UPDATE %s SET value = '%s' WHERE name = '%s'", IG_DB_INFO_TABLE, version.getMajor(), IG_SCHEMA_MAJOR_VERSION_KEY )); statement.execute(String.format("UPDATE %s SET value = '%s' WHERE name = '%s'", IG_DB_INFO_TABLE, version.getMajor(), IG_SCHEMA_MAJOR_VERSION_KEY));
statement.execute(String.format("UPDATE %s SET value = '%s' WHERE name = '%s'", IG_DB_INFO_TABLE, version.getMinor(), IG_SCHEMA_MINOR_VERSION_KEY )); statement.execute(String.format("UPDATE %s SET value = '%s' WHERE name = '%s'", IG_DB_INFO_TABLE, version.getMinor(), IG_SCHEMA_MINOR_VERSION_KEY));
statement.close(); statement.close();
} } finally {
finally {
dbWriteUnlock(); dbWriteUnlock();
} }
} }
@ -860,7 +864,7 @@ public final class DrawableDB {
/** /**
* Updates the IG schema version in CaseDB * Updates the IG schema version in CaseDB
* *
* @param version new version number * @param version new version number
* @param caseDbTransaction transaction to use to update the CaseDB * @param caseDbTransaction transaction to use to update the CaseDB
* *
* @throws SQLException * @throws SQLException
@ -872,7 +876,6 @@ public final class DrawableDB {
tskCase.getCaseDbAccessManager().update(IG_DB_INFO_TABLE, String.format(updateSQLTemplate, version.getMinor(), IG_SCHEMA_MINOR_VERSION_KEY), caseDbTransaction); tskCase.getCaseDbAccessManager().update(IG_DB_INFO_TABLE, String.format(updateSQLTemplate, version.getMinor(), IG_SCHEMA_MINOR_VERSION_KEY), caseDbTransaction);
} }
/** /**
* Upgrades the DB schema. * Upgrades the DB schema.
* *
@ -884,7 +887,7 @@ public final class DrawableDB {
private boolean upgradeDBSchema() throws TskCoreException, SQLException { private boolean upgradeDBSchema() throws TskCoreException, SQLException {
// Read current version from the DBs // Read current version from the DBs
VersionNumber drawableDbIgSchemaVersion = getDrawableDbIgSchemaVersion(); VersionNumber drawableDbIgSchemaVersion = getDrawableDbIgSchemaVersion();
VersionNumber caseDbIgSchemaVersion = getCaseDbIgSchemaVersion(); VersionNumber caseDbIgSchemaVersion = getCaseDbIgSchemaVersion();
// Upgrade Schema in both DrawableDB and CaseDB // Upgrade Schema in both DrawableDB and CaseDB
@ -896,15 +899,14 @@ public final class DrawableDB {
drawableDbIgSchemaVersion = upgradeDrawableDbIgSchema1dot0TO1dot1(drawableDbIgSchemaVersion, transaction); drawableDbIgSchemaVersion = upgradeDrawableDbIgSchema1dot0TO1dot1(drawableDbIgSchemaVersion, transaction);
// update the versions in the tables // update the versions in the tables
updateCaseDbIgSchemaVersion(caseDbIgSchemaVersion, caseDbTransaction ); updateCaseDbIgSchemaVersion(caseDbIgSchemaVersion, caseDbTransaction);
updateDrawableDbIgSchemaVersion(drawableDbIgSchemaVersion, transaction); updateDrawableDbIgSchemaVersion(drawableDbIgSchemaVersion, transaction);
caseDbTransaction.commit(); caseDbTransaction.commit();
caseDbTransaction = null; caseDbTransaction = null;
commitTransaction(transaction, false); commitTransaction(transaction, false);
transaction = null; transaction = null;
} } catch (TskCoreException | SQLException ex) {
catch (TskCoreException | SQLException ex) {
if (null != caseDbTransaction) { if (null != caseDbTransaction) {
try { try {
caseDbTransaction.rollback(); caseDbTransaction.rollback();
@ -925,51 +927,53 @@ public final class DrawableDB {
} }
/** /**
* Upgrades IG tables in CaseDB from 1.0 to 1.1 * Upgrades IG tables in CaseDB from 1.0 to 1.1 Does nothing if the incoming
* Does nothing if the incoming version is not 1.0 * version is not 1.0
* *
* @param currVersion version to upgrade from * @param currVersion version to upgrade from
* @param caseDbTransaction transaction to use for all updates * @param caseDbTransaction transaction to use for all updates
* *
* @return new version number * @return new version number
*
* @throws TskCoreException * @throws TskCoreException
*/ */
private VersionNumber upgradeCaseDbIgSchema1dot0TO1dot1(VersionNumber currVersion, CaseDbTransaction caseDbTransaction ) throws TskCoreException { private VersionNumber upgradeCaseDbIgSchema1dot0TO1dot1(VersionNumber currVersion, CaseDbTransaction caseDbTransaction) throws TskCoreException {
// Upgrade if current version is 1.0 // Upgrade if current version is 1.0
// or 1.1 - a bug in versioning alllowed some databases to be versioned as 1.1 without the actual corresponding upgrade. This allows such databases to be fixed, if needed. // or 1.1 - a bug in versioning alllowed some databases to be versioned as 1.1 without the actual corresponding upgrade. This allows such databases to be fixed, if needed.
if (!(currVersion.getMajor() == 1 && if (!(currVersion.getMajor() == 1
(currVersion.getMinor() == 0 || currVersion.getMinor() == 1))) { && (currVersion.getMinor() == 0 || currVersion.getMinor() == 1))) {
return currVersion; return currVersion;
} }
// Add a 'is_analyzed' column to groups table in CaseDB // Add a 'is_analyzed' column to groups table in CaseDB
String alterSQL = " ADD COLUMN is_analyzed integer DEFAULT 1 "; //NON-NLS String alterSQL = " ADD COLUMN is_analyzed integer DEFAULT 1 "; //NON-NLS
if (false == tskCase.getCaseDbAccessManager().columnExists(GROUPS_TABLENAME, "is_analyzed", caseDbTransaction )) { if (false == tskCase.getCaseDbAccessManager().columnExists(GROUPS_TABLENAME, "is_analyzed", caseDbTransaction)) {
tskCase.getCaseDbAccessManager().alterTable(GROUPS_TABLENAME, alterSQL, caseDbTransaction); tskCase.getCaseDbAccessManager().alterTable(GROUPS_TABLENAME, alterSQL, caseDbTransaction);
} }
return new VersionNumber(1,1,0); return new VersionNumber(1, 1, 0);
} }
/** /**
* Upgrades IG tables in DrawableDB from 1.0 to 1.1 * Upgrades IG tables in DrawableDB from 1.0 to 1.1 Does nothing if the
* Does nothing if the incoming version is not 1.0 * incoming version is not 1.0
* *
* @param currVersion version to upgrade from * @param currVersion version to upgrade from
* @param transaction transaction to use for all updates * @param transaction transaction to use for all updates
* *
* @return new version number * @return new version number
*
* @throws TskCoreException * @throws TskCoreException
*/ */
private VersionNumber upgradeDrawableDbIgSchema1dot0TO1dot1(VersionNumber currVersion, DrawableTransaction transaction ) throws TskCoreException { private VersionNumber upgradeDrawableDbIgSchema1dot0TO1dot1(VersionNumber currVersion, DrawableTransaction transaction) throws TskCoreException {
if (currVersion.getMajor() != 1 || if (currVersion.getMajor() != 1
currVersion.getMinor() != 0) { || currVersion.getMinor() != 0) {
return currVersion; return currVersion;
} }
// There are no changes in DrawableDB schema in 1.0 -> 1.1 // There are no changes in DrawableDB schema in 1.0 -> 1.1
return new VersionNumber(1,1,0); return new VersionNumber(1, 1, 0);
} }
@Override @Override
@ -1143,10 +1147,10 @@ public final class DrawableDB {
} }
/** /**
* Record in the DB that the group with the given key is seen * Record in the DB that the group with the given key is seen by given
* by given examiner id. * examiner id.
* *
* @param groupKey key identifying the group. * @param groupKey key identifying the group.
* @param examinerID examiner id. * @param examinerID examiner id.
* *
* @throws TskCoreException * @throws TskCoreException
@ -1154,8 +1158,8 @@ public final class DrawableDB {
public void markGroupSeen(GroupKey<?> groupKey, long examinerID) throws TskCoreException { public void markGroupSeen(GroupKey<?> groupKey, long examinerID) throws TskCoreException {
/* /*
* Check the groupSeenCache to see if the seen status for this group was set recently. * Check the groupSeenCache to see if the seen status for this group was
* If recently set to seen, there's no need to update it * set recently. If recently set to seen, there's no need to update it
*/ */
Boolean cachedValue = groupSeenCache.getIfPresent(groupKey); Boolean cachedValue = groupSeenCache.getIfPresent(groupKey);
if (cachedValue != null && cachedValue == true) { if (cachedValue != null && cachedValue == true) {
@ -1163,7 +1167,7 @@ public final class DrawableDB {
} }
// query to find the group id from attribute/value // query to find the group id from attribute/value
String innerQuery = String.format("( SELECT group_id FROM " + GROUPS_TABLENAME //NON-NLS String innerQuery = String.format("( SELECT group_id FROM " + GROUPS_TABLENAME //NON-NLS
+ " WHERE attribute = \'%s\' AND value = \'%s\' and data_source_obj_id = %d )", //NON-NLS + " WHERE attribute = \'%s\' AND value = \'%s\' and data_source_obj_id = %d )", //NON-NLS
SleuthkitCase.escapeSingleQuotes(groupKey.getAttribute().attrName.toString()), SleuthkitCase.escapeSingleQuotes(groupKey.getAttribute().attrName.toString()),
SleuthkitCase.escapeSingleQuotes(groupKey.getValueDisplayName()), SleuthkitCase.escapeSingleQuotes(groupKey.getValueDisplayName()),
@ -1180,8 +1184,8 @@ public final class DrawableDB {
} }
/** /**
* Record in the DB that given group is unseen. * Record in the DB that given group is unseen. The group is marked unseen
* The group is marked unseen for ALL examiners that have seen the group. * for ALL examiners that have seen the group.
* *
* @param groupKey key identifying the group. * @param groupKey key identifying the group.
* *
@ -1190,15 +1194,15 @@ public final class DrawableDB {
public void markGroupUnseen(GroupKey<?> groupKey) throws TskCoreException { public void markGroupUnseen(GroupKey<?> groupKey) throws TskCoreException {
/* /*
* Check the groupSeenCache to see if the seen status for this group was set recently. * Check the groupSeenCache to see if the seen status for this group was
* If recently set to unseen, there's no need to update it * set recently. If recently set to unseen, there's no need to update it
*/ */
Boolean cachedValue = groupSeenCache.getIfPresent(groupKey); Boolean cachedValue = groupSeenCache.getIfPresent(groupKey);
if (cachedValue != null && cachedValue == false) { if (cachedValue != null && cachedValue == false) {
return; return;
} }
String updateSQL = String.format(" SET seen = 0 WHERE group_id in ( " + getGroupIdQuery(groupKey) + ")" ); //NON-NLS String updateSQL = String.format(" SET seen = 0 WHERE group_id in ( " + getGroupIdQuery(groupKey) + ")"); //NON-NLS
tskCase.getCaseDbAccessManager().update(GROUPS_SEEN_TABLENAME, updateSQL); tskCase.getCaseDbAccessManager().update(GROUPS_SEEN_TABLENAME, updateSQL);
groupSeenCache.put(groupKey, false); groupSeenCache.put(groupKey, false);
@ -1213,7 +1217,6 @@ public final class DrawableDB {
*/ */
public void markGroupAnalyzed(GroupKey<?> groupKey) throws TskCoreException { public void markGroupAnalyzed(GroupKey<?> groupKey) throws TskCoreException {
String updateSQL = String.format(" SET is_analyzed = %d " String updateSQL = String.format(" SET is_analyzed = %d "
+ " WHERE attribute = \'%s\' AND value = \'%s\' and data_source_obj_id = %d ", + " WHERE attribute = \'%s\' AND value = \'%s\' and data_source_obj_id = %d ",
1, 1,
@ -1288,13 +1291,12 @@ public final class DrawableDB {
} }
} }
/** /**
* Update an existing entry (or make a new one) into the DB that includes * Update an existing entry (or make a new one) into the DB that includes
* group information. Called when a file has been analyzed or during a bulk * group information. Called when a file has been analyzed or during a bulk
* rebuild * rebuild
* *
* @param f file to update * @param f file to update
* @param tr * @param tr
* @param caseDbTransaction * @param caseDbTransaction
*/ */
@ -1603,8 +1605,8 @@ public final class DrawableDB {
} }
/** /**
* Get the build status for the given data source. * Get the build status for the given data source. Will return UNKNOWN if
* Will return UNKNOWN if the data source is not yet in the database. * the data source is not yet in the database.
* *
* @param dataSourceId * @param dataSourceId
* *
@ -1687,10 +1689,13 @@ public final class DrawableDB {
} }
/** /**
* Returns whether or not the given group is analyzed and ready to be viewed. * Returns whether or not the given group is analyzed and ready to be
* viewed.
* *
* @param groupKey group key. * @param groupKey group key.
*
* @return true if the group is analyzed. * @return true if the group is analyzed.
*
* @throws SQLException * @throws SQLException
* @throws TskCoreException * @throws TskCoreException
*/ */
@ -1709,7 +1714,7 @@ public final class DrawableDB {
public void process(ResultSet resultSet) { public void process(ResultSet resultSet) {
try { try {
if (resultSet.next()) { if (resultSet.next()) {
isAnalyzed = resultSet.getInt("is_analyzed") == 1 ? true: false; isAnalyzed = resultSet.getInt("is_analyzed") == 1 ? true : false;
} }
} catch (SQLException ex) { } catch (SQLException ex) {
logger.log(Level.SEVERE, "Failed to get group is_analyzed", ex); //NON-NLS logger.log(Level.SEVERE, "Failed to get group is_analyzed", ex); //NON-NLS
@ -1720,14 +1725,14 @@ public final class DrawableDB {
IsGroupAnalyzedQueryResultProcessor queryResultProcessor = new IsGroupAnalyzedQueryResultProcessor(); IsGroupAnalyzedQueryResultProcessor queryResultProcessor = new IsGroupAnalyzedQueryResultProcessor();
try { try {
String groupAnalyzedQueryStmt = String.format("is_analyzed FROM " + GROUPS_TABLENAME String groupAnalyzedQueryStmt = String.format("is_analyzed FROM " + GROUPS_TABLENAME
+ " WHERE attribute = \'%s\' AND value = \'%s\' and data_source_obj_id = %d ", + " WHERE attribute = \'%s\' AND value = \'%s\' and data_source_obj_id = %d ",
SleuthkitCase.escapeSingleQuotes(groupKey.getAttribute().attrName.toString()), SleuthkitCase.escapeSingleQuotes(groupKey.getAttribute().attrName.toString()),
SleuthkitCase.escapeSingleQuotes(groupKey.getValueDisplayName()), SleuthkitCase.escapeSingleQuotes(groupKey.getValueDisplayName()),
groupKey.getAttribute() == DrawableAttribute.PATH ? groupKey.getDataSourceObjId() : 0); groupKey.getAttribute() == DrawableAttribute.PATH ? groupKey.getDataSourceObjId() : 0);
tskCase.getCaseDbAccessManager().select(groupAnalyzedQueryStmt, queryResultProcessor); tskCase.getCaseDbAccessManager().select(groupAnalyzedQueryStmt, queryResultProcessor);
return queryResultProcessor.getIsAnalyzed(); return queryResultProcessor.getIsAnalyzed();
} catch ( TskCoreException ex) { } catch (TskCoreException ex) {
String msg = String.format("Failed to get group is_analyzed for group key %s", groupKey.getValueDisplayName()); //NON-NLS String msg = String.format("Failed to get group is_analyzed for group key %s", groupKey.getValueDisplayName()); //NON-NLS
logger.log(Level.SEVERE, msg, ex); logger.log(Level.SEVERE, msg, ex);
} }
@ -1995,7 +2000,6 @@ public final class DrawableDB {
return countFilesWhere(" 1 "); return countFilesWhere(" 1 ");
} }
/** /**
* delete the row with obj_id = id. * delete the row with obj_id = id.
* *
@ -2027,6 +2031,37 @@ public final class DrawableDB {
} }
} }
/**
* Deletes a cascading delete of a data source, starting from the
* datasources table.
*
* @param dataSourceID The object ID of the data source to delete.
*
* @throws SQLException
* @throws TskCoreException
*/
public void deleteDataSource(long dataSourceID) throws SQLException, TskCoreException {
dbWriteLock();
DrawableTransaction trans = null;
try {
trans = beginTransaction();
deleteDataSourceStmt.setLong(1, dataSourceID);
deleteDataSourceStmt.executeUpdate();
commitTransaction(trans, true);
} catch (SQLException | TskCoreException ex) {
if (null != trans) {
try {
rollbackTransaction(trans);
} catch (SQLException ex2) {
logger.log(Level.SEVERE, String.format("Failed to roll back drawables db transaction after error: %s", ex.getMessage()), ex2); //NON-NLS
}
}
throw ex;
} finally {
dbWriteUnlock();
}
}
public class MultipleTransactionException extends IllegalStateException { public class MultipleTransactionException extends IllegalStateException {
public MultipleTransactionException() { public MultipleTransactionException() {
@ -2203,8 +2238,8 @@ public final class DrawableDB {
// The files are processed ORDERED BY parent path // The files are processed ORDERED BY parent path
// We want to preserve that order here, so that we can detect a // We want to preserve that order here, so that we can detect a
// change in path, and thus mark the path group as analyzed // change in path, and thus mark the path group as analyzed
// Hence we use a LinkedHashSet here. // Hence we use a LinkedHashSet here.
private final Set<Long> updatedFiles = new LinkedHashSet<>(); private final Set<Long> updatedFiles = new LinkedHashSet<>();
private final Set<Long> removedFiles = new LinkedHashSet<>(); private final Set<Long> removedFiles = new LinkedHashSet<>();

View File

@ -348,7 +348,6 @@ SolrSearch.openCore.msg=Opening text index
SolrSearch.openGiantCore.msg=Opening text index. Text index for this case is very large and may take long time to load. SolrSearch.openGiantCore.msg=Opening text index. Text index for this case is very large and may take long time to load.
SolrSearch.openLargeCore.msg=Opening text index. This may take several minutes. SolrSearch.openLargeCore.msg=Opening text index. This may take several minutes.
SolrSearch.readingIndexes.msg=Reading text index metadata file SolrSearch.readingIndexes.msg=Reading text index metadata file
SolrSearchService.deleteDataSource.exceptionMessage.noCurrentSolrCore=DeleteDataSource did not contain a current Solr core so could not delete the Data Source
# {0} - index folder path # {0} - index folder path
SolrSearchService.exceptionMessage.failedToDeleteIndexFiles=Failed to delete text index files at {0} SolrSearchService.exceptionMessage.failedToDeleteIndexFiles=Failed to delete text index files at {0}
SolrSearchService.exceptionMessage.noCurrentSolrCore=IndexMetadata did not contain a current Solr core so could not delete the case SolrSearchService.exceptionMessage.noCurrentSolrCore=IndexMetadata did not contain a current Solr core so could not delete the case

View File

@ -1,5 +1,5 @@
#Updated by build script #Updated by build script
#Fri, 04 Oct 2019 14:30:10 -0400 #Mon, 28 Oct 2019 16:22:16 -0400
LBL_splash_window_title=Starting Autopsy LBL_splash_window_title=Starting Autopsy
SPLASH_HEIGHT=314 SPLASH_HEIGHT=314
SPLASH_WIDTH=538 SPLASH_WIDTH=538

View File

@ -1,4 +1,4 @@
#Updated by build script #Updated by build script
#Fri, 04 Oct 2019 14:30:10 -0400 #Mon, 28 Oct 2019 16:22:16 -0400
CTL_MainWindow_Title=Autopsy 4.13.0 CTL_MainWindow_Title=Autopsy 4.13.0
CTL_MainWindow_Title_No_Project=Autopsy 4.13.0 CTL_MainWindow_Title_No_Project=Autopsy 4.13.0