diff --git a/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java b/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java index eb4372c6417cf407a3037f4af0a6427cbd658d84..d7782fef832654f1879281e63b29581c43c451ab 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java +++ b/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java @@ -266,7 +266,7 @@ private void createTagTables(Statement stmt) throws SQLException { stmt.execute("CREATE TABLE tsk_tag_sets (tag_set_id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, name TEXT UNIQUE)"); stmt.execute("CREATE TABLE tag_names (tag_name_id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, display_name TEXT UNIQUE, " + "description TEXT NOT NULL, color TEXT NOT NULL, knownStatus INTEGER NOT NULL," - + " tag_set_id INTEGER, FOREIGN KEY(tag_set_id) REFERENCES tsk_tag_sets(tag_set_id) ON DELETE SET NULL)"); + + " tag_set_id " + dbQueryHelper.getBigIntType() + ", rank INTEGER, FOREIGN KEY(tag_set_id) REFERENCES tsk_tag_sets(tag_set_id) ON DELETE SET NULL)"); stmt.execute("CREATE TABLE tsk_examiners (examiner_id " + dbQueryHelper.getPrimaryKey() + " PRIMARY KEY, " + "login_name TEXT NOT NULL, display_name TEXT, UNIQUE(login_name))"); diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java index 2c5fee8df6e97f9740bfd0569ca2713b71e65424..c27726a8cf85856e74e962805c4dc5d8d3b713d1 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java @@ -98,7 +98,6 @@ public class SleuthkitCase { */ static final CaseDbSchemaVersionNumber CURRENT_DB_SCHEMA_VERSION = new CaseDbSchemaVersionNumber(8, 5); - private static final long BASE_ARTIFACT_ID = Long.MIN_VALUE; // Artifact ids will start at the lowest negative value private static final Logger logger = Logger.getLogger(SleuthkitCase.class.getName()); @@ -480,11 +479,11 @@ public TimelineManager getTimelineManager() throws TskCoreException { public synchronized CaseDbAccessManager getCaseDbAccessManager() throws TskCoreException { return dbAccessManager; } - + /** * Get the case database TaggingManager object. - * - * @return The per case TaggingManager object. + * + * @return The per case TaggingManager object. */ public synchronized TaggingManager getTaggingManager() { return taggingMgr; @@ -1919,24 +1918,23 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot2toSchema8dot3(CaseDbSchem statement.execute("UPDATE tsk_db_info_extended SET name = 'CREATION_SCHEMA_MAJOR_VERSION' WHERE name = 'CREATED_SCHEMA_MAJOR_VERSION'"); statement.execute("UPDATE tsk_db_info_extended SET name = 'CREATION_SCHEMA_MINOR_VERSION' WHERE name = 'CREATED_SCHEMA_MINOR_VERSION'"); - - return new CaseDbSchemaVersionNumber(8, 3); } finally { closeResultSet(resultSet); releaseSingleUserCaseWriteLock(); } } - + /** * Updates a schema version 8.3 database to a schema version 8.4 database. - * - * This includes a bug fix update for a misnamed column in tsk_event_descriptions in - * the previous update code. - * - * Note that 8.4 also introduced cascading deletes on many of the database tables. We do not need to - * add these in the upgrade code because data sources in cases that were originally created with 8.3 - * or earlier can not be deleted. + * + * This includes a bug fix update for a misnamed column in + * tsk_event_descriptions in the previous update code. + * + * Note that 8.4 also introduced cascading deletes on many of the database + * tables. We do not need to add these in the upgrade code because data + * sources in cases that were originally created with 8.3 or earlier can not + * be deleted. * * @param schemaVersion The current schema version of the database. * @param connection A connection to the case database. @@ -1960,24 +1958,24 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot3toSchema8dot4(CaseDbSchem Statement statement = connection.createStatement(); ResultSet results = null; - acquireSingleUserCaseWriteLock(); + acquireSingleUserCaseWriteLock(); try { // This is a bug fix update for a misnamed column in tsk_event_descriptions in // the previous update code. if (null == getDatabaseType()) { throw new TskCoreException("Unsupported data base type: " + getDatabaseType().toString()); - } - + } + switch (getDatabaseType()) { case POSTGRESQL: // Check if the misnamed column is present results = statement.executeQuery("SELECT column_name FROM information_schema.columns " - + "WHERE table_name='tsk_event_descriptions' and column_name='file_obj_id'"); + + "WHERE table_name='tsk_event_descriptions' and column_name='file_obj_id'"); if (results.next()) { // In PostgreSQL we can rename the column if it exists statement.execute("ALTER TABLE tsk_event_descriptions " - + "RENAME COLUMN file_obj_id TO content_obj_id"); - + + "RENAME COLUMN file_obj_id TO content_obj_id"); + // In 8.2 to 8.3 upgrade, the event_id & time column in tsk_events table was erroneously created as type INTEGER, instead of BIGINT // Fix the schema, preserving any data if exists. statement.execute("CREATE TABLE temp_tsk_events ( " @@ -1986,18 +1984,18 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot3toSchema8dot4(CaseDbSchem + " event_description_id BIGINT NOT NULL REFERENCES tsk_event_descriptions(event_description_id)," + " time BIGINT NOT NULL, " + " UNIQUE (event_type_id, event_description_id, time))" - ); - + ); + // Copy the data statement.execute("INSERT INTO temp_tsk_events(event_id, event_type_id, " + "event_description_id, time) SELECT * FROM tsk_events"); - + // Drop the old table statement.execute("DROP TABLE tsk_events"); - + // Rename the new table statement.execute("ALTER TABLE temp_tsk_events RENAME TO tsk_events"); - + //create tsk_events indices that were skipped in the 8.2 to 8.3 update code statement.execute("CREATE INDEX events_data_source_obj_id ON tsk_event_descriptions(data_source_obj_id) "); statement.execute("CREATE INDEX events_content_obj_id ON tsk_event_descriptions(content_obj_id) "); @@ -2013,9 +2011,9 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot3toSchema8dot4(CaseDbSchem if (results.getString("name") != null && results.getString("name").equals("file_obj_id")) { hasMisnamedColumn = true; break; - } + } } - + if (hasMisnamedColumn) { // Since we can't rename the column we'll need to make new tables and copy the data statement.execute("CREATE TABLE temp_tsk_event_descriptions (" @@ -2032,16 +2030,16 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot3toSchema8dot4(CaseDbSchem + " FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id), " + " FOREIGN KEY(content_obj_id) REFERENCES tsk_files(obj_id), " + " FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id))" - ); - + ); + statement.execute("CREATE TABLE temp_tsk_events ( " + " event_id INTEGER PRIMARY KEY, " + " event_type_id BIGINT NOT NULL REFERENCES tsk_event_types(event_type_id) ," + " event_description_id BIGINT NOT NULL REFERENCES temp_tsk_event_descriptions(event_description_id)," + " time INTEGER NOT NULL, " + " UNIQUE (event_type_id, event_description_id, time))" - ); - + ); + // Copy the data statement.execute("INSERT INTO temp_tsk_event_descriptions(event_description_id, full_description, " + "med_description, short_description, data_source_obj_id, content_obj_id, artifact_id, " @@ -2049,7 +2047,7 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot3toSchema8dot4(CaseDbSchem statement.execute("INSERT INTO temp_tsk_events(event_id, event_type_id, " + "event_description_id, time) SELECT * FROM tsk_events"); - + // Drop the old tables statement.execute("DROP TABLE tsk_events"); statement.execute("DROP TABLE tsk_event_descriptions"); @@ -2057,7 +2055,7 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot3toSchema8dot4(CaseDbSchem // Rename the new tables statement.execute("ALTER TABLE temp_tsk_event_descriptions RENAME TO tsk_event_descriptions"); statement.execute("ALTER TABLE temp_tsk_events RENAME TO tsk_events"); - + //create tsk_events indices statement.execute("CREATE INDEX events_data_source_obj_id ON tsk_event_descriptions(data_source_obj_id) "); statement.execute("CREATE INDEX events_content_obj_id ON tsk_event_descriptions(content_obj_id) "); @@ -2069,14 +2067,14 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot3toSchema8dot4(CaseDbSchem default: throw new TskCoreException("Unsupported data base type: " + getDatabaseType().toString()); } - + // create pool info table if (this.dbType.equals(DbType.SQLITE)) { statement.execute("CREATE TABLE tsk_pool_info (obj_id INTEGER PRIMARY KEY, pool_type INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)"); } else { statement.execute("CREATE TABLE tsk_pool_info (obj_id BIGSERIAL PRIMARY KEY, pool_type INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)"); } - + // Add new account types for newly supported messaging applications, if they dont exists already. insertAccountTypeIfNotExists(statement, "IMO", "IMO"); insertAccountTypeIfNotExists(statement, "LINE", "LINE"); @@ -2088,15 +2086,15 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot3toSchema8dot4(CaseDbSchem insertAccountTypeIfNotExists(statement, "XENDER", "Xender"); insertAccountTypeIfNotExists(statement, "ZAPYA", "Zapya"); insertAccountTypeIfNotExists(statement, "SHAREIT", "ShareIt"); - + return new CaseDbSchemaVersionNumber(8, 4); } finally { closeResultSet(results); closeStatement(statement); releaseSingleUserCaseWriteLock(); - } + } } - + private CaseDbSchemaVersionNumber updateFromSchema8dot4toSchema8dot5(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException { if (schemaVersion.getMajor() != 8) { return schemaVersion; @@ -2112,13 +2110,15 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot4toSchema8dot5(CaseDbSchem switch (getDatabaseType()) { case POSTGRESQL: statement.execute("CREATE TABLE tsk_tag_sets (tag_set_id BIGSERIAL PRIMARY KEY, name TEXT UNIQUE)"); + statement.execute("ALTER TABLE tag_names ADD COLUMN tag_set_id BIGINT REFERENCES tsk_tag_sets(tag_set_id)"); break; case SQLITE: statement.execute("CREATE TABLE tsk_tag_sets (tag_set_id INTEGER PRIMARY KEY, name TEXT UNIQUE)"); + statement.execute("ALTER TABLE tag_names ADD COLUMN tag_set_id INTEGER REFERENCES tsk_tag_sets(tag_set_id)"); break; } - statement.execute("ALTER TABLE tag_names ADD COLUMN tag_set_id INTEGER REFERENCES tsk_tag_sets(tag_set_id)"); + statement.execute("ALTER TABLE tag_names ADD COLUMN rank INTEGER"); String insertStmt = "INSERT INTO tsk_tag_sets (name) VALUES ('Project VIC')"; if (getDatabaseType() == DbType.POSTGRESQL) { @@ -2130,12 +2130,12 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot4toSchema8dot5(CaseDbSchem if (resultSet != null && resultSet.next()) { int tagSetId = resultSet.getInt(1); - String updateQuery = "UPDATE tag_names SET tag_set_id = %d, color = '%s', display_name = '%s' WHERE display_name = '%s'"; - statement.executeUpdate(String.format(updateQuery, tagSetId, "Red", "Child Exploitation (Illegal)", "CAT-1: Child Exploitation (Illegal)")); - statement.executeUpdate(String.format(updateQuery, tagSetId, "Lime", "Child Exploitation (Non-Illegal/Age Difficult)", "CAT-2: Child Exploitation (Non-Illegal/Age Difficult)")); - statement.executeUpdate(String.format(updateQuery, tagSetId, "Yellow", "CGI/Animation (Child Exploitive)", "CAT-3: CGI/Animation (Child Exploitive)")); - statement.executeUpdate(String.format(updateQuery, tagSetId, "Purple", "Exemplar/Comparison (Internal Use Only)", "CAT-4: Exemplar/Comparison (Internal Use Only)")); - statement.executeUpdate(String.format(updateQuery, tagSetId, "Fuchsia", "Non-pertinent", "CAT-5: Non-pertinent")); + String updateQuery = "UPDATE tag_names SET tag_set_id = %d, color = '%s', rank = %d, display_name = '%s' WHERE display_name = '%s'"; + statement.executeUpdate(String.format(updateQuery, tagSetId, "Red", 1, "Child Exploitation (Illegal)", "CAT-1: Child Exploitation (Illegal)")); + statement.executeUpdate(String.format(updateQuery, tagSetId, "Lime", 2, "Child Exploitation (Non-Illegal/Age Difficult)", "CAT-2: Child Exploitation (Non-Illegal/Age Difficult)")); + statement.executeUpdate(String.format(updateQuery, tagSetId, "Yellow", 3, "CGI/Animation (Child Exploitive)", "CAT-3: CGI/Animation (Child Exploitive)")); + statement.executeUpdate(String.format(updateQuery, tagSetId, "Purple", 4, "Exemplar/Comparison (Internal Use Only)", "CAT-4: Exemplar/Comparison (Internal Use Only)")); + statement.executeUpdate(String.format(updateQuery, tagSetId, "Fuchsia", 5, "Non-pertinent", "CAT-5: Non-pertinent")); String deleteContentTag = "DELETE FROM content_tags WHERE tag_name_id IN (SELECT tag_name_id from tag_names WHERE display_name LIKE 'CAT-0: Uncategorized')"; String deleteArtifactTag = "DELETE FROM blackboard_artifact_tags WHERE tag_name_id IN (SELECT tag_name_id from tag_names WHERE display_name LIKE 'CAT-0: Uncategorized')"; @@ -2143,7 +2143,7 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot4toSchema8dot5(CaseDbSchem statement.executeUpdate(deleteContentTag); statement.executeUpdate(deleteArtifactTag); statement.executeUpdate(deleteCat0); - + } else { throw new TskCoreException("Failed to retrieve the default tag_set_id from DB"); } @@ -2181,18 +2181,18 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot4toSchema8dot5(CaseDbSchem } /** - * Inserts a row for the given account type in account_types table, - * if one doesn't exist. - * - * @param statement Statement to use to execute SQL. - * @param type_name Account type name. + * Inserts a row for the given account type in account_types table, if one + * doesn't exist. + * + * @param statement Statement to use to execute SQL. + * @param type_name Account type name. * @param display_name Account type display name. - * + * * @throws TskCoreException - * @throws SQLException + * @throws SQLException */ private void insertAccountTypeIfNotExists(Statement statement, String type_name, String display_name) throws TskCoreException, SQLException { - + String insertSQL = String.format("INTO account_types(type_name, display_name) VALUES ('%s', '%s')", type_name, display_name); switch (getDatabaseType()) { case POSTGRESQL: @@ -2206,7 +2206,8 @@ private void insertAccountTypeIfNotExists(Statement statement, String type_name, } statement.execute(insertSQL); //NON-NLS } - /** + + /** * Extract the extension from a file name. * * @param fileName the file name to extract the extension from. @@ -3035,7 +3036,7 @@ public long getBlackboardArtifactsTypeCount(int artifactTypeID) throws TskCoreEx releaseSingleUserCaseReadLock(); } } - + /** * Get a count of artifacts of a given type for the given data source. Does * not include rejected artifacts. @@ -6029,17 +6030,17 @@ public Volume addVolume(long parentObjId, long addr, long start, long length, St releaseSingleUserCaseWriteLock(); } } - + /** * Add a pool to the database. - * + * * @param parentObjId Object ID of the pool's parent * @param type Type of pool * @param transaction Case DB transaction - * + * * @return the newly created Pool - * - * @throws TskCoreException + * + * @throws TskCoreException */ public Pool addPool(long parentObjId, TskData.TSK_POOL_TYPE_ENUM type, CaseDbTransaction transaction) throws TskCoreException { acquireSingleUserCaseWriteLock(); @@ -6065,7 +6066,7 @@ public Pool addPool(long parentObjId, TskData.TSK_POOL_TYPE_ENUM type, CaseDbTra closeStatement(statement); releaseSingleUserCaseWriteLock(); } - } + } /** * Add a FileSystem to the database. @@ -6213,10 +6214,10 @@ public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId, connection.executeUpdate(statement); - DerivedFile derivedFile = new DerivedFile(this, objectId, dataSourceObjId, fileName, dirType, metaType, dirFlag, metaFlags, + DerivedFile derivedFile = new DerivedFile(this, objectId, dataSourceObjId, fileName, dirType, metaType, dirFlag, metaFlags, size, ctime, crtime, atime, mtime, null, null, parentPath, null, parent.getId(), null, null, extension); - timelineManager.addEventsForNewFile(derivedFile, connection); + timelineManager.addEventsForNewFile(derivedFile, connection); transaction.commit(); transaction = null; @@ -7673,7 +7674,7 @@ FileSystem getFileSystemById(long id, long parentId) throws TskCoreException { FileSystem getFileSystemById(long id, Volume parent) throws TskCoreException { return getFileSystemByIdHelper(id, parent); } - + /** * Get a pool by the object id * @@ -7687,8 +7688,8 @@ FileSystem getFileSystemById(long id, Volume parent) throws TskCoreException { */ Pool getPoolById(long id, Content parent) throws TskCoreException { return getPoolByIdHelper(id, parent); - } - + } + /** * @param id ID of the desired Volume * @param parentId ID of the Volume's parent @@ -7702,7 +7703,7 @@ Pool getPoolById(long id, long parentId) throws TskCoreException { pool.setParentId(parentId); return pool; } - + /** * Get pool by id and Content parent * @@ -7718,13 +7719,13 @@ private Pool getPoolByIdHelper(long id, Content parent) throws TskCoreException acquireSingleUserCaseReadLock(); try (CaseDbConnection connection = connections.getConnection(); - Statement s = connection.createStatement(); - ResultSet rs = connection.executeQuery(s, "SELECT * FROM tsk_pool_info " //NON-NLS - + "where obj_id = " + id);) { //NON-NLS + Statement s = connection.createStatement(); + ResultSet rs = connection.executeQuery(s, "SELECT * FROM tsk_pool_info " //NON-NLS + + "where obj_id = " + id);) { //NON-NLS if (rs.next()) { Pool pool = new Pool(this, rs.getLong("obj_id"), TskData.TSK_POOL_TYPE_ENUM.valueOf(rs.getLong("pool_type")).getName(), rs.getLong("pool_type")); pool.setParent(parent); - + return pool; } else { throw new TskCoreException("No pool found for ID:" + id); @@ -8014,7 +8015,7 @@ List<Long> getImageChildrenIds(Image img) throws TskCoreException { } return children; } - + /** * Returns the list of direct children for a given Pool * @@ -8075,7 +8076,7 @@ List<Long> getPoolChildrenIds(Pool pool) throws TskCoreException { } } return children; - } + } /** * Returns the list of direct children for a given VolumeSystem @@ -9612,7 +9613,7 @@ public List<TagName> getAllTagNames() throws TskCoreException { while (resultSet.next()) { tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"), resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")), - TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getInt("tag_set_id"))); //NON-NLS + TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS } return tagNames; } catch (SQLException ex) { @@ -9646,7 +9647,7 @@ public List<TagName> getTagNamesInUse() throws TskCoreException { while (resultSet.next()) { tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"), resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")), - TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"))); //NON-NLS + TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS } return tagNames; } catch (SQLException ex) { @@ -9690,7 +9691,7 @@ public List<TagName> getTagNamesInUse(long dsObjId) throws TskCoreException { while (resultSet.next()) { tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"), resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")), - TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"))); //NON-NLS + TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS } return tagNames; } catch (SQLException ex) { @@ -9753,8 +9754,16 @@ public TagName addOrUpdateTagName(String displayName, String description, TagNam connection.executeUpdate(statement); resultSet = statement.getGeneratedKeys(); resultSet.next(); - return new TagName(resultSet.getLong(1), //last_insert_rowid() - displayName, description, color, knownStatus, 0); + + long tagId = resultSet.getLong(1); + + statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_TAG_NAME_BY_ID); + statement.clearParameters(); + statement.setLong(1, tagId); + resultSet = connection.executeQuery(statement); + + return new TagName(tagId, + displayName, description, color, knownStatus, resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); } catch (SQLException ex) { throw new TskCoreException("Error adding row for " + displayName + " tag name to tag_names table", ex); } finally { @@ -9776,7 +9785,7 @@ public TagName addOrUpdateTagName(String displayName, String description, TagNam * @return A ContentTag data transfer object (DTO) for the new row. * * @throws TskCoreException - * @deprecated Use TaggingManager.addContentTag + * @deprecated Use TaggingManager.addContentTag */ @Deprecated public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws TskCoreException { @@ -9828,7 +9837,7 @@ public List<ContentTag> getAllContentTags() throws TskCoreException { while (resultSet.next()) { TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"), resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")), - TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id")); //NON-NLS + TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS Content content = getContentById(resultSet.getLong("obj_id")); //NON-NLS tags.add(new ContentTag(resultSet.getLong("tag_id"), content, tagName, resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name"))); //NON-NLS @@ -9958,7 +9967,7 @@ public ContentTag getContentTagByID(long contentTagID) throws TskCoreException { while (resultSet.next()) { TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"), resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")), - TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id")); + TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); tag = new ContentTag(resultSet.getLong("tag_id"), getContentById(resultSet.getLong("obj_id")), tagName, resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name")); } @@ -10094,7 +10103,7 @@ public List<ContentTag> getContentTagsByContent(Content content) throws TskCoreE while (resultSet.next()) { TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"), resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")), - TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id")); //NON-NLS + TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS ContentTag tag = new ContentTag(resultSet.getLong("tag_id"), content, tagName, resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name")); //NON-NLS tags.add(tag); @@ -10174,7 +10183,7 @@ public List<BlackboardArtifactTag> getAllBlackboardArtifactTags() throws TskCore while (resultSet.next()) { TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"), resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")), - TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id")); //NON-NLS + TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS Content content = getContentById(artifact.getObjectID()); BlackboardArtifactTag tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"), @@ -10404,7 +10413,7 @@ public BlackboardArtifactTag getBlackboardArtifactTagByID(long artifactTagID) th while (resultSet.next()) { TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"), resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")), - TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id")); + TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS Content content = getContentById(artifact.getObjectID()); tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"), @@ -10452,7 +10461,7 @@ public List<BlackboardArtifactTag> getBlackboardArtifactTagsByArtifact(Blackboar while (resultSet.next()) { TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"), resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")), - TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id")); //NON-NLS + TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS Content content = getContentById(artifact.getObjectID()); BlackboardArtifactTag tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"), artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name")); //NON-NLS @@ -10980,21 +10989,21 @@ private List<IngestModuleInfo> getIngestModules(int ingestJobId, CaseDbConnectio } } - + /** - * Add an image to the database. - * For use with the JNI callbacks associated with the add image process. - * - * @param type Type of image. - * @param sectorSize Sector size. - * @param size Image size. - * @param timezone Time zone. - * @param md5 MD5 hash. - * @param sha1 SHA1 hash. - * @param sha256 SHA256 hash. - * @param deviceId Device ID. + * Add an image to the database. For use with the JNI callbacks associated + * with the add image process. + * + * @param type Type of image. + * @param sectorSize Sector size. + * @param size Image size. + * @param timezone Time zone. + * @param md5 MD5 hash. + * @param sha1 SHA1 hash. + * @param sha256 SHA256 hash. + * @param deviceId Device ID. * @param collectionDetails Collection details. - * @param transaction Case DB transaction. + * @param transaction Case DB transaction. * * @return The newly added Image object ID. * @@ -11042,17 +11051,17 @@ long addImageJNI(TskData.TSK_IMG_TYPE_ENUM type, long sectorSize, long size, releaseSingleUserCaseWriteLock(); } } - + /** - * Add an image name to the database. - * For use with the JNI callbacks associated with the add image process. - * - * @param objId The object id of the image. - * @param name The file name for the image - * @param sequence The sequence number of this file. + * Add an image name to the database. For use with the JNI callbacks + * associated with the add image process. + * + * @param objId The object id of the image. + * @param name The file name for the image + * @param sequence The sequence number of this file. * @param transaction The open transaction. - * - * @throws TskCoreException + * + * @throws TskCoreException */ void addImageNameJNI(long objId, String name, long sequence, CaseDbTransaction transaction) throws TskCoreException { @@ -11071,21 +11080,21 @@ void addImageNameJNI(long objId, String name, long sequence, releaseSingleUserCaseWriteLock(); } } - + /** - * Looks up a parent file object ID. - * The calling thread is expected to have a case read lock. - * For use with the JNI callbacks associated with the add image process. - * - * @param metaAddr The metadata address. - * @param fsObjId The file system object ID. - * @param path The file path. - * @param name The file name. + * Looks up a parent file object ID. The calling thread is expected to have + * a case read lock. For use with the JNI callbacks associated with the add + * image process. + * + * @param metaAddr The metadata address. + * @param fsObjId The file system object ID. + * @param path The file path. + * @param name The file name. * @param transaction The open transaction. - * + * * @return The object ID if found, -1 otherwise. - * - * @throws TskCoreException + * + * @throws TskCoreException */ long findParentObjIdJNI(long metaAddr, long fsObjId, String path, String name, CaseDbTransaction transaction) throws TskCoreException { ResultSet resultSet = null; @@ -11109,48 +11118,50 @@ long findParentObjIdJNI(long metaAddr, long fsObjId, String path, String name, C closeResultSet(resultSet); } } - + /** - * Add a file system file to the database. - * For use with the JNI callbacks associated with the add image process. - * + * Add a file system file to the database. For use with the JNI callbacks + * associated with the add image process. + * * @param parentObjId The parent of the file. * @param fsObjId The object ID of the file system. * @param dataSourceObjId The data source object ID. - * @param fsType The type. - * @param attrType The type attribute given to the file by the file system. - * @param attrId The type id given to the file by the file system. - * @param name The name of the file. - * @param metaAddr The meta address of the file. - * @param metaSeq The meta sequence number of the file. - * @param dirType The type of the file, usually as reported in - * the name structure of the file system. - * @param metaType The type of the file, usually as reported in - * the metadata structure of the file system. - * @param dirFlags The allocated status of the file, usually as - * reported in the name structure of the file system. - * @param metaFlags The allocated status of the file, usually as - * reported in the metadata structure of the file system. - * @param size The file size. - * @param crtime The created time. - * @param ctime The last changed time - * @param atime The last accessed time. - * @param mtime The last modified time. - * @param meta_mode The modes for the file. - * @param gid The group identifier. - * @param uid The user identifier. - * @param md5 The MD5 hash. - * @param known The file known status. - * @param escaped_path The escaped path to the file. - * @param extension The file extension. - * @param hasLayout True if this is a layout file, false otherwise. - * @param transaction The open transaction. - * + * @param fsType The type. + * @param attrType The type attribute given to the file by the file + * system. + * @param attrId The type id given to the file by the file system. + * @param name The name of the file. + * @param metaAddr The meta address of the file. + * @param metaSeq The meta sequence number of the file. + * @param dirType The type of the file, usually as reported in the + * name structure of the file system. + * @param metaType The type of the file, usually as reported in the + * metadata structure of the file system. + * @param dirFlags The allocated status of the file, usually as + * reported in the name structure of the file system. + * @param metaFlags The allocated status of the file, usually as + * reported in the metadata structure of the file + * system. + * @param size The file size. + * @param crtime The created time. + * @param ctime The last changed time + * @param atime The last accessed time. + * @param mtime The last modified time. + * @param meta_mode The modes for the file. + * @param gid The group identifier. + * @param uid The user identifier. + * @param md5 The MD5 hash. + * @param known The file known status. + * @param escaped_path The escaped path to the file. + * @param extension The file extension. + * @param hasLayout True if this is a layout file, false otherwise. + * @param transaction The open transaction. + * * @return The object ID of the new file system - * - * @throws TskCoreException + * + * @throws TskCoreException */ - long addFileJNI(long parentObjId, + long addFileJNI(long parentObjId, Long fsObjId, long dataSourceObjId, int fsType, Integer attrType, Integer attrId, String name, @@ -11160,7 +11171,7 @@ long addFileJNI(long parentObjId, Long crtime, Long ctime, Long atime, Long mtime, Integer meta_mode, Integer gid, Integer uid, String md5, TskData.FileKnown known, - String escaped_path, String extension, + String escaped_path, String extension, boolean hasLayout, CaseDbTransaction transaction) throws TskCoreException { Statement queryStatement = null; @@ -11184,7 +11195,7 @@ long addFileJNI(long parentObjId, } statement.setLong(2, objectId); // obj_id statement.setLong(3, dataSourceObjId); // data_source_obj_id - statement.setShort(4, (short)fsType); // type + statement.setShort(4, (short) fsType); // type if (attrType != null) { statement.setShort(5, attrType.shortValue()); // attr_type } else { @@ -11206,10 +11217,10 @@ long addFileJNI(long parentObjId, } else { statement.setNull(9, java.sql.Types.INTEGER); } - statement.setShort(10, (short)dirType); // dir_type - statement.setShort(11, (short)metaType); // meta_type - statement.setShort(12, (short)dirFlags); // dir_flags - statement.setShort(13, (short)metaFlags); // meta_flags + statement.setShort(10, (short) dirType); // dir_type + statement.setShort(11, (short) metaType); // meta_type + statement.setShort(12, (short) dirFlags); // dir_flags + statement.setShort(13, (short) metaFlags); // meta_flags statement.setLong(14, size < 0 ? 0 : size); // size if (crtime != null) { statement.setLong(15, crtime); // crtime @@ -11258,20 +11269,20 @@ long addFileJNI(long parentObjId, connection.executeUpdate(statement); // If this is not a slack file create the timeline events - if (! hasLayout + if (!hasLayout && TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType() != fsType && (!name.equals(".")) && (!name.equals(".."))) { TimelineManager timelineManager = getTimelineManager(); - DerivedFile derivedFile = new DerivedFile(this, objectId, dataSourceObjId, name, - TSK_FS_NAME_TYPE_ENUM.valueOf((short)dirType), - TSK_FS_META_TYPE_ENUM.valueOf((short)metaType), - TSK_FS_NAME_FLAG_ENUM.valueOf(dirFlags), - (short)metaFlags, + DerivedFile derivedFile = new DerivedFile(this, objectId, dataSourceObjId, name, + TSK_FS_NAME_TYPE_ENUM.valueOf((short) dirType), + TSK_FS_META_TYPE_ENUM.valueOf((short) metaType), + TSK_FS_NAME_FLAG_ENUM.valueOf(dirFlags), + (short) metaFlags, size, ctime, crtime, atime, mtime, null, null, escaped_path, null, parentObjId, null, null, extension); - timelineManager.addEventsForNewFileQuiet(derivedFile, connection); + timelineManager.addEventsForNewFileQuiet(derivedFile, connection); } - + return objectId; } catch (SQLException ex) { throw new TskCoreException("Failed to add file system file", ex); @@ -11280,28 +11291,28 @@ long addFileJNI(long parentObjId, releaseSingleUserCaseWriteLock(); } } - + /** - * Add a layout file range to the database. - * For use with the JNI callbacks associated with the add image process. - * - * @param objId Object ID of the layout file. - * @param byteStart Start byte. - * @param byteLen Length in bytes. - * @param seq Sequence number of this range. + * Add a layout file range to the database. For use with the JNI callbacks + * associated with the add image process. + * + * @param objId Object ID of the layout file. + * @param byteStart Start byte. + * @param byteLen Length in bytes. + * @param seq Sequence number of this range. * @param transaction The open transaction. - * - * @throws TskCoreException + * + * @throws TskCoreException */ - void addLayoutFileRangeJNI(long objId, long byteStart, long byteLen, + void addLayoutFileRangeJNI(long objId, long byteStart, long byteLen, long seq, CaseDbTransaction transaction) throws TskCoreException { try { acquireSingleUserCaseWriteLock(); CaseDbConnection connection = transaction.getConnection(); - + PreparedStatement prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LAYOUT_FILE); prepStmt.clearParameters(); - prepStmt.setLong(1, objId); + prepStmt.setLong(1, objId); prepStmt.setLong(2, byteStart); prepStmt.setLong(3, byteLen); prepStmt.setLong(4, seq); @@ -11312,7 +11323,7 @@ void addLayoutFileRangeJNI(long objId, long byteStart, long byteLen, releaseSingleUserCaseWriteLock(); } } - + /** * Stores a pair of object ID and its type */ @@ -11443,7 +11454,7 @@ private enum PREPARED_STATEMENT { + " AND content_tags.tag_name_id = ? " + " AND tsk_files.data_source_obj_id = ? " ), - SELECT_CONTENT_TAGS("SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id " + SELECT_CONTENT_TAGS("SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id, tag_names.rank " + "FROM content_tags " + "INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id " + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id"), //NON-NLS @@ -11458,12 +11469,12 @@ private enum PREPARED_STATEMENT { + " AND content_tags.tag_name_id = tag_names.tag_name_id" + " AND content_tags.tag_name_id = ?" + " AND tsk_files.data_source_obj_id = ? "), - SELECT_CONTENT_TAG_BY_ID("SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id " + SELECT_CONTENT_TAG_BY_ID("SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id, tag_names.rank " + "FROM content_tags " + "INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id " + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id " + "WHERE tag_id = ?"), //NON-NLS - SELECT_CONTENT_TAGS_BY_CONTENT("SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id " + SELECT_CONTENT_TAGS_BY_CONTENT("SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id, tag_names.rank " + "FROM content_tags " + "INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id " + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id " @@ -11471,7 +11482,7 @@ private enum PREPARED_STATEMENT { INSERT_ARTIFACT_TAG("INSERT INTO blackboard_artifact_tags (artifact_id, tag_name_id, comment, examiner_id) " + "VALUES (?, ?, ?, ?)"), //NON-NLS DELETE_ARTIFACT_TAG("DELETE FROM blackboard_artifact_tags WHERE tag_id = ?"), //NON-NLS - SELECT_ARTIFACT_TAGS("SELECT blackboard_artifact_tags.tag_id, blackboard_artifact_tags.artifact_id, blackboard_artifact_tags.tag_name_id, blackboard_artifact_tags.comment, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tag_names.tag_set_id, tsk_examiners.login_name " + SELECT_ARTIFACT_TAGS("SELECT blackboard_artifact_tags.tag_id, blackboard_artifact_tags.artifact_id, blackboard_artifact_tags.tag_name_id, blackboard_artifact_tags.comment, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tag_names.tag_set_id, tsk_examiners.login_name, tag_names.rank " + "FROM blackboard_artifact_tags " + "INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id " + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id"), //NON-NLS @@ -11489,12 +11500,12 @@ private enum PREPARED_STATEMENT { + " AND artifact_tags.artifact_id = arts.artifact_id" + " AND artifact_tags.tag_name_id = ? " + " AND arts.data_source_obj_id = ? "), - SELECT_ARTIFACT_TAG_BY_ID("SELECT blackboard_artifact_tags.tag_id, blackboard_artifact_tags.artifact_id, blackboard_artifact_tags.tag_name_id, blackboard_artifact_tags.comment, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id " + SELECT_ARTIFACT_TAG_BY_ID("SELECT blackboard_artifact_tags.tag_id, blackboard_artifact_tags.artifact_id, blackboard_artifact_tags.tag_name_id, blackboard_artifact_tags.comment, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id, tag_names.rank " + "FROM blackboard_artifact_tags " + "INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id " + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id " + "WHERE blackboard_artifact_tags.tag_id = ?"), //NON-NLS - SELECT_ARTIFACT_TAGS_BY_ARTIFACT("SELECT blackboard_artifact_tags.tag_id, blackboard_artifact_tags.artifact_id, blackboard_artifact_tags.tag_name_id, blackboard_artifact_tags.comment, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id " + SELECT_ARTIFACT_TAGS_BY_ARTIFACT("SELECT blackboard_artifact_tags.tag_id, blackboard_artifact_tags.artifact_id, blackboard_artifact_tags.tag_name_id, blackboard_artifact_tags.comment, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id, tag_names.rank " + "FROM blackboard_artifact_tags " + "INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id " + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id " @@ -11531,7 +11542,8 @@ private enum PREPARED_STATEMENT { INSERT_POOL_INFO("INSERT INTO tsk_pool_info (obj_id, pool_type) VALUES (?, ?)"), INSERT_FS_INFO("INSERT INTO tsk_fs_info (obj_id, data_source_obj_id, img_offset, fs_type, block_size, block_count, root_inum, first_inum, last_inum, display_name)" + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"), - SELECT_OBJ_ID_BY_META_ADDR_AND_PATH("SELECT obj_id FROM tsk_files WHERE meta_addr = ? AND fs_obj_id = ? AND parent_path = ? AND name = ?"); + SELECT_OBJ_ID_BY_META_ADDR_AND_PATH("SELECT obj_id FROM tsk_files WHERE meta_addr = ? AND fs_obj_id = ? AND parent_path = ? AND name = ?"), + SELECT_TAG_NAME_BY_ID("SELECT * FROM tag_names where tag_name_id = ?"); private final String sql; diff --git a/bindings/java/src/org/sleuthkit/datamodel/TagName.java b/bindings/java/src/org/sleuthkit/datamodel/TagName.java index 2bb7b92f3747c4407ef42c18b3dc1cbc864d2b24..769971b5e9be1776d6a8aab10a5fce03c3db4971 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/TagName.java +++ b/bindings/java/src/org/sleuthkit/datamodel/TagName.java @@ -87,15 +87,17 @@ public static HTML_COLOR getColorByName(String colorName) { private final HTML_COLOR color; private final TskData.FileKnown knownStatus; private final long tagSetId; + private final int rank; // Clients of the org.sleuthkit.datamodel package should not directly create these objects. - TagName(long id, String displayName, String description, HTML_COLOR color, TskData.FileKnown knownStatus, long tagSetId) { + TagName(long id, String displayName, String description, HTML_COLOR color, TskData.FileKnown knownStatus, long tagSetId, int rank) { this.id = id; this.displayName = displayName; this.description = description; this.color = color; this.knownStatus = knownStatus; this.tagSetId = tagSetId; + this.rank = rank; } public long getId() { @@ -121,6 +123,10 @@ public TskData.FileKnown getKnownStatus() { long getTagSetId() { return tagSetId; } + + public int getRank() { + return rank; + } /** * Compares two TagName objects by comparing their display names. diff --git a/bindings/java/src/org/sleuthkit/datamodel/TaggingManager.java b/bindings/java/src/org/sleuthkit/datamodel/TaggingManager.java index 60ff54ba72c2e2603d6a3bf146666ae1391b7ce1..29826d973765b201532398a5c6c391262281d7ad 100755 --- a/bindings/java/src/org/sleuthkit/datamodel/TaggingManager.java +++ b/bindings/java/src/org/sleuthkit/datamodel/TaggingManager.java @@ -109,20 +109,16 @@ public TagSet addTagSet(String name, List<TagName> tagNames) throws TskCoreExcep if (tagNames != null) { // Get all of the TagName ids they can be updated in one // SQL call. - List<String> idList = new ArrayList<>(); - for (TagName tagName : tagNames) { - idList.add(Long.toString(tagName.getId())); - } - - stmt.executeUpdate(String.format("UPDATE tag_names SET tag_set_id = %d WHERE tag_name_id IN (%s)", setID, String.join(",", idList))); - - for (TagName tagName : tagNames) { + for (int index = 0; index < tagNames.size(); index++) { + TagName tagName = tagNames.get(index); + stmt.executeUpdate(String.format("UPDATE tag_names SET tag_set_id = %d, rank = %d WHERE tag_name_id = %d", setID, index, tagName.getId())); updatedTags.add(new TagName(tagName.getId(), tagName.getDisplayName(), tagName.getDescription(), tagName.getColor(), tagName.getKnownStatus(), - setID)); + setID, + index)); } } tagSet = new TagSet(setID, name, updatedTags); @@ -213,7 +209,7 @@ public TagSet addTagNameToTagSet(TagSet tagSet, TagName tagName) throws TskCoreE List<TagName> newTagNameList = new ArrayList<>(); newTagNameList.addAll(setTagNameList); - newTagNameList.add(new TagName(tagName.getId(), tagName.getDisplayName(), tagName.getDescription(), tagName.getColor(), tagName.getKnownStatus(), tagSet.getId())); + newTagNameList.add(new TagName(tagName.getId(), tagName.getDisplayName(), tagName.getDescription(), tagName.getColor(), tagName.getKnownStatus(), tagSet.getId(), tagName.getRank())); return new TagSet(tagSet.getId(), tagSet.getName(), newTagNameList); @@ -266,7 +262,8 @@ public BlackboardArtifactTagChange addArtifactTag(BlackboardArtifact artifact, T resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")), TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), - tagSetId + tagSetId, + resultSet.getInt("rank") ); BlackboardArtifactTag bat @@ -361,7 +358,8 @@ public ContentTagChange addContentTag(Content content, TagName tagName, String c resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")), TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), - tagSetId + tagSetId, + resultSet.getInt("rank") ); ContentTag bat @@ -487,13 +485,13 @@ private List<TagName> getTagNamesByTagSetID(int tagSetId) throws TskCoreExceptio String query = String.format("SELECT * FROM tag_names WHERE tag_set_id = %d", tagSetId); try (Statement stmt = connection.createStatement(); ResultSet resultSet = stmt.executeQuery(query)) { while (resultSet.next()) { - long tagId = resultSet.getLong("tag_name_id"); - String tagName = resultSet.getString("display_name"); - String description = resultSet.getString("description"); - String color = resultSet.getString("color"); - byte knownStatus = resultSet.getByte("knownStatus"); - - tagNameList.add(new TagName(tagId, tagName, description, TagName.HTML_COLOR.getColorByName(color), TskData.FileKnown.valueOf(knownStatus), tagSetId)); + tagNameList.add(new TagName(resultSet.getLong("tag_name_id"), + resultSet.getString("display_name"), + resultSet.getString("description"), + TagName.HTML_COLOR.getColorByName(resultSet.getString("color")), + TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), + tagSetId, + resultSet.getInt("rank"))); } } catch (SQLException ex) { throw new TskCoreException(String.format("Error getting tag names for tag set (%d)", tagSetId), ex);