diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java index e534c08b2ab321558f9550d026552c4799b8a910..802f95d1329583d4cfb950c9d095a071a6e6bf6e 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java @@ -368,13 +368,12 @@ private void init() throws Exception { typeNameToAttributeTypeMap = new ConcurrentHashMap<>(); /* - * The following methods need to be called before updateDatabaseSchema - * due to the way that updateFromSchema2toSchema3 was implemented. + * The database schema must be updated before loading blackboard artifact/attribute types */ + updateDatabaseSchema(null); initBlackboardArtifactTypes(); initBlackboardAttributeTypes(); initNextArtifactId(); - updateDatabaseSchema(null); try (CaseDbConnection connection = connections.getConnection()) { initIngestModuleTypes(connection); @@ -1072,11 +1071,13 @@ private CaseDbSchemaVersionNumber updateFromSchema2toSchema3(CaseDbSchemaVersion return schemaVersion; } Statement statement = null; + Statement statement2 = null; Statement updateStatement = null; ResultSet resultSet = null; acquireSingleUserCaseWriteLock(); try { statement = connection.createStatement(); + statement2 = connection.createStatement(); // Add new tables for tags. statement.execute("CREATE TABLE tag_names (tag_name_id INTEGER PRIMARY KEY, display_name TEXT UNIQUE, description TEXT NOT NULL, color TEXT NOT NULL)"); //NON-NLS @@ -1121,61 +1122,105 @@ private CaseDbSchemaVersionNumber updateFromSchema2toSchema3(CaseDbSchemaVersion + " WHERE blackboard_attributes.artifact_id = " + artifactId + ";"); //NON-NLS } resultSet.close(); - resultSet = null; // Convert existing tag artifact and attribute rows to rows in the new tags tables. - // TODO: This code depends on prepared statements that could evolve with - // time, breaking this upgrade. The code that follows should be rewritten - // to do everything with SQL specific to case database schema version 2. - HashMap<String, TagName> tagNames = new HashMap<String, TagName>(); - for (BlackboardArtifact artifact : getBlackboardArtifacts(ARTIFACT_TYPE.TSK_TAG_FILE)) { - Content content = getContentById(artifact.getObjectID()); - String name = ""; //NON-NLS - String comment = ""; //NON-NLS - ArrayList<BlackboardAttribute> attributes = getBlackboardAttributes(artifact); - for (BlackboardAttribute attribute : attributes) { - if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID()) { - name = attribute.getValueString(); - } else if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID()) { - comment = attribute.getValueString(); - } + Map<String, Long> tagNames = new HashMap<>(); + long tagNameCounter = 1; + + // Convert file tags. + // We need data from the TSK_TAG_NAME and TSK_COMMENT attributes, and need the file size from the tsk_files table. + resultSet = statement.executeQuery("SELECT * FROM \n" + + "(SELECT blackboard_artifacts.obj_id AS objId, blackboard_attributes.artifact_id AS artifactId, blackboard_attributes.value_text AS name\n" + + "FROM blackboard_artifacts INNER JOIN blackboard_attributes \n" + + "ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id \n" + + "WHERE blackboard_artifacts.artifact_type_id = " + + BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() + + " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID() + + ") AS tagNames \n" + + "INNER JOIN \n" + + "(SELECT tsk_files.obj_id as objId2, tsk_files.size AS fileSize \n" + + "FROM blackboard_artifacts INNER JOIN tsk_files \n" + + "ON blackboard_artifacts.obj_id = tsk_files.obj_id) AS fileData \n" + + "ON tagNames.objId = fileData.objId2 \n" + + "LEFT JOIN \n" + + "(SELECT value_text AS comment, artifact_id AS tagArtifactId FROM blackboard_attributes WHERE attribute_type_id = " + + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID() + ") AS tagComments \n" + + "ON tagNames.artifactId = tagComments.tagArtifactId"); + + while (resultSet.next()) { + long objId = resultSet.getLong("objId"); + long fileSize = resultSet.getLong("fileSize"); + String tagName = resultSet.getString("name"); + String tagComment = resultSet.getString("comment"); + if (tagComment == null) { + tagComment = ""; } - if (!name.isEmpty()) { - TagName tagName; - if (tagNames.containsKey(name)) { - tagName = tagNames.get(name); + + if (tagName != null && ! tagName.isEmpty()) { + // Get the index for the tag name, adding it to the database if needed. + long tagNameIndex; + if (tagNames.containsKey(tagName)) { + tagNameIndex = tagNames.get(tagName); } else { - tagName = addTagName(name, "", TagName.HTML_COLOR.NONE); //NON-NLS - tagNames.put(name, tagName); + statement2.execute("INSERT INTO tag_names (display_name, description, color) " + + "VALUES(\"" + tagName + "\", \"\", \"None\")"); + tagNames.put(tagName, tagNameCounter); + tagNameIndex = tagNameCounter; + tagNameCounter++; } - addContentTag(content, tagName, comment, 0, content.getSize() - 1); + + statement2.execute("INSERT INTO content_tags (obj_id, tag_name_id, comment, begin_byte_offset, end_byte_offset) " + + "VALUES(" + objId + ", " + tagNameIndex + ", \"" + tagComment + "\", 0, " + fileSize + ")"); } } - for (BlackboardArtifact artifact : getBlackboardArtifacts(ARTIFACT_TYPE.TSK_TAG_ARTIFACT)) { - long taggedArtifactId = -1; - String name = ""; //NON-NLS - String comment = ""; //NON-NLS - ArrayList<BlackboardAttribute> attributes = getBlackboardAttributes(artifact); - for (BlackboardAttribute attribute : attributes) { - if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID()) { - name = attribute.getValueString(); - } else if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID()) { - comment = attribute.getValueString(); - } else if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()) { - taggedArtifactId = attribute.getValueLong(); - } + resultSet.close(); + + // Convert artifact tags. + // We need data from the TSK_TAG_NAME, TSK_TAGGED_ARTIFACT, and TSK_COMMENT attributes. + resultSet = statement.executeQuery("SELECT * FROM \n" + + "(SELECT blackboard_artifacts.obj_id AS objId, blackboard_attributes.artifact_id AS artifactId, " + + "blackboard_attributes.value_text AS name\n" + + "FROM blackboard_artifacts INNER JOIN blackboard_attributes \n" + + "ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id \n" + + "WHERE blackboard_artifacts.artifact_type_id = " + + BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID() + + " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID() + + ") AS tagNames \n" + + "INNER JOIN \n" + + "(SELECT value_int64 AS taggedArtifactId, artifact_id AS associatedArtifactId FROM blackboard_attributes WHERE attribute_type_id = " + + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID() + ") AS tagArtifacts \n" + + "ON tagNames.artifactId = tagArtifacts.associatedArtifactId \n" + + "LEFT JOIN \n" + + "(SELECT value_text AS comment, artifact_id AS commentArtifactId FROM blackboard_attributes WHERE attribute_type_id = " + + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID() + ") AS tagComments \n" + + "ON tagNames.artifactId = tagComments.commentArtifactId"); + + while (resultSet.next()) { + long artifactId = resultSet.getLong("taggedArtifactId"); + String tagName = resultSet.getString("name"); + String tagComment = resultSet.getString("comment"); + if (tagComment == null) { + tagComment = ""; } - if (taggedArtifactId != -1 && !name.isEmpty()) { - TagName tagName; - if (tagNames.containsKey(name)) { - tagName = tagNames.get(name); + if (tagName != null && ! tagName.isEmpty()) { + // Get the index for the tag name, adding it to the database if needed. + long tagNameIndex; + if (tagNames.containsKey(tagName)) { + tagNameIndex = tagNames.get(tagName); } else { - tagName = addTagName(name, "", TagName.HTML_COLOR.NONE); //NON-NLS - tagNames.put(name, tagName); + statement2.execute("INSERT INTO tag_names (display_name, description, color) " + + "VALUES(\"" + tagName + "\", \"\", \"None\")"); + tagNames.put(tagName, tagNameCounter); + tagNameIndex = tagNameCounter; + tagNameCounter++; } - addBlackboardArtifactTag(getBlackboardArtifact(taggedArtifactId), tagName, comment); + + statement2.execute("INSERT INTO blackboard_artifact_tags (artifact_id, tag_name_id, comment) " + + "VALUES(" + artifactId + ", " + tagNameIndex + ", \"" + tagComment + "\")"); } - } + } + resultSet.close(); + statement.execute( "DELETE FROM blackboard_attributes WHERE artifact_id IN " //NON-NLS + "(SELECT artifact_id FROM blackboard_artifacts WHERE artifact_type_id = " //NON-NLS @@ -1191,7 +1236,7 @@ private CaseDbSchemaVersionNumber updateFromSchema2toSchema3(CaseDbSchemaVersion closeStatement(updateStatement); closeResultSet(resultSet); closeStatement(statement); - connection.close(); + closeStatement(statement2); releaseSingleUserCaseWriteLock(); } } @@ -2260,12 +2305,14 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot6toSchema8dot7(CaseDbSchem dateDataType = "INTEGER"; primaryKeyType = "INTEGER"; } - statement.execute("ALTER TABLE data_source_info ADD COLUMN added_date_time "+ dateDataType); + statement.execute("ALTER TABLE data_source_info ADD COLUMN added_date_time "+ dateDataType ); statement.execute("ALTER TABLE data_source_info ADD COLUMN acquisition_tool_settings TEXT"); statement.execute("ALTER TABLE data_source_info ADD COLUMN acquisition_tool_name TEXT"); statement.execute("ALTER TABLE data_source_info ADD COLUMN acquisition_tool_version TEXT"); + + statement.execute("ALTER TABLE blackboard_artifact_types ADD COLUMN category_type INTEGER DEFAULT 0"); - // create host table. + // Create host table. statement.execute("CREATE TABLE tsk_hosts (id " + primaryKeyType + " PRIMARY KEY, " + "name TEXT NOT NULL, " // host name + "status INTEGER DEFAULT 0, " // to indicate if the host was merged/deleted