diff --git a/.travis.yml b/.travis.yml
index 4158fbd7208b94a223433c883e412b54e9671a6a..2c2bbd9d5d3f0933e4265c24b811835df2785457 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -41,6 +41,8 @@ addons:
     - gettext
     - cppunit
     - afflib
+    taps: homebrew/cask-versions
+    casks: corretto8
 
 python:
   - "2.7"
@@ -57,9 +59,12 @@ before_script:
     fi
   - if [ $TRAVIS_OS_NAME = "osx" ]; then
         export PATH=${PATH}:/usr/local/opt/gettext/bin;
+        brew uninstall java --force;
+        brew cask uninstall java --force;
     fi
 
 script:
+  - javac -version
   - ./bootstrap && ./configure --prefix=/usr && make
   - pushd bindings/java/ && ant -q dist-PostgreSQL && popd
   - make check && if [ -f "tests/test-suite.log" ];then cat tests/test-suite.log; fi ; if [ -f "unit_tests/base/test-suite.log" ];then cat unit_tests/base/test-suite.log; fi
diff --git a/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java b/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java
index 5b605f8fd80b850f4cc34ea4d02529d3c539e339..28c15e6ffb90881b3a38e6d13aae6edcd8159d32 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java
@@ -1201,18 +1201,25 @@ public enum ARTIFACT_TYPE implements SleuthkitVisitableItem {
 		TSK_WEB_CACHE (52, "TSK_WEB_CACHE",  //NON-NLS
 				bundle.getString("BlackboardArtifact.tskWebCache.text")),
 		
+		/**
+		 * A generic (timeline) event.
+		 */
+		TSK_TL_EVENT(53, "TSK_TL_EVENT", //NON-NLS
+				bundle.getString("BlackboardArtifact.tskTLEvent.text")),
+
 		/**
 		 * Indicates clipboard content
 		 */
-		TSK_CLIPBOARD_CONTENT (53, "TSK_CLIPBOARD_CONTENT",  //NON-NLS
+		TSK_CLIPBOARD_CONTENT (54, "TSK_CLIPBOARD_CONTENT",  //NON-NLS
 				bundle.getString("BlackboardArtifact.tskClipboardContent.text")),
-
+		
 		/**
-		 * A generic (timeline) event.
+		 * An associated object.
 		 */
-		TSK_TL_EVENT(53, "TSK_TL_EVENT", //NON-NLS
-				bundle.getString("BlackboardArtifact.tskTLEvent.text"));
+		TSK_ASSOCIATED_OBJECT(55, "TSK_ASSOCIATED_OBJECT", //NON-NLS
+				bundle.getString("BlackboardArtifact.tskAssociatedObject.text"));
 
+				
 		private final String label;
 		private final int typeId;
 		private final String displayName;
diff --git a/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java b/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java
index 32ee4acd81d415ffb162ff1ce1adb4326584d006..93d5f4d5ab2c6bd295aba1c3355d845bfccb3b52 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java
@@ -546,8 +546,6 @@ public String getDisplayString() {
 			}
 			break;
 			case JSON: {
-				// @TODO 5726: convert JSON string to multilevel bulleted lists 
-				// for display
 				return getValueString();
 			}
 		}
diff --git a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties
index eecf0cb0ecf49c64edb3f68e8b19e8aadb9ff5a8..846484439189f6a2aeac2afb503b8cce9797dbee 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties
+++ b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties
@@ -52,6 +52,7 @@ BlackboardArtifact.tskDownloadSource.text=Download Source
 BlackboardArtifact.tskWebCache.text=Web Cache
 BlackboardArtifact.tskClipboardContent.text=Clipboard Content
 BlackboardArtifact.shortDescriptionDate.text=at {0}
+BlackboardArtifact.tskAssociatedObject.text=Associated Object
 BlackboardAttribute.tskAccountType.text=Account Type
 BlackboardAttribute.tskUrl.text=URL
 BlackboardAttribute.tskDatetime.text=Date/Time
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
old mode 100755
new mode 100644
index c9898814d6c274c3c98230bbc3b14aaf2d19bda8..a2364cafef1f18d82d7971107cdef9cc9da6f566
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
@@ -1904,8 +1904,8 @@ private CaseDbSchemaVersionNumber updateFromSchema8dot2toSchema8dot3(CaseDbSchem
 			);
 
 			// Fix mistakenly set names in tsk_db_info_extended 
-			statement.execute("UPDATE tsk_db_info_extended SET name = 'CREATION_SCHEMA_MAJOR_VERION' WHERE name = 'CREATED_SCHEMA_MAJOR_VERSION'");
-			statement.execute("UPDATE tsk_db_info_extended SET name = 'CREATION_SCHEMA_MINOR_VERION' WHERE name = 'CREATED_SCHEMA_MINOR_VERSION'");
+			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 {
@@ -5750,37 +5750,37 @@ public FileSystem addFileSystem(long parentObjId, long imgOffset, TskData.TSK_FS
 
 	/**
 	 * Add a file system file.
-	 * 
+	 *
 	 * @param dataSourceObjId	The object id of the root data source of this
-	 *							file.
-	 * @param fsObjId		The file system object id.
-	 * @param fileName		The name of the file.
-	 * @param metaAddr		The meta address of the file.
-	 * @param metaSeq		The meta address sequence of the file.
-	 * @param attrType		The attributed type of the file.
-	 * @param attrId		The attribute id 
-	 * @param dirFlag		The allocated status from the name structure
+	 *                        file.
+	 * @param fsObjId		       The file system object id.
+	 * @param fileName		      The name of the file.
+	 * @param metaAddr		      The meta address of the file.
+	 * @param metaSeq		       The meta address sequence of the file.
+	 * @param attrType		      The attributed type of the file.
+	 * @param attrId		        The attribute id
+	 * @param dirFlag		       The allocated status from the name structure
 	 * @param metaFlags
-	 * @param size			The size of the file in bytes.
-	 * @param ctime			The changed time of the file.
-	 * @param crtime		The creation time of the file.
-	 * @param atime			The accessed time of the file
-	 * @param mtime			The modified time of the file.
-	 ** @param isFile		True, unless the file is a directory.
-	 * @param parent		The parent of the file (e.g., a virtual directory)
-	 * 
+	 * @param size			         The size of the file in bytes.
+	 * @param ctime			        The changed time of the file.
+	 * @param crtime		        The creation time of the file.
+	 * @param atime			        The accessed time of the file
+	 * @param mtime			        The modified time of the file.
+	 ** @param isFile		        True, unless the file is a directory.
+	 * @param parent		        The parent of the file (e.g., a virtual directory)
+	 *
 	 * @return Newly created file
-	 * 
-	 * @throws TskCoreException 
-	 */
-	public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId, 
-										String fileName,
-										long metaAddr, int metaSeq,
-										TSK_FS_ATTR_TYPE_ENUM attrType, int attrId,
-										TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size, 
-										long ctime, long crtime, long atime, long mtime,
-										boolean isFile, Content parent) throws TskCoreException {
-		
+	 *
+	 * @throws TskCoreException
+	 */
+	public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId,
+			String fileName,
+			long metaAddr, int metaSeq,
+			TSK_FS_ATTR_TYPE_ENUM attrType, int attrId,
+			TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size,
+			long ctime, long crtime, long atime, long mtime,
+			boolean isFile, Content parent) throws TskCoreException {
+
 		CaseDbTransaction transaction = beginTransaction();
 		Statement queryStatement = null;
 		try {
@@ -5790,9 +5790,9 @@ public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId,
 			// Insert a row for the local/logical file into the tsk_objects table.
 			// INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
 			long objectId = addObject(parent.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
-			
+
 			String parentPath;
-			
+
 			if (parent instanceof AbstractFile) {
 				AbstractFile parentFile = (AbstractFile) parent;
 				if (isRootDirectory(parentFile, transaction)) {
@@ -5803,13 +5803,13 @@ public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId,
 			} else {
 				parentPath = "/";
 			}
-	
+
 			PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE_SYSTEM_FILE);
 			statement.clearParameters();
 			statement.setLong(1, objectId);											// obj_is
 			statement.setLong(2, fsObjId);											// fs_obj_id 
 			statement.setLong(3, dataSourceObjId);									// data_source_obj_id 
-			statement.setShort(4, (short)attrType.getValue());						// attr_type
+			statement.setShort(4, (short) attrType.getValue());						// attr_type
 			statement.setInt(5, attrId);											// attr_id
 			statement.setString(6, fileName);										// name
 			statement.setLong(7, metaAddr);											// meta_addr
@@ -5822,7 +5822,7 @@ public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId,
 			statement.setShort(12, metaType.getValue());							// meta_type
 			statement.setShort(13, dirFlag.getValue());								// dir_flags
 			statement.setShort(14, metaFlags);										// meta_flags
-			statement.setLong(15,  size < 0 ? 0 : size);
+			statement.setLong(15, size < 0 ? 0 : size);
 			statement.setLong(16, ctime);
 			statement.setLong(17, crtime);
 			statement.setLong(18, atime);
@@ -5832,21 +5832,20 @@ public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId,
 			statement.setString(21, extension);
 
 			connection.executeUpdate(statement);
-			
+
 			transaction.commit();
 			transaction = null;
-			
+
 			return new org.sleuthkit.datamodel.File(this, objectId, dataSourceObjId, fsObjId,
-			attrType, attrId, fileName, metaAddr, metaSeq,
-			dirType, metaType, dirFlag, metaFlags,
-			size, ctime, crtime, atime, mtime,
-			(short)0, 0, 0, null, null, parentPath, null,
-			extension);
-			
-		} catch(SQLException ex) {
+					attrType, attrId, fileName, metaAddr, metaSeq,
+					dirType, metaType, dirFlag, metaFlags,
+					size, ctime, crtime, atime, mtime,
+					(short) 0, 0, 0, null, null, parentPath, null,
+					extension);
+
+		} catch (SQLException ex) {
 			logger.log(Level.WARNING, "Failed to add file system file", ex);
-		} 
-		finally {
+		} finally {
 			closeStatement(queryStatement);
 			if (null != transaction) {
 				try {
@@ -7897,6 +7896,43 @@ public void setImagePaths(long obj_id, List<String> paths) throws TskCoreExcepti
 		}
 	}
 
+	/**
+	 * Deletes a datasource from the open case, the database has foreign keys
+	 * with a delete cascade so that all the tables that have a datasource
+	 * object id will have their data deleted. This is private to keep it out of
+	 * the public API
+	 *
+	 * @param dataSourceObjectId the id of the datasource to be deleted
+	 *
+	 * @throws TskCoreException exception thrown when critical error occurs
+	 *                          within tsk core and the update fails
+	 */
+	void deleteDataSource(long dataSourceObjectId) throws TskCoreException {
+		CaseDbConnection connection = connections.getConnection();
+		Statement statement = null;
+		acquireSingleUserCaseWriteLock();
+		try {
+			statement = connection.createStatement();
+			connection.beginTransaction();
+			// The following delete(s) uses a foreign key delete with cascade in the DB so that it will delete
+			// all associated rows from tsk_object and its children.  For large data sources this may take some time.
+			statement.execute("DELETE FROM tsk_objects WHERE obj_id = " + dataSourceObjectId);
+			// The following delete uses a foreign key delete with cascade in the DB so that it will delete all
+			// associated rows from accounts table and its children.
+			String accountSql = "DELETE FROM accounts WHERE account_id in (SELECT account_id FROM accounts "
+					+ "WHERE account_id NOT IN (SELECT account1_id FROM account_relationships) "
+					+ "AND account_id NOT IN (SELECT account2_id FROM account_relationships))";
+			statement.execute(accountSql);
+			connection.commitTransaction();
+		} catch (SQLException ex) {
+			connection.rollbackTransaction();
+			throw new TskCoreException("Error deleting data source.", ex);
+		} finally {
+			connection.close();
+			releaseSingleUserCaseWriteLock();
+		}
+	}
+
 	/**
 	 * Creates file object from a SQL query result set of rows from the
 	 * tsk_files table. Assumes that the query was of the form "SELECT * FROM
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCaseAdminUtil.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCaseAdminUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..58b4ffcd22a367b00714289f39734fb2947883c7
--- /dev/null
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCaseAdminUtil.java
@@ -0,0 +1,44 @@
+/*
+ * Sleuth Kit Data Model
+ *
+ * Copyright 2019 Basis Technology Corp.
+ * Contact: carrier <at> sleuthkit <dot> org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *	 http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.datamodel;
+
+/**
+ * Utility methods for administering a case database.
+ */
+public final class SleuthkitCaseAdminUtil {
+
+	/**
+	 * Deletes a data source from a case database.
+	 *
+	 * @param caseDB          The case database.
+	 * @param dataSourceObjID The object ID of the data source to be deleted.
+	 *
+	 * @throws TskCoreException If there is an error deleting the data source.
+	 */
+	public static void deleteDataSource(SleuthkitCase caseDB, long dataSourceObjID) throws TskCoreException {
+		caseDB.deleteDataSource(dataSourceObjID);
+	}
+
+	/**
+	 * Prevent instantiation of this utility class.
+	 */
+	private SleuthkitCaseAdminUtil() {
+	}
+
+}
diff --git a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/Attachment.java b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/Attachment.java
new file mode 100644
index 0000000000000000000000000000000000000000..bf25c914474d21ff0039508e382612a3964023d7
--- /dev/null
+++ b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/Attachment.java
@@ -0,0 +1,42 @@
+/*
+ * Sleuth Kit Data Model
+ *
+ * Copyright 2019 Basis Technology Corp.
+ * Contact: carrier <at> sleuthkit <dot> org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.datamodel.blackboardutils;
+
+/**
+ *
+ * An interface implemented by message attachments.
+ */
+public interface Attachment {
+
+	/**
+	 * Returns location of an attachment - a path or a URL.
+	 *
+	 * @return String representing location of attachment.
+	 */
+	String getLocation();
+
+	/*
+	 * Returns object id of the attachment file.
+	 *
+	 * @return Object id of attachment, may be null if not available or
+	 * not applicable.
+	 */
+	Long getObjId();
+
+}
diff --git a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/CommunicationArtifactsHelper.java b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/CommunicationArtifactsHelper.java
index 704d18b32b3761d1c9cfc5b04b729c9ec2e62dfb..67da88f133d3145fd76de1be5a522cee12549d63 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/CommunicationArtifactsHelper.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/CommunicationArtifactsHelper.java
@@ -756,7 +756,7 @@ public BlackboardArtifact addCalllog(CommunicationDirection direction,
 	/**
 	 * Adds attachments to a message.
 	 *
-	 * @param message     Message artifact
+	 * @param message     Message artifact.
 	 * @param attachments Attachments to add to the message.
 	 *
 	 * @throws TskCoreException If there is an error in adding attachments
@@ -770,10 +770,38 @@ public void addAttachments(BlackboardArtifact message, MessageAttachments attach
 		// Create attribute 
 		message.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ATTACHMENTS, getModuleName(), attachmentsJson));
 
-		// @TODO 5698: create a TSK_ASSOCIATED_OBJECT artifact for each fileAttachment 
-		//             to associate the file with the message.
+		// Associate each attachment file with the message.
+		Collection<FileAttachment> fileAttachments = attachments.getFileAttachments();
+		for (FileAttachment fileAttachment : fileAttachments) {
+			long attachedFileObjId = fileAttachment.getObjectId();
+			if (attachedFileObjId >= 0) {
+				AbstractFile attachedFile = message.getSleuthkitCase().getAbstractFileById(attachedFileObjId);
+				associateAttachmentWithMesssge(message, attachedFile);
+			}
+		}
 	}
 
+	/**
+	 * Creates a TSK_ASSOCIATED_OBJECT artifact between the attachment file and
+	 * the message.
+	 *
+	 * @param message     Message artifact.
+	 * @param attachments Attachment file.
+	 *
+	 * @return TSK_ASSOCIATED_OBJECT artifact.
+	 *
+	 * @throws TskCoreException If there is an error creating the
+	 *                          TSK_ASSOCIATED_OBJECT artifact.
+	 */
+	private BlackboardArtifact associateAttachmentWithMesssge(BlackboardArtifact message, AbstractFile attachedFile) throws TskCoreException {
+		Collection<BlackboardAttribute> attributes = new ArrayList<>();
+		attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, this.getModuleName(), message.getArtifactID()));
+
+		BlackboardArtifact bba = attachedFile.newArtifact(ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT);
+		bba.addAttributes(attributes); //write out to bb
+		return bba;
+	}
+	
 	/**
 	 * Converts a list of ids into a single comma separated string.
 	 */
diff --git a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/FileAttachment.java b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/FileAttachment.java
index af0277b86b30f1cb50b3e4265474815426ab8955..0f6ee4c340ad7845d220af939b84ebf5a0fb0632 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/FileAttachment.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/FileAttachment.java
@@ -37,7 +37,7 @@
  * file.
  *
  */
-public final class FileAttachment {
+public final class FileAttachment implements Attachment {
 
 	private final String filePathName;
 	private final long objId;
@@ -103,6 +103,15 @@ public FileAttachment(DerivedFile derivedFile) {
 		filePathName = derivedFile.getLocalAbsPath() + "/" + derivedFile.getName();
 	}
 
+	/**
+	 * Creates a file attachment from a file.
+	 *
+	 * @param abstractFile Abstract file for attachment..
+	 */
+	public FileAttachment(AbstractFile abstractFile) {
+		objId = abstractFile.getId();
+		filePathName = abstractFile.getParentPath() + "/" + abstractFile.getName();
+	}
 
 	/**
 	 * Returns the full path name of the file.
@@ -132,8 +141,8 @@ public long getObjectId() {
 	 * @return normalized path.
 	 */
 	private String normalizePath(String path) {
-		//normalize the slashes.
-		String adjustedPath = path.replace("\\", "/");
+		//normalize the slashes, replace encoded space
+		String adjustedPath = path.replace("\\", "/").replace("%20"," ");
 
 		// Strip common known mountpoints.
 		for (String mountPoint : KNOWN_MOUNTPOINTS) {
@@ -145,4 +154,14 @@ private String normalizePath(String path) {
 
 		return adjustedPath;
 	}
+
+	@Override
+	public String getLocation() {
+		return this.filePathName;
+	}
+
+	@Override
+	public Long getObjId() {
+		return this.objId;
+	}
 }
diff --git a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/MessageAttachments.java b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/MessageAttachments.java
index 174d3c322a5e4d6c29791cfaea69960c615df4aa..718a5b56b30e5a92f40fd202e0bea92bba474566 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/MessageAttachments.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/MessageAttachments.java
@@ -62,4 +62,12 @@ public Collection<URLAttachment> getUrlAttachments() {
 		return Collections.unmodifiableCollection(urlAttachments);
 	}
 
+	/**
+	 * Returns total count of attachments.
+	 * 
+	 * @return Count of attachments.
+	 */
+	public int getAttachmentsCount() {
+		return (fileAttachments.size() + urlAttachments.size());
+	}
 }
diff --git a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/URLAttachment.java b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/URLAttachment.java
index 0cecda68c01bd1ecbe7abd2c1f7765cec105c88f..99207b777c317e954ee77b74d8e3b32a032e872c 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/URLAttachment.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/blackboardutils/URLAttachment.java
@@ -22,7 +22,7 @@
  * Represents a message attachment where a URL of the attachment is available.
  *
  */
-public class URLAttachment {
+public class URLAttachment implements Attachment {
 
 	private final String url;
 
@@ -44,4 +44,15 @@ public String getURL() {
 		return url;
 	}
 
+	@Override
+	public String getLocation() {
+		return this.url;
+	}
+
+	@Override
+	public Long getObjId() {
+		// no real object available. 
+		return null;
+	}
+
 }
diff --git a/tsk/auto/db_postgresql.cpp b/tsk/auto/db_postgresql.cpp
index 83653cf7b9b7b2ac695fbc8cbcf5ae3695deed60..d65e470e977d40d33db0a5567179d89711e6fa9a 100755
--- a/tsk/auto/db_postgresql.cpp
+++ b/tsk/auto/db_postgresql.cpp
@@ -526,40 +526,40 @@ int TskDbPostgreSQL::initialize() {
 
     // ELTODO: change INTEGER (4 bytes) fields to SMALLINT (2 bytes) to use less memory for enum fields
 
-	if (attempt_exec("CREATE TABLE tsk_objects (obj_id BIGSERIAL PRIMARY KEY, par_obj_id BIGINT, type INTEGER NOT NULL);", "Error creating tsk_objects table: %s\n")
+    if (attempt_exec("CREATE TABLE tsk_objects (obj_id BIGSERIAL PRIMARY KEY, par_obj_id BIGINT, type INTEGER NOT NULL, FOREIGN KEY (par_obj_id) REFERENCES tsk_objects (obj_id) ON DELETE CASCADE);","Error creating tsk_objects table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE tsk_image_info (obj_id BIGSERIAL PRIMARY KEY, type INTEGER, ssize INTEGER, tzone TEXT, size BIGINT, md5 TEXT, sha1 TEXT, sha256 TEXT, display_name TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        ("CREATE TABLE tsk_image_info (obj_id BIGSERIAL PRIMARY KEY, type INTEGER, ssize INTEGER, tzone TEXT, size BIGINT, md5 TEXT, sha1 TEXT, sha256 TEXT, display_name TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
             "Error creating tsk_image_info table: %s\n")
         ||
-        attempt_exec("CREATE TABLE tsk_image_names (obj_id BIGINT NOT NULL, name TEXT NOT NULL, sequence INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        attempt_exec("CREATE TABLE tsk_image_names (obj_id BIGINT NOT NULL, name TEXT NOT NULL, sequence INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
             "Error creating tsk_image_names table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE tsk_vs_info (obj_id BIGSERIAL PRIMARY KEY, vs_type INTEGER NOT NULL, img_offset BIGINT NOT NULL, block_size BIGINT NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        ("CREATE TABLE tsk_vs_info (obj_id BIGSERIAL PRIMARY KEY, vs_type INTEGER NOT NULL, img_offset BIGINT NOT NULL, block_size BIGINT NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
             "Error creating tsk_vs_info table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE data_source_info (obj_id BIGINT PRIMARY KEY, device_id TEXT NOT NULL, time_zone TEXT NOT NULL, acquisition_details TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        ("CREATE TABLE data_source_info (obj_id BIGINT PRIMARY KEY, device_id TEXT NOT NULL, time_zone TEXT NOT NULL, acquisition_details TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
             "Error creating data_source_info table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE tsk_fs_info (obj_id BIGSERIAL PRIMARY KEY, img_offset BIGINT NOT NULL, fs_type INTEGER NOT NULL, block_size BIGINT NOT NULL, block_count BIGINT NOT NULL, root_inum BIGINT NOT NULL, first_inum BIGINT NOT NULL, last_inum BIGINT NOT NULL, display_name TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        ("CREATE TABLE tsk_fs_info (obj_id BIGSERIAL PRIMARY KEY, img_offset BIGINT NOT NULL, fs_type INTEGER NOT NULL, block_size BIGINT NOT NULL, block_count BIGINT NOT NULL, root_inum BIGINT NOT NULL, first_inum BIGINT NOT NULL, last_inum BIGINT NOT NULL, display_name TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
             "Error creating tsk_fs_info table: %s\n")
         ||
         attempt_exec
         ("CREATE TABLE tsk_files (obj_id BIGSERIAL PRIMARY KEY, fs_obj_id BIGINT, data_source_obj_id BIGINT NOT NULL, attr_type INTEGER, attr_id INTEGER, name TEXT NOT NULL, meta_addr BIGINT, meta_seq BIGINT, type INTEGER, has_layout INTEGER, has_path INTEGER, dir_type INTEGER, meta_type INTEGER, dir_flags INTEGER, meta_flags INTEGER, size BIGINT, ctime BIGINT, crtime BIGINT, atime BIGINT, mtime BIGINT, mode INTEGER, uid INTEGER, gid INTEGER, md5 TEXT, known INTEGER, parent_path TEXT, mime_type TEXT, extension TEXT, "
-            "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id), FOREIGN KEY(fs_obj_id) REFERENCES tsk_fs_info(obj_id), FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id));",
+            "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, FOREIGN KEY(fs_obj_id) REFERENCES tsk_fs_info(obj_id) ON DELETE CASCADE, FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id) ON DELETE CASCADE);",
             "Error creating tsk_files table: %s\n")
         ||
         attempt_exec
         ("CREATE TABLE file_encoding_types (encoding_type INTEGER PRIMARY KEY, name TEXT NOT NULL);",
             "Error creating file_encoding_types table: %s\n")
         ||
-        attempt_exec("CREATE TABLE tsk_files_path (obj_id BIGSERIAL PRIMARY KEY, path TEXT NOT NULL, encoding_type INTEGER, FOREIGN KEY(encoding_type) references file_encoding_types(encoding_type), FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id))",
+        attempt_exec("CREATE TABLE tsk_files_path (obj_id BIGSERIAL PRIMARY KEY, path TEXT NOT NULL, encoding_type INTEGER, FOREIGN KEY(encoding_type) references file_encoding_types(encoding_type), FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)",
             "Error creating tsk_files_path table: %s\n")
         ||
-        attempt_exec("CREATE TABLE tsk_files_derived (obj_id BIGSERIAL PRIMARY KEY, derived_id BIGINT NOT NULL, rederive TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id))", "Error creating tsk_files_derived table: %s\n")
+        attempt_exec("CREATE TABLE tsk_files_derived (obj_id BIGSERIAL PRIMARY KEY, derived_id BIGINT NOT NULL, rederive TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)", "Error creating tsk_files_derived table: %s\n")
         ||
         attempt_exec("CREATE TABLE tsk_files_derived_method (derived_id BIGSERIAL PRIMARY KEY, tool_name TEXT NOT NULL, tool_version TEXT NOT NULL, other TEXT)", "Error creating tsk_files_derived_method table: %s\n")
         ||
@@ -580,9 +580,9 @@ int TskDbPostgreSQL::initialize() {
             "data_source_obj_id BIGINT NOT NULL, "
             "artifact_type_id BIGINT NOT NULL, "
             "review_status_id INTEGER NOT NULL, "
-            "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id), "
-            "FOREIGN KEY(artifact_obj_id) REFERENCES tsk_objects(obj_id), "
-            "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id), "
+            "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
+            "FOREIGN KEY(artifact_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
+            "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
             "FOREIGN KEY(artifact_type_id) REFERENCES blackboard_artifact_types(artifact_type_id), "
             "FOREIGN KEY(review_status_id) REFERENCES review_statuses(review_status_id))",
             "Error creating blackboard_artifact table: %s\n")
@@ -596,12 +596,12 @@ int TskDbPostgreSQL::initialize() {
         attempt_exec
         ("CREATE TABLE blackboard_attributes (artifact_id BIGINT NOT NULL, artifact_type_id BIGINT NOT NULL, source TEXT, context TEXT, attribute_type_id BIGINT NOT NULL, value_type INTEGER NOT NULL, "
             "value_byte BYTEA, value_text TEXT, value_int32 INTEGER, value_int64 BIGINT, value_double NUMERIC(20, 10), "
-            "FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id), FOREIGN KEY(artifact_type_id) REFERENCES blackboard_artifact_types(artifact_type_id), FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))",
+            "FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE, FOREIGN KEY(artifact_type_id) REFERENCES blackboard_artifact_types(artifact_type_id), FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))",
             "Error creating blackboard_attribute table: %s\n")
         ||
         /* In PostgreSQL "desc" indicates "descending order" so I had to rename "desc TEXT" to "descr TEXT". Should I also make this change for SQLite?*/
         attempt_exec
-        ("CREATE TABLE tsk_vs_parts (obj_id BIGSERIAL PRIMARY KEY, addr BIGINT NOT NULL, start BIGINT NOT NULL, length BIGINT NOT NULL, descr TEXT, flags INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        ("CREATE TABLE tsk_vs_parts (obj_id BIGSERIAL PRIMARY KEY, addr BIGINT NOT NULL, start BIGINT NOT NULL, length BIGINT NOT NULL, descr TEXT, flags INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
             "Error creating tsk_vol_info table: %s\n")
         ||
         attempt_exec
@@ -613,19 +613,19 @@ int TskDbPostgreSQL::initialize() {
             "Error creating ingest_job_status_types table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE ingest_modules (ingest_module_id BIGSERIAL PRIMARY KEY, display_name TEXT NOT NULL, unique_name TEXT UNIQUE NOT NULL, type_id INTEGER NOT NULL, version TEXT NOT NULL, FOREIGN KEY(type_id) REFERENCES ingest_module_types(type_id));",
+        ("CREATE TABLE ingest_modules (ingest_module_id BIGSERIAL PRIMARY KEY, display_name TEXT NOT NULL, unique_name TEXT UNIQUE NOT NULL, type_id INTEGER NOT NULL, version TEXT NOT NULL, FOREIGN KEY(type_id) REFERENCES ingest_module_types(type_id) ON DELETE CASCADE);",
             "Error creating ingest_modules table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE ingest_jobs (ingest_job_id BIGSERIAL PRIMARY KEY, obj_id BIGINT NOT NULL, host_name TEXT NOT NULL, start_date_time BIGINT NOT NULL, end_date_time BIGINT NOT NULL, status_id INTEGER NOT NULL, settings_dir TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id), FOREIGN KEY(status_id) REFERENCES ingest_job_status_types(type_id));",
+        ("CREATE TABLE ingest_jobs (ingest_job_id BIGSERIAL PRIMARY KEY, obj_id BIGINT NOT NULL, host_name TEXT NOT NULL, start_date_time BIGINT NOT NULL, end_date_time BIGINT NOT NULL, status_id INTEGER NOT NULL, settings_dir TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, FOREIGN KEY(status_id) REFERENCES ingest_job_status_types(type_id) ON DELETE CASCADE);",
             "Error creating ingest_jobs table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE ingest_job_modules (ingest_job_id INTEGER, ingest_module_id INTEGER, pipeline_position INTEGER, PRIMARY KEY(ingest_job_id, ingest_module_id), FOREIGN KEY(ingest_job_id) REFERENCES ingest_jobs(ingest_job_id), FOREIGN KEY(ingest_module_id) REFERENCES ingest_modules(ingest_module_id));",
+        ("CREATE TABLE ingest_job_modules (ingest_job_id INTEGER, ingest_module_id INTEGER, pipeline_position INTEGER, PRIMARY KEY(ingest_job_id, ingest_module_id), FOREIGN KEY(ingest_job_id) REFERENCES ingest_jobs(ingest_job_id) ON DELETE CASCADE, FOREIGN KEY(ingest_module_id) REFERENCES ingest_modules(ingest_module_id) ON DELETE CASCADE);",
             "Error creating ingest_job_modules table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE reports (obj_id BIGSERIAL PRIMARY KEY, path TEXT NOT NULL, crtime INTEGER NOT NULL, src_module_name TEXT NOT NULL, report_name TEXT NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));", "Error creating reports table: %s\n")
+        ("CREATE TABLE reports (obj_id BIGSERIAL PRIMARY KEY, path TEXT NOT NULL, crtime INTEGER NOT NULL, src_module_name TEXT NOT NULL, report_name TEXT NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);", "Error creating reports table: %s\n")
         ||
         attempt_exec
         ("CREATE TABLE account_types (account_type_id BIGSERIAL PRIMARY KEY, type_name TEXT UNIQUE NOT NULL, display_name TEXT NOT NULL)",
@@ -636,7 +636,7 @@ int TskDbPostgreSQL::initialize() {
             "Error creating accounts table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE account_relationships  (relationship_id BIGSERIAL PRIMARY KEY, account1_id INTEGER NOT NULL, account2_id INTEGER NOT NULL, relationship_source_obj_id BIGINT NOT NULL, date_time BIGINT, relationship_type INTEGER NOT NULL, data_source_obj_id BIGINT NOT NULL, UNIQUE(account1_id, account2_id, relationship_source_obj_id), FOREIGN KEY(account1_id) REFERENCES accounts(account_id), FOREIGN KEY(account2_id) REFERENCES accounts(account_id), FOREIGN KEY(relationship_source_obj_id) REFERENCES tsk_objects(obj_id), FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id))",
+        ("CREATE TABLE account_relationships  (relationship_id BIGSERIAL PRIMARY KEY, account1_id INTEGER NOT NULL, account2_id INTEGER NOT NULL, relationship_source_obj_id BIGINT NOT NULL, date_time BIGINT, relationship_type INTEGER NOT NULL, data_source_obj_id BIGINT NOT NULL, UNIQUE(account1_id, account2_id, relationship_source_obj_id), FOREIGN KEY(account1_id) REFERENCES accounts(account_id), FOREIGN KEY(account2_id) REFERENCES accounts(account_id), FOREIGN KEY(relationship_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)",
             "Error creating relationships table: %s\n")
         ||
         attempt_exec(
@@ -679,9 +679,9 @@ int TskDbPostgreSQL::initialize() {
             " artifact_id BIGINT, "
             " hash_hit INTEGER NOT NULL, " //boolean 
             " tagged INTEGER NOT NULL, " //boolean 
-            " FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id), "
-            " FOREIGN KEY(content_obj_id) REFERENCES tsk_objects(obj_id), "
-            " FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ,"
+            " FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id) ON DELETE CASCADE, "
+            " FOREIGN KEY(content_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
+            " FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE,"
 			" UNIQUE (full_description, content_obj_id, artifact_id))",
             "Error creating tsk_event_descriptions table: %s\n")
         ||
@@ -689,7 +689,7 @@ int TskDbPostgreSQL::initialize() {
             "CREATE TABLE tsk_events ("
             " event_id BIGSERIAL PRIMARY KEY, "
             " event_type_id BIGINT NOT NULL REFERENCES tsk_event_types(event_type_id) ,"
-            " event_description_id BIGINT NOT NULL REFERENCES tsk_event_descriptions(event_description_id) ,"
+            " event_description_id BIGINT NOT NULL REFERENCES tsk_event_descriptions(event_description_id) ON DELETE CASCADE ,"
             " time BIGINT NOT NULL , "
 			" UNIQUE (event_type_id, event_description_id, time))"
             , "Error creating tsk_events table: %s\n")
@@ -700,18 +700,18 @@ int TskDbPostgreSQL::initialize() {
         ||
         attempt_exec
         ("CREATE TABLE content_tags (tag_id BIGSERIAL PRIMARY KEY, obj_id BIGINT NOT NULL, tag_name_id BIGINT NOT NULL, comment TEXT NOT NULL, begin_byte_offset BIGINT NOT NULL, end_byte_offset BIGINT NOT NULL, examiner_id BIGINT, "
-            "FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id), FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id), FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id))",
+            "FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id), FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id))",
             "Error creating content_tags table: %s\n")
         ||
         attempt_exec
         ("CREATE TABLE blackboard_artifact_tags (tag_id BIGSERIAL PRIMARY KEY, artifact_id BIGINT NOT NULL, tag_name_id BIGINT NOT NULL, comment TEXT NOT NULL,  examiner_id BIGINT, "
-            "FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id), FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id), FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id))",
+            "FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id), FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE, FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id))",
             "Error creating blackboard_artifact_tags table: %s\n")){
 		return 1;
 	}
 
     if (attempt_exec
-        ("CREATE TABLE tsk_file_layout (obj_id BIGINT NOT NULL, byte_start BIGINT NOT NULL, byte_len BIGINT NOT NULL, sequence INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        ("CREATE TABLE tsk_file_layout (obj_id BIGINT NOT NULL, byte_start BIGINT NOT NULL, byte_len BIGINT NOT NULL, sequence INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
         "Error creating tsk_fs_blocks table: %s\n")) {
             return 1;
     }
diff --git a/tsk/auto/db_sqlite.cpp b/tsk/auto/db_sqlite.cpp
index 3f5d1598ad241130992ec531d37e466c85136938..ae41c8fd9c554eeded5e93b39113277f911151f2 100755
--- a/tsk/auto/db_sqlite.cpp
+++ b/tsk/auto/db_sqlite.cpp
@@ -284,36 +284,36 @@ TskDbSqlite::initialize()
 	}
 
 	if (attempt_exec
-        ("CREATE TABLE tsk_objects (obj_id INTEGER PRIMARY KEY, par_obj_id INTEGER, type INTEGER NOT NULL);",
+        ("CREATE TABLE tsk_objects (obj_id INTEGER PRIMARY KEY, par_obj_id INTEGER, type INTEGER NOT NULL, UNIQUE (obj_id), FOREIGN KEY (par_obj_id) references tsk_objects(obj_id) ON DELETE CASCADE);",
         "Error creating tsk_objects table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE tsk_image_info (obj_id INTEGER PRIMARY KEY, type INTEGER, ssize INTEGER, tzone TEXT, size INTEGER, md5 TEXT, sha1 TEXT, sha256 TEXT, display_name TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        ("CREATE TABLE tsk_image_info (obj_id INTEGER PRIMARY KEY, type INTEGER, ssize INTEGER, tzone TEXT, size INTEGER, md5 TEXT, sha1 TEXT, sha256 TEXT, display_name TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
             "Error creating tsk_image_info table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE tsk_image_names (obj_id INTEGER NOT NULL, name TEXT NOT NULL, sequence INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        ("CREATE TABLE tsk_image_names (obj_id INTEGER NOT NULL, name TEXT NOT NULL, sequence INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
             "Error creating tsk_image_names table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE tsk_vs_info (obj_id INTEGER PRIMARY KEY, vs_type INTEGER NOT NULL, img_offset INTEGER NOT NULL, block_size INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        ("CREATE TABLE tsk_vs_info (obj_id INTEGER PRIMARY KEY, vs_type INTEGER NOT NULL, img_offset INTEGER NOT NULL, block_size INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
             "Error creating tsk_vs_info table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE tsk_vs_parts (obj_id INTEGER PRIMARY KEY, addr INTEGER NOT NULL, start INTEGER NOT NULL, length INTEGER NOT NULL, desc TEXT, flags INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        ("CREATE TABLE tsk_vs_parts (obj_id INTEGER PRIMARY KEY, addr INTEGER NOT NULL, start INTEGER NOT NULL, length INTEGER NOT NULL, desc TEXT, flags INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
             "Error creating tsk_vol_info table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE tsk_fs_info (obj_id INTEGER PRIMARY KEY, img_offset INTEGER NOT NULL, fs_type INTEGER NOT NULL, block_size INTEGER NOT NULL, block_count INTEGER NOT NULL, root_inum INTEGER NOT NULL, first_inum INTEGER NOT NULL, last_inum INTEGER NOT NULL, display_name TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        ("CREATE TABLE tsk_fs_info (obj_id INTEGER PRIMARY KEY, img_offset INTEGER NOT NULL, fs_type INTEGER NOT NULL, block_size INTEGER NOT NULL, block_count INTEGER NOT NULL, root_inum INTEGER NOT NULL, first_inum INTEGER NOT NULL, last_inum INTEGER NOT NULL, display_name TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
             "Error creating tsk_fs_info table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE data_source_info (obj_id INTEGER PRIMARY KEY, device_id TEXT NOT NULL,  time_zone TEXT NOT NULL, acquisition_details TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        ("CREATE TABLE data_source_info (obj_id INTEGER PRIMARY KEY, device_id TEXT NOT NULL,  time_zone TEXT NOT NULL, acquisition_details TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
             "Error creating data_source_info table: %s\n")
         ||
         attempt_exec
         ("CREATE TABLE tsk_files (obj_id INTEGER PRIMARY KEY, fs_obj_id INTEGER, data_source_obj_id INTEGER NOT NULL, attr_type INTEGER, attr_id INTEGER, name TEXT NOT NULL, meta_addr INTEGER, meta_seq INTEGER, type INTEGER, has_layout INTEGER, has_path INTEGER, dir_type INTEGER, meta_type INTEGER, dir_flags INTEGER, meta_flags INTEGER, size INTEGER, ctime INTEGER, crtime INTEGER, atime INTEGER, mtime INTEGER, mode INTEGER, uid INTEGER, gid INTEGER, md5 TEXT, known INTEGER, parent_path TEXT, mime_type TEXT, extension TEXT , "
-            "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id), FOREIGN KEY(fs_obj_id) REFERENCES tsk_fs_info(obj_id), FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id));",
+            "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, FOREIGN KEY(fs_obj_id) REFERENCES tsk_fs_info(obj_id) ON DELETE CASCADE, FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id) ON DELETE CASCADE);",
             "Error creating tsk_files table: %s\n")
         ||
         attempt_exec
@@ -321,11 +321,11 @@ TskDbSqlite::initialize()
             "Error creating file_encoding_types table: %s\n")
         ||
         attempt_exec(
-            "CREATE TABLE tsk_files_path (obj_id INTEGER PRIMARY KEY, path TEXT NOT NULL, encoding_type INTEGER NOT NULL, FOREIGN KEY(encoding_type) references file_encoding_types(encoding_type), FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id))",
+            "CREATE TABLE tsk_files_path (obj_id INTEGER PRIMARY KEY, path TEXT NOT NULL, encoding_type INTEGER NOT NULL, FOREIGN KEY(encoding_type) references file_encoding_types(encoding_type), FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)",
             "Error creating tsk_files_path table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE tsk_files_derived (obj_id INTEGER PRIMARY KEY, derived_id INTEGER NOT NULL, rederive TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id))",
+        ("CREATE TABLE tsk_files_derived (obj_id INTEGER PRIMARY KEY, derived_id INTEGER NOT NULL, rederive TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)",
             "Error creating tsk_files_derived table: %s\n")
         ||
         attempt_exec
@@ -348,9 +348,9 @@ TskDbSqlite::initialize()
             "data_source_obj_id INTEGER NOT NULL, "
             "artifact_type_id INTEGER NOT NULL, "
             "review_status_id INTEGER NOT NULL, "
-            "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id), "
-            "FOREIGN KEY(artifact_obj_id) REFERENCES tsk_objects(obj_id), "
-            "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id), "
+            "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
+            "FOREIGN KEY(artifact_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
+            "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
             "FOREIGN KEY(artifact_type_id) REFERENCES blackboard_artifact_types(artifact_type_id), "
             "FOREIGN KEY(review_status_id) REFERENCES review_statuses(review_status_id))",
             "Error creating blackboard_artifact table: %s\n")
@@ -358,7 +358,7 @@ TskDbSqlite::initialize()
         attempt_exec
         ("CREATE TABLE blackboard_attributes (artifact_id INTEGER NOT NULL, artifact_type_id INTEGER NOT NULL, source TEXT, context TEXT, attribute_type_id INTEGER NOT NULL, value_type INTEGER NOT NULL, "
             "value_byte BLOB, value_text TEXT, value_int32 INTEGER, value_int64 INTEGER, value_double NUMERIC(20, 10), "
-            "FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id), FOREIGN KEY(artifact_type_id) REFERENCES blackboard_artifact_types(artifact_type_id), FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))",
+            "FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE, FOREIGN KEY(artifact_type_id) REFERENCES blackboard_artifact_types(artifact_type_id), FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))",
             "Error creating blackboard_attribute table: %s\n")
         ||
         attempt_exec
@@ -378,19 +378,19 @@ TskDbSqlite::initialize()
             "Error creating ingest_job_status_types table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE ingest_modules (ingest_module_id INTEGER PRIMARY KEY, display_name TEXT NOT NULL, unique_name TEXT UNIQUE NOT NULL, type_id INTEGER NOT NULL, version TEXT NOT NULL, FOREIGN KEY(type_id) REFERENCES ingest_module_types(type_id));",
+        ("CREATE TABLE ingest_modules (ingest_module_id INTEGER PRIMARY KEY, display_name TEXT NOT NULL, unique_name TEXT UNIQUE NOT NULL, type_id INTEGER NOT NULL, version TEXT NOT NULL, FOREIGN KEY(type_id) REFERENCES ingest_module_types(type_id) ON DELETE CASCADE);",
             "Error creating ingest_modules table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE ingest_jobs (ingest_job_id INTEGER PRIMARY KEY, obj_id INTEGER NOT NULL, host_name TEXT NOT NULL, start_date_time INTEGER NOT NULL, end_date_time INTEGER NOT NULL, status_id INTEGER NOT NULL, settings_dir TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id), FOREIGN KEY(status_id) REFERENCES ingest_job_status_types(type_id));",
+        ("CREATE TABLE ingest_jobs (ingest_job_id INTEGER PRIMARY KEY, obj_id INTEGER NOT NULL, host_name TEXT NOT NULL, start_date_time INTEGER NOT NULL, end_date_time INTEGER NOT NULL, status_id INTEGER NOT NULL, settings_dir TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, FOREIGN KEY(status_id) REFERENCES ingest_job_status_types(type_id) ON DELETE CASCADE);",
             "Error creating ingest_jobs table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE ingest_job_modules (ingest_job_id INTEGER, ingest_module_id INTEGER, pipeline_position INTEGER, PRIMARY KEY(ingest_job_id, ingest_module_id), FOREIGN KEY(ingest_job_id) REFERENCES ingest_jobs(ingest_job_id), FOREIGN KEY(ingest_module_id) REFERENCES ingest_modules(ingest_module_id));",
+        ("CREATE TABLE ingest_job_modules (ingest_job_id INTEGER, ingest_module_id INTEGER, pipeline_position INTEGER, PRIMARY KEY(ingest_job_id, ingest_module_id), FOREIGN KEY(ingest_job_id) REFERENCES ingest_jobs(ingest_job_id) ON DELETE CASCADE, FOREIGN KEY(ingest_module_id) REFERENCES ingest_modules(ingest_module_id) ON DELETE CASCADE);",
             "Error creating ingest_job_modules table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE reports (obj_id INTEGER PRIMARY KEY, path TEXT NOT NULL, crtime INTEGER NOT NULL, src_module_name TEXT NOT NULL, report_name TEXT NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        ("CREATE TABLE reports (obj_id INTEGER PRIMARY KEY, path TEXT NOT NULL, crtime INTEGER NOT NULL, src_module_name TEXT NOT NULL, report_name TEXT NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
             "Error creating reports table: %s\n")
         ||
         attempt_exec
@@ -402,7 +402,7 @@ TskDbSqlite::initialize()
             "Error creating accounts table: %s\n")
         ||
         attempt_exec
-        ("CREATE TABLE account_relationships (relationship_id INTEGER PRIMARY KEY, account1_id INTEGER NOT NULL, account2_id INTEGER NOT NULL, relationship_source_obj_id INTEGER NOT NULL,  date_time INTEGER, relationship_type INTEGER NOT NULL, data_source_obj_id INTEGER NOT NULL, UNIQUE(account1_id, account2_id, relationship_source_obj_id), FOREIGN KEY(account1_id) REFERENCES accounts(account_id), FOREIGN KEY(account2_id) REFERENCES accounts(account_id), FOREIGN KEY(relationship_source_obj_id) REFERENCES tsk_objects(obj_id), FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id))",
+        ("CREATE TABLE account_relationships (relationship_id INTEGER PRIMARY KEY, account1_id INTEGER NOT NULL, account2_id INTEGER NOT NULL, relationship_source_obj_id INTEGER NOT NULL,  date_time INTEGER, relationship_type INTEGER NOT NULL, data_source_obj_id INTEGER NOT NULL, UNIQUE(account1_id, account2_id, relationship_source_obj_id), FOREIGN KEY(account1_id) REFERENCES accounts(account_id), FOREIGN KEY(account2_id) REFERENCES accounts(account_id), FOREIGN KEY(relationship_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)",
             "Error creating relationships table: %s\n")
         ||
         attempt_exec(
@@ -441,9 +441,9 @@ TskDbSqlite::initialize()
 	        " full_description TEXT NOT NULL, "
 	        " med_description TEXT, "
 	        " short_description TEXT,"
-	        " data_source_obj_id INTEGER NOT NULL REFERENCES data_source_info(obj_id), "
-	        " content_obj_id INTEGER NOT NULL REFERENCES tsk_objects(obj_id), "
-	        " artifact_id INTEGER REFERENCES blackboard_artifacts(artifact_id), "
+	        " data_source_obj_id INTEGER NOT NULL REFERENCES data_source_info(obj_id) ON DELETE CASCADE, "
+	        " content_obj_id INTEGER NOT NULL REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
+	        " artifact_id INTEGER REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE, "
 	        " hash_hit INTEGER NOT NULL, " //boolean 
 	        " tagged INTEGER NOT NULL, " //boolean 
 			" UNIQUE (full_description, content_obj_id, artifact_id))",
@@ -453,7 +453,7 @@ TskDbSqlite::initialize()
 	        "CREATE TABLE 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 tsk_event_descriptions(event_description_id) ,"
+	        " event_description_id BIGINT NOT NULL REFERENCES tsk_event_descriptions(event_description_id) ON DELETE CASCADE ,"
 	        " time BIGINT NOT NULL , "
 			" UNIQUE (event_type_id, event_description_id, time))"
 	        , "Error creating tsk_events table: %s\n")
@@ -465,18 +465,18 @@ TskDbSqlite::initialize()
         ||
 		attempt_exec
 		("CREATE TABLE content_tags (tag_id INTEGER PRIMARY KEY, obj_id INTEGER NOT NULL, tag_name_id INTEGER NOT NULL, comment TEXT NOT NULL, begin_byte_offset INTEGER NOT NULL, end_byte_offset INTEGER NOT NULL, examiner_id INTEGER, "
-			"FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id), FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id), FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id))",
+			"FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id) ON DELETE CASCADE, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id) ON DELETE CASCADE)",
 			"Error creating content_tags table: %s\n")
 		||
 		attempt_exec
 		("CREATE TABLE blackboard_artifact_tags (tag_id INTEGER PRIMARY KEY, artifact_id INTEGER NOT NULL, tag_name_id INTEGER NOT NULL, comment TEXT NOT NULL, examiner_id INTEGER, "
-			"FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id), FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id), FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id))",
+			"FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id) ON DELETE CASCADE, FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE, FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id) ON DELETE CASCADE)",
 			"Error creating blackboard_artifact_tags table: %s\n")) {
         return 1;
     }
 
     if (attempt_exec
-        ("CREATE TABLE tsk_file_layout (obj_id INTEGER NOT NULL, byte_start INTEGER NOT NULL, byte_len INTEGER NOT NULL, sequence INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));",
+        ("CREATE TABLE tsk_file_layout (obj_id INTEGER NOT NULL, byte_start INTEGER NOT NULL, byte_len INTEGER NOT NULL, sequence INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);",
         "Error creating tsk_fs_blocks table: %s\n")) {
             return 1;
     }
diff --git a/tsk/auto/tsk_db.h b/tsk/auto/tsk_db.h
index bf7b72ebb3ddf5a3440cc1e522ccaa574f964adb..8e2c87b0515703e4cabd1c9ade06d3274d9c476d 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 3
+#define TSK_SCHEMA_MINOR_VER 4
 
 /**
  * Values for the type column in the tsk_objects table.