From e8f4dadf31fffc784f802930fabc8a507195409c Mon Sep 17 00:00:00 2001
From: Ann Priestman <apriestman@basistech.com>
Date: Thu, 31 Jan 2019 12:49:32 -0500
Subject: [PATCH] Changed logic for parsing local path. Fixed typo in creation
 version. Added upgrade to fix typo.

---
 .../org/sleuthkit/datamodel/AbstractFile.java | 19 +++++--
 .../sleuthkit/datamodel/SleuthkitCase.java    | 52 ++++++++++++++++++-
 tsk/auto/db_sqlite.cpp                        |  4 +-
 tsk/auto/tsk_db.h                             |  2 +-
 4 files changed, 68 insertions(+), 9 deletions(-)

diff --git a/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java b/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java
index 4ee740047..5043c0a64 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java
@@ -900,12 +900,21 @@ void setLocalFilePath(String localPath) {
 			localAbsPath = null;
 			localPathSet = false;
 		} else {
-			this.localPath = localPath;
-			if (localPath.startsWith("/") || localPath.startsWith("\\")
-					|| localPath.matches("[A-Za-z]:[/\\\\].*")) {
-				this.localAbsPath = localPath;
+			// It should always be the case that absolute paths start with slashes or a windows drive letter
+			// and relative paths do not, but some older versions of modules created derived file paths
+			// starting with slashes. So we first check if this file is a DerivedFile before looking at the path.
+			if (this instanceof DerivedFile) {
+				// DerivedFiles always have relative paths
+				this.localAbsPath = getSleuthkitCase().getDbDirPath() + java.io.File.separator + localPath;
 			} else {
-				this.localAbsPath = getSleuthkitCase().getDbDirPath() + java.io.File.separator + this.localPath;
+				// If a path starts with a slash or with a Windows drive letter, then it is
+				// absolute. Otherwise it is relative.
+				if (localPath.startsWith("/") || localPath.startsWith("\\")
+						|| localPath.matches("[A-Za-z]:[/\\\\].*")) {
+					this.localAbsPath = localPath;
+				} else {
+					this.localAbsPath = getSleuthkitCase().getDbDirPath() + java.io.File.separator + localPath;
+				}
 			}
 			this.localPathSet = true;
 		}
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
index 847eaf467..43dc114c5 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
@@ -94,7 +94,7 @@ public class SleuthkitCase {
 	 * tsk/auto/tsk_db.h.
 	 */
 	private static final CaseDbSchemaVersionNumber CURRENT_DB_SCHEMA_VERSION
-			= new CaseDbSchemaVersionNumber(8, 2);
+			= new CaseDbSchemaVersionNumber(8, 3);
 
 	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());
@@ -862,8 +862,11 @@ private void updateDatabaseSchema(String dbPath) throws Exception {
 				dbSchemaVersion = updateFromSchema7dot2toSchema8dot0(dbSchemaVersion, connection);
 				dbSchemaVersion = updateFromSchema8dot0toSchema8dot1(dbSchemaVersion, connection);
 				dbSchemaVersion = updateFromSchema8dot1toSchema8dot2(dbSchemaVersion, connection);
+				dbSchemaVersion = updateFromSchema8dot2toSchema8dot3(dbSchemaVersion, connection);
 				statement = connection.createStatement();
 				connection.executeUpdate(statement, "UPDATE tsk_db_info SET schema_ver = " + dbSchemaVersion.getMajor() + ", schema_minor_ver = " + dbSchemaVersion.getMinor()); //NON-NLS
+				connection.executeUpdate(statement, "UPDATE tsk_db_info_extended SET value='8' WHERE name='" + SCHEMA_MAJOR_VERSION_KEY + "'");
+				connection.executeUpdate(statement, "UPDATE tsk_db_info_extended SET value='3' WHERE name='" + SCHEMA_MINOR_VERSION_KEY + "'");
 				statement.close();
 				statement = null;
 			}
@@ -1666,6 +1669,45 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot1toSchema8dot2(CaseDbSchem
 			releaseSingleUserCaseWriteLock();
 		}
 	}
+	
+	/**
+	 * Updates a schema version 8.2 database to a schema version 8.3 database.
+	 *
+	 * @param schemaVersion The current schema version of the database.
+	 * @param connection    A connection to the case database.
+	 *
+	 * @return The new database schema version.
+	 *
+	 * @throws SQLException     If there is an error completing a database
+	 *                          operation.
+	 * @throws TskCoreException If there is an error completing a database
+	 *                          operation via another SleuthkitCase method.
+	 */
+	private CaseDbSchemaVersionNumber updateFromSchema8dot2toSchema8dot3(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
+		if (schemaVersion.getMajor() != 8) {
+			return schemaVersion;
+		}
+
+		if (schemaVersion.getMinor() != 2) {
+			return schemaVersion;
+		}
+		Statement statement = connection.createStatement();
+		acquireSingleUserCaseWriteLock();
+		try {
+
+			// Fix typo in 8.2 Sqlite databases
+			statement.execute("UPDATE tsk_db_info_extended SET name='" + CREATION_SCHEMA_MAJOR_VERSION_KEY + 
+					"' WHERE name='CREATED_SCHEMA_MAJOR_VERSION'");
+			statement.execute("UPDATE tsk_db_info_extended SET name='" + CREATION_SCHEMA_MINOR_VERSION_KEY + 
+					"' WHERE name='CREATED_SCHEMA_MINOR_VERSION'");
+
+			return new CaseDbSchemaVersionNumber(8, 3);
+
+		} finally {
+			closeStatement(statement);
+			releaseSingleUserCaseWriteLock();
+		}
+	}	
 
 	/**
 	 * Extract the extension from a file name.
@@ -5619,6 +5661,10 @@ public DerivedFile addDerivedFile(String fileName, String localPath,
 			boolean isFile, Content parentObj,
 			String rederiveDetails, String toolName, String toolVersion,
 			String otherDetails, TskData.EncodingType encodingType) throws TskCoreException {
+		
+		// Strip off any leading slashes from the local path (leading slashes indicate absolute paths)
+		localPath = localPath.replaceAll("^[/\\\\]+", "");
+		
 		CaseDbConnection connection = connections.getConnection();
 		acquireSingleUserCaseWriteLock();
 		try {
@@ -5744,6 +5790,10 @@ public DerivedFile updateDerivedFile(DerivedFile derivedFile, String localPath,
 			boolean isFile, String mimeType,
 			String rederiveDetails, String toolName, String toolVersion,
 			String otherDetails, TskData.EncodingType encodingType) throws TskCoreException {
+		
+		// Strip off any leading slashes from the local path (leading slashes indicate absolute paths)
+		localPath = localPath.replaceAll("^[/\\\\]+", "");
+		
 		CaseDbConnection connection = connections.getConnection();
 		acquireSingleUserCaseWriteLock();
 		ResultSet rs = null;
diff --git a/tsk/auto/db_sqlite.cpp b/tsk/auto/db_sqlite.cpp
index 2e660729a..7275689c8 100755
--- a/tsk/auto/db_sqlite.cpp
+++ b/tsk/auto/db_sqlite.cpp
@@ -266,12 +266,12 @@ int
 		return 1;
 	}
 
-	snprintf(foo, 1024, "INSERT INTO tsk_db_info_extended (name, value) VALUES ('CREATED_SCHEMA_MAJOR_VERSION', '%d');", TSK_SCHEMA_VER);
+	snprintf(foo, 1024, "INSERT INTO tsk_db_info_extended (name, value) VALUES ('CREATION_SCHEMA_MAJOR_VERSION', '%d');", TSK_SCHEMA_VER);
 	if (attempt_exec(foo, "Error adding data to tsk_db_info table: %s\n")) {
 		return 1;
 	}
 
-	snprintf(foo, 1024, "INSERT INTO tsk_db_info_extended (name, value) VALUES ('CREATED_SCHEMA_MINOR_VERSION', '%d');", TSK_SCHEMA_MINOR_VER);
+	snprintf(foo, 1024, "INSERT INTO tsk_db_info_extended (name, value) VALUES ('CREATION_SCHEMA_MINOR_VERSION', '%d');", TSK_SCHEMA_MINOR_VER);
 	if (attempt_exec(foo, "Error adding data to tsk_db_info table: %s\n")) {
 		return 1;
 	}
diff --git a/tsk/auto/tsk_db.h b/tsk/auto/tsk_db.h
index 621eec3bc..f5d4ca246 100755
--- a/tsk/auto/tsk_db.h
+++ b/tsk/auto/tsk_db.h
@@ -29,7 +29,7 @@ using std::vector;
 using std::string;
 
 #define TSK_SCHEMA_VER 8
-#define TSK_SCHEMA_MINOR_VER 2
+#define TSK_SCHEMA_MINOR_VER 3
 
 /**
  * Values for the type column in the tsk_objects table. 
-- 
GitLab