diff --git a/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java b/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java
index 280ac930434f7916994bbd5adee1e84620a60418..9f61fbd6b0553c43f8945dd3f8fe6cfd12bfdc3b 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/BlackboardArtifact.java
@@ -1,7 +1,7 @@
 /*
  * Sleuth Kit Data Model
  *
- * Copyright 2011-2018 Basis Technology Corp.
+ * Copyright 2011-2019 Basis Technology Corp.
  * Contact: carrier <at> sleuthkit <dot> org
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -1179,6 +1179,21 @@ public enum ARTIFACT_TYPE implements SleuthkitVisitableItem {
 		 */
 		TSK_VERIFICATION_FAILED(47, "TSK_VERIFICATION_FAILED",  //NON-NLS
 				bundle.getString("BlackboardArtifact.tskVerificationFailed.text")),
+		/**
+		 * Categorization information for a data source.
+		 */
+		TSK_DATA_SOURCE_USAGE(48, "TSK_DATA_SOURCE_USAGE", //NON-NLS
+				bundle.getString("BlackboardArtifact.tskDataSourceUsage.text")),
+		/**
+		 * Indicates auto fill data from a Web form
+		 */
+		TSK_WEB_FORM_AUTOFILL(49, "TSK_WEB_FORM_AUTOFILL",  //NON-NLS
+				bundle.getString("BlackboardArtifact.tskWebFormAutofill.text")),
+		/**
+		 * Indicates an person's address filled in a web form
+		 */
+		TSK_WEB_FORM_ADDRESS (50, "TSK_WEB_FORM_ADDRESSES ",  //NON-NLS
+				bundle.getString("BlackboardArtifact.tskWebFormAddresses.text"));
 		
 /**
 		 * A generic (timeline) event.
diff --git a/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java b/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java
index f0128c72de436e0540a007581ccc67072e27e7c9..7c899a7a41bc1e1623597f81c4719285bff49551 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java
@@ -1,7 +1,7 @@
 /*
  * Sleuth Kit Data Model
  *
- * Copyright 2011-2018 Basis Technology Corp.
+ * Copyright 2011-2019 Basis Technology Corp.
  * Contact: carrier <at> sleuthkit <dot> org
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties
index 58bc10dffe8589ada63187794dce07d9c1755659..1fc2fd028cccd403f8f984ad6a3b2887667ef632 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties
+++ b/bindings/java/src/org/sleuthkit/datamodel/Bundle.properties
@@ -45,6 +45,9 @@ BlackboardArtifact.tskSimAttached.text=SIM Attached
 BlackboardArtifact.tskBluetoothAdapter.text=Bluetooth Adapter
 BlackboardArtifact.tskWIFINetworkAdapter.text=Wireless Network Adapters
 BlackboardArtifact.tskVerificationFailed.text=Verification Failure
+BlackboardArtifact.tskDataSourceUsage.text=Data Source Usage
+BlackboardArtifact.tskWebFormAutofill.text=Web Form Autofill
+BlackboardArtifact.tskWebFormAddresses.text=Web Form Addresses
 BlackboardArtifact.shortDescriptionDate.text=at {0}
 BlackboardAttribute.tskAccountType.text=Account Type
 BlackboardAttribute.tskUrl.text=URL
diff --git a/bindings/java/src/org/sleuthkit/datamodel/DataSource.java b/bindings/java/src/org/sleuthkit/datamodel/DataSource.java
index 25f09d0e12eda16b6d4d3527ff645eb28c86efc3..f2633a1172998e3efc47c9dda9502d8aaae78d3f 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/DataSource.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/DataSource.java
@@ -66,4 +66,21 @@ public interface DataSource extends Content {
 	 */
 	long getContentSize(SleuthkitCase sleuthkitCase) throws TskCoreException;
 
+	/**
+	 * Sets the acquisition details field in the case database.
+	 * 
+	 * @param details The acquisition details
+	 * 
+	 * @throws TskCoreException Thrown if the data can not be written
+	 */
+	void setAcquisitionDetails(String details) throws TskCoreException;
+	
+	/**
+	 * Gets the acquisition details field from the case database.
+	 * 
+	 * @return The acquisition details
+	 * 
+	 * @throws TskCoreException Thrown if the data can not be read
+	 */
+	String getAcquisitionDetails() throws TskCoreException;
 }
diff --git a/bindings/java/src/org/sleuthkit/datamodel/Image.java b/bindings/java/src/org/sleuthkit/datamodel/Image.java
index 04a65ba290df24c5e350dca839fde2b593fe5d04..4bbc4636aa28edb49241037a04031253be2a2ea2 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/Image.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/Image.java
@@ -119,6 +119,10 @@ protected Image(SleuthkitCase db, long obj_id, long type, long ssize, String nam
 	 * @throws TskCoreException
 	 */
 	public synchronized long getImageHandle() throws TskCoreException {
+		if (paths.length == 0) {
+			throw new TskCoreException("Image has no associated paths");
+		}
+		
 		if (imageHandle == 0) {
 			imageHandle = SleuthkitJNI.openImage(paths, (int)ssize);
 		}
@@ -150,6 +154,11 @@ public void finalize() throws Throwable {
 
 	@Override
 	public int read(byte[] buf, long offset, long len) throws TskCoreException {
+		// If there are no paths, don't attempt to read the image
+		if (paths.length == 0) {
+			return 0;
+		}
+		
 		// read from the image
 		return SleuthkitJNI.readImg(getImageHandle(), buf, offset, len);
 	}
@@ -501,6 +510,30 @@ public long getContentSize(SleuthkitCase sleuthkitCase) throws TskCoreException
 
 		return contentSize;
 	}
+	
+	/**
+	 * Sets the acquisition details field in the case database.
+	 * 
+	 * @param details The acquisition details
+	 * 
+	 * @throws TskCoreException Thrown if the data can not be written
+	 */
+	@Override
+	public void setAcquisitionDetails(String details) throws TskCoreException {
+		getSleuthkitCase().setAcquisitionDetails(this, details);
+	}
+	
+	/**
+	 * Gets the acquisition details field from the case database.
+	 * 
+	 * @return The acquisition details
+	 * 
+	 * @throws TskCoreException Thrown if the data can not be read
+	 */
+	@Override
+	public String getAcquisitionDetails() throws TskCoreException {
+		return getSleuthkitCase().getAcquisitionDetails(this);
+	}	
 
 	/**
 	 * Close a ResultSet.
diff --git a/bindings/java/src/org/sleuthkit/datamodel/LocalFilesDataSource.java b/bindings/java/src/org/sleuthkit/datamodel/LocalFilesDataSource.java
index ed0a78b5e8e09a1ed3802f4dec895e988232d35b..1d2e25eedc0a26384d1a1946f33735097e36cc18 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/LocalFilesDataSource.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/LocalFilesDataSource.java
@@ -179,6 +179,30 @@ static long getContentSize(SleuthkitCase sleuthkitCase, long dataSourceObjId) th
 
 		return contentSize;
 	}
+	
+	/**
+	 * Sets the acquisition details field in the case database.
+	 * 
+	 * @param details The acquisition details
+	 * 
+	 * @throws TskCoreException Thrown if the data can not be written
+	 */
+	@Override
+	public void setAcquisitionDetails(String details) throws TskCoreException {
+		getSleuthkitCase().setAcquisitionDetails(this, details);
+	}
+	
+	/**
+	 * Gets the acquisition details field from the case database.
+	 * 
+	 * @return The acquisition details
+	 * 
+	 * @throws TskCoreException Thrown if the data can not be read
+	 */
+	@Override
+	public String getAcquisitionDetails() throws TskCoreException {
+		return getSleuthkitCase().getAcquisitionDetails(this);
+	}
 
 	/**
 	 * Close a ResultSet.
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
index 7a202326ac3fa2e84d3ac1cc76ce7519ce4de02b..a70c04d04ccaadd830aa2f75050f4b5eb5bdc60d 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
@@ -5205,10 +5205,14 @@ public LocalDirectory addLocalDirectory(long parentId, String directoryName, Cas
 			CaseDbConnection connection = transaction.getConnection();
 			AbstractFile parent = getAbstractFileById(parentId, connection);
 			String parentPath;
-			if (parent.getParent() == null && parent.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)) {
-				parentPath = "/";
+			if (parent != null) {
+				if (parent.getParent() == null && parent.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)) {
+					parentPath = "/";
+				} else {
+					parentPath = parent.getParentPath() + parent.getName() + "/"; //NON-NLS
+				}
 			} else {
-				parentPath = parent.getParentPath() + parent.getName() + "/"; //NON-NLS
+				parentPath = "/";
 			}
 
 			// Insert a row for the local directory into the tsk_objects table.
@@ -5354,7 +5358,229 @@ public LocalFilesDataSource addLocalFilesDataSource(String deviceId, String root
 			releaseSingleUserCaseWriteLock();
 		}
 	}
+	
+	/**
+	 * Add an image to the database.
+	 * 
+	 * @param type         Type of image
+	 * @param sectorSize   Sector size
+	 * @param size         Image size
+	 * @param displayName  Display name for the image
+	 * @param imagePaths   Image path(s)
+	 * @param timezone     Time zone
+	 * @param md5          MD5 hash
+	 * @param sha1         SHA1 hash
+	 * @param sha256       SHA256 hash
+	 * @param deviceId     Device ID
+	 * @param transaction  Case DB transaction
+	 * 
+	 * @return the newly added Image
+	 * 
+	 * @throws TskCoreException 
+	 */
+	public Image addImage(TskData.TSK_IMG_TYPE_ENUM type, long sectorSize, long size, String displayName, List<String> imagePaths,
+			String timezone, String md5, String sha1, String sha256,
+			String deviceId,
+			CaseDbTransaction transaction) throws TskCoreException {
+		acquireSingleUserCaseWriteLock();
+		Statement statement = null;
+		try {
+			// Insert a row for the Image into the tsk_objects table.
+			CaseDbConnection connection = transaction.getConnection();
+			long newObjId = addObject(0, TskData.ObjectType.IMG.getObjectType(), connection);
+			
+			// Add a row to tsk_image_info
+			// INSERT INTO tsk_image_info (obj_id, type, ssize, tzone, size, md5, sha1, sha256, display_name)
+			PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_INFO);
+			preparedStatement.clearParameters();
+			preparedStatement.setLong(1, newObjId);
+			preparedStatement.setShort(2, (short)type.getValue());
+			preparedStatement.setLong(3, sectorSize);
+			preparedStatement.setString(4, timezone);
+			preparedStatement.setLong(5, size);
+			preparedStatement.setString(6, md5);
+			preparedStatement.setString(7, sha1);
+			preparedStatement.setString(8, sha256);
+			preparedStatement.setString(9, displayName);
+			connection.executeUpdate(preparedStatement);
+			
+			// If there are paths, add them to tsk_image_names
+			for (int i = 0; i < imagePaths.size(); i++) {
+				preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_NAME);
+				preparedStatement.clearParameters();
+				preparedStatement.setLong(1, newObjId);
+				preparedStatement.setString(2, imagePaths.get(i));
+				preparedStatement.setLong(3, i);
+				connection.executeUpdate(preparedStatement);
+			}
+			
+			// Add a row to data_source_info
+			statement = connection.createStatement();
+			statement.executeUpdate("INSERT INTO data_source_info (obj_id, device_id, time_zone) "
+					+ "VALUES(" + newObjId + ", '" + deviceId + "', '" + timezone + "');");
+			
+			// Create the new Image object
+			return new Image(this, newObjId, type.getValue(), deviceId, sectorSize, displayName,
+						imagePaths.toArray(new String[imagePaths.size()]), timezone, md5, sha1, sha256, size);
+		} catch (SQLException ex) {
+			if (! imagePaths.isEmpty()) {
+				throw new TskCoreException(String.format("Error adding image with path %s to database", imagePaths.get(0)), ex);
+			} else {
+				throw new TskCoreException(String.format("Error adding image with display name %s to database", displayName), ex);
+			}
+		} finally {
+			closeStatement(statement);
+			releaseSingleUserCaseWriteLock();
+		}	
+	}
+	
+	/**
+	 * Add a volume system to the database.
+	 * 
+	 * @param parentObjId  Object ID of the volume system's parent
+	 * @param type         Type of volume system
+	 * @param imgOffset    Image offset
+	 * @param blockSize    Block size
+	 * @param transaction  Case DB transaction
+	 * 
+	 * @return the newly added VolumeSystem
+	 * 
+	 * @throws TskCoreException 
+	 */
+	public VolumeSystem addVolumeSystem(long parentObjId, TskData.TSK_VS_TYPE_ENUM type, long imgOffset, 
+			long blockSize, CaseDbTransaction transaction) throws TskCoreException{
+		acquireSingleUserCaseWriteLock();
+		try {
+			// Insert a row for the VolumeSystem into the tsk_objects table.
+			CaseDbConnection connection = transaction.getConnection();
+			long newObjId = addObject(parentObjId, TskData.ObjectType.VS.getObjectType(), connection);
+			
+			// Add a row to tsk_vs_info
+			// INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size)
+			PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_INFO);
+			preparedStatement.clearParameters();
+			preparedStatement.setLong(1, newObjId);
+			preparedStatement.setShort(2, (short)type.getVsType());
+			preparedStatement.setLong(3, imgOffset);
+			preparedStatement.setLong(4, blockSize);
+			connection.executeUpdate(preparedStatement);
+
+			// Create the new VolumeSystem object
+			return new VolumeSystem(this, newObjId, "", type.getVsType(), imgOffset, blockSize);
+		} catch (SQLException ex) {
+			throw new TskCoreException(String.format("Error creating volume system with parent ID %d and image offset %d", 
+					parentObjId, imgOffset), ex);
+		} finally {
+			releaseSingleUserCaseWriteLock();
+		}			
+	}
+
+	/**
+	 * Add a volume to the database
+	 * 
+	 * @param parentObjId   Object ID of the volume's parent
+	 * @param addr			Address of the volume
+	 * @param start         Start of the volume
+	 * @param length        Length of the volume
+	 * @param desc          Description of the volume
+	 * @param flags         Flags
+	 * @param transaction   Case DB transaction
+	 * 
+	 * @return the newly created Volume
+	 * 
+	 * @throws TskCoreException 
+	 */
+	public Volume addVolume(long parentObjId, long addr, long start, long length, String desc,
+			long flags, CaseDbTransaction transaction) throws TskCoreException{
+		acquireSingleUserCaseWriteLock();
+		Statement statement = null;
+		try {
+			// Insert a row for the Volume into the tsk_objects table.
+			CaseDbConnection connection = transaction.getConnection();
+			long newObjId = addObject(parentObjId, TskData.ObjectType.VOL.getObjectType(), connection);
+			
+			// Add a row to tsk_vs_parts
+			// INSERT INTO tsk_vs_parts (obj_id, addr, start, length, desc, flags)
+			PreparedStatement preparedStatement;
+			if (this.dbType == DbType.POSTGRESQL) {
+				preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_PART_POSTGRESQL);
+			} else {
+				preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_PART_SQLITE);
+			}
+			preparedStatement.clearParameters();
+			preparedStatement.setLong(1, newObjId);
+			preparedStatement.setLong(2, addr);
+			preparedStatement.setLong(3, start);
+			preparedStatement.setLong(4, length);
+			preparedStatement.setString(5, desc);
+			preparedStatement.setShort(6, (short)flags);
+			connection.executeUpdate(preparedStatement);
+
+			// Create the new Volume object
+			return new Volume(this, newObjId, addr, start, length, flags, desc);
+		} catch (SQLException ex) {
+			throw new TskCoreException(String.format("Error creating volume with address %d and parent ID %d", addr, parentObjId), ex);
+		} finally {
+			closeStatement(statement);
+			releaseSingleUserCaseWriteLock();
+		}			
+	}	
+	
+	/**
+	 * Add a FileSystem to the database.
+	 * 
+	 * @param parentObjId  Object ID of the file system's parent
+	 * @param imgOffset    Offset in the image
+	 * @param type         Type of file system
+	 * @param blockSize    Block size
+	 * @param blockCount   Block count
+	 * @param rootInum     root inum
+	 * @param firstInum    first inum
+	 * @param lastInum     last inum
+	 * @param displayName  display name
+	 * @param transaction  Case DB transaction
+	 * 
+	 * @return the newly created FileSystem
+	 * 
+	 * @throws TskCoreException 
+	 */
+	public FileSystem addFileSystem(long parentObjId, long imgOffset, TskData.TSK_FS_TYPE_ENUM type, long blockSize, long blockCount, 
+			long rootInum, long firstInum, long lastInum, String displayName,
+			CaseDbTransaction transaction) throws TskCoreException{
+		acquireSingleUserCaseWriteLock();
+		Statement statement = null;
+		try {
+			// Insert a row for the FileSystem into the tsk_objects table.
+			CaseDbConnection connection = transaction.getConnection();
+			long newObjId = addObject(parentObjId, TskData.ObjectType.FS.getObjectType(), connection);
+			
+			// Add a row to tsk_fs_info
+			// INSERT INTO tsk_fs_info (obj_id, img_offset, fs_type, block_size, block_count, root_inum, first_inum, last_inum, display_name)
+			PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FS_INFO);
+			preparedStatement.clearParameters();
+			preparedStatement.setLong(1, newObjId);
+			preparedStatement.setLong(2, imgOffset);
+			preparedStatement.setShort(3, (short)type.getValue());
+			preparedStatement.setLong(4, blockSize);
+			preparedStatement.setLong(5, blockCount);
+			preparedStatement.setLong(6, rootInum);
+			preparedStatement.setLong(7, firstInum);
+			preparedStatement.setLong(8, lastInum);
+			preparedStatement.setString(9, displayName);
+			connection.executeUpdate(preparedStatement);
 
+			// Create the new FileSystem object
+			return new FileSystem(this, newObjId, displayName, imgOffset, type, blockSize, blockCount, rootInum,
+				firstInum, lastInum);
+		} catch (SQLException ex) {
+			throw new TskCoreException(String.format("Error creating file system with image offset %d and parent ID %d",
+					imgOffset, parentObjId), ex);
+		} finally {
+			closeStatement(statement);
+			releaseSingleUserCaseWriteLock();
+		}			
+	}			
+	
 	/**
 	 * Get IDs of the virtual folder roots (at the same level as image), used
 	 * for containers such as for local files.
@@ -8036,6 +8262,66 @@ String getSha256ImageHash(Image img) throws TskCoreException {
 			releaseSingleUserCaseReadLock();
 		}
 	}
+	
+	/**
+	 * Set the acquisition details in the data_source_info table
+	 * 
+	 * @param datasource The data source
+	 * @param details    The acquisition details
+	 * 
+	 * @throws TskCoreException Thrown if the database write fails
+	 */
+	void setAcquisitionDetails(DataSource datasource, String details) throws TskCoreException {
+
+		long id = datasource.getId();
+		CaseDbConnection connection = connections.getConnection();
+		acquireSingleUserCaseWriteLock();
+		try {
+			PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_ACQUISITION_DETAILS);
+			statement.clearParameters();
+			statement.setString(1, details);
+			statement.setLong(2, id);
+			connection.executeUpdate(statement);
+		} catch (SQLException ex) {
+			throw new TskCoreException("Error setting acquisition details", ex);
+		} finally {
+			connection.close();
+			releaseSingleUserCaseWriteLock();
+		}
+	}
+	
+	/**
+	 * Get the acquisition details from the data_source_info table
+	 * 
+	 * @param datasource The data source
+	 * 
+	 * @return The acquisition details
+	 * 
+	 * @throws TskCoreException Thrown if the database read fails
+	 */
+	String getAcquisitionDetails(DataSource datasource) throws TskCoreException {
+		long id = datasource.getId();
+		CaseDbConnection connection = connections.getConnection();
+		acquireSingleUserCaseReadLock();
+		ResultSet rs = null;
+		String hash = "";
+		try {
+			PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ACQUISITION_DETAILS);
+			statement.clearParameters();
+			statement.setLong(1, id);
+			rs = connection.executeQuery(statement);
+			if (rs.next()) {
+				hash = rs.getString("acquisition_details");
+			}
+			return hash;
+		} catch (SQLException ex) {
+			throw new TskCoreException("Error setting acquisition details", ex);
+		} finally {
+			closeResultSet(rs);
+			connection.close();
+			releaseSingleUserCaseReadLock();
+		}
+	}
 
 	/**
 	 * Set the review status of the given artifact to newStatus
@@ -9713,6 +9999,8 @@ private enum PREPARED_STATEMENT {
 		SELECT_IMAGE_MD5("SELECT md5 FROM tsk_image_info WHERE obj_id = ?"), //NON-NLS
 		SELECT_IMAGE_SHA1("SELECT sha1 FROM tsk_image_info WHERE obj_id = ?"), //NON-NLS
 		SELECT_IMAGE_SHA256("SELECT sha256 FROM tsk_image_info WHERE obj_id = ?"), //NON-NLS
+		UPDATE_ACQUISITION_DETAILS("UPDATE data_source_info SET acquisition_details = ? WHERE obj_id = ?"), //NON-NLS
+		SELECT_ACQUISITION_DETAILS("SELECT acquisition_details FROM data_source_info WHERE obj_id = ?"), //NON-NLS
 		SELECT_LOCAL_PATH_FOR_FILE("SELECT path FROM tsk_files_path WHERE obj_id = ?"), //NON-NLS
 		SELECT_ENCODING_FOR_FILE("SELECT encoding_type FROM tsk_files_path WHERE obj_id = ?"), // NON-NLS
 		SELECT_LOCAL_PATH_AND_ENCODING_FOR_FILE("SELECT path, encoding_type FROM tsk_files_path WHERE obj_id = ?"), // NON_NLS
@@ -9836,7 +10124,15 @@ private enum PREPARED_STATEMENT {
 		UPDATE_FILE_NAME("UPDATE tsk_files SET name = ? WHERE obj_id = ?"),
 		UPDATE_IMAGE_NAME("UPDATE tsk_image_info SET display_name = ? WHERE obj_id = ?"),
 		DELETE_IMAGE_NAME("DELETE FROM tsk_image_names WHERE obj_id = ?"),
-		INSERT_IMAGE_NAME("INSERT INTO tsk_image_names (obj_id, name, sequence) VALUES (?, ?, ?)");
+		INSERT_IMAGE_NAME("INSERT INTO tsk_image_names (obj_id, name, sequence) VALUES (?, ?, ?)"),
+		INSERT_IMAGE_INFO("INSERT INTO tsk_image_info (obj_id, type, ssize, tzone, size, md5, sha1, sha256, display_name)" + 
+				" VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"),
+		INSERT_VS_INFO("INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size) VALUES (?, ?, ?, ?)"),
+		INSERT_VS_PART_SQLITE("INSERT INTO tsk_vs_parts (obj_id, addr, start, length, desc, flags) VALUES (?, ?, ?, ?, ?, ?)"),
+		INSERT_VS_PART_POSTGRESQL("INSERT INTO tsk_vs_parts (obj_id, addr, start, length, descr, flags) VALUES (?, ?, ?, ?, ?, ?)"),
+		INSERT_FS_INFO("INSERT INTO tsk_fs_info (obj_id, img_offset, fs_type, block_size, block_count, root_inum, first_inum, last_inum, display_name)"
+					+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
+		
 		
 		private final String sql;
 
diff --git a/release/release-deb.pl b/release/release-deb.pl
new file mode 100755
index 0000000000000000000000000000000000000000..539f0173ffc3a506f7b43dd07a5152ec4613726f
--- /dev/null
+++ b/release/release-deb.pl
@@ -0,0 +1,128 @@
+#!/usr/bin/perl
+
+# Makes deb file based on release tag
+# 
+
+use strict;
+
+my $TESTING = 0;
+print "TESTING MODE (no commits)\n" if ($TESTING);
+
+unless (@ARGV == 1) {
+	print stderr "Missing arguments: version\n";
+	print stderr "    for example: release-deb.pl 3.1.0\n";
+	exit(1);
+}
+
+my $RELDIR = `pwd`;	# The release directory
+chomp $RELDIR;
+my $TSKDIR = "$RELDIR/../";
+
+my $VER = $ARGV[0];
+my $TAGNAME = "sleuthkit-${VER}";
+my $TARFILE = "${TSKDIR}/../sleuthkit-java_${VER}.orig.tar.xz";
+my $DEBFILE = "${TSKDIR}/../sleuthkit-java_${VER}-1_amd64.deb";
+die ("ERROR: ${TARFILE} file already exists") if (-e ${TARFILE});
+die ("ERROR: ${DEBFILE} file already exists") if (-e ${DEBFILE});
+
+
+
+#######################
+
+# Function to execute a command and send output to pipe
+# returns handle
+# exec_pipe(HANDLE, CMD);
+sub exec_pipe {
+    my $handle = shift(@_);
+    my $cmd    = shift(@_);
+
+    die "Can't open pipe for exec_pipe"
+      unless defined(my $pid = open($handle, '-|'));
+
+    if ($pid) {
+        return $handle;
+    }
+    else {
+        $| = 1;
+        exec("$cmd") or die "Can't exec program: $!";
+    }
+}
+
+
+
+# Read a line of text from an open exec_pipe handle
+sub read_pipe_line {
+    my $handle = shift(@_);
+    my $out;
+
+    for (my $i = 0; $i < 100; $i++) {
+        $out = <$handle>;
+        return $out if (defined $out);
+    }
+    return $out;
+}
+
+
+
+############## CODE SPECIFIC STUFF ##########
+
+# Checkout a specific tag 
+# Starts and ends in sleuthkit
+sub update_code {
+
+	`git reset --hard HEAD > /dev/null`;
+	# Make sure we have no changes in the current tree
+	exec_pipe(*OUT, "git status -s | grep \"^ M\"");
+	my $foo = read_pipe_line(*OUT);
+	if ($foo ne "") {
+	    print "Changes stil exist in current repository -- commit them\n";
+	    die "stopping";
+	}
+
+	# Make sure src dir is up to date
+	print "Updating source directory\n";
+	`git checkout develop`;
+	`git pull`;
+
+	# Verify the tag exists
+	exec_pipe(*OUT, "git tag | grep \"^${TAGNAME}\"");
+	my $foo = read_pipe_line(*OUT);
+	if ($foo eq "") {
+	    print "Tag ${TAGNAME} doesn't exist\n";
+	    die "stopping";
+	}
+	close(OUT);
+
+	`git checkout -q ${TAGNAME}`;
+}
+
+
+# Make deb
+sub build_deb {
+	print "Running bootstrap\n";
+	`rm configure`;
+	`./bootstrap`;
+	die ("Configure missing") unless (-e "configure");
+
+
+	print "Running 'dh_make'. Ignore messages about overwriting, and it's OK if it goes blank\n";
+	`dh_make --s -y -e \“info\@sleuthkit.org\” -p sleuthkit-java_${VER} --createorig`;
+
+	die ("ERROR: ${TARFILE} file not created") unless (-e ${TARFILE});
+
+	print "Running debuild\n";
+	`debuild -us -uc`;
+	if (-e ${DEBFILE}) {
+		print "${DEBFILE} created\n";
+	} else {
+		die "deb file was not created\n";
+	}
+}
+
+
+##############################
+
+chdir ("$TSKDIR") or die "Error changing to TSK dir $TSKDIR";
+
+update_code();
+build_deb();
diff --git a/setupDevRepos.py b/setupDevRepos.py
index 74c20af705e00d5929de4538976aad9903c6940c..d598df87d54632e7890bd4401a99e3390ce2226f 100644
--- a/setupDevRepos.py
+++ b/setupDevRepos.py
@@ -8,24 +8,31 @@
 
 import os
 import subprocess
+import ntpath
 import sys
 
 
-def setupLibrary(path):
-    ''' sets up the library path variable '''
-    git_repository_url = "https://github.com/sleuthkit/"
+def makeRepos(path):
+    ''' creates the needed repositories '''
+    
+    # Clone zlib
     git_zlib_repository_url="https://github.com/madler/"
     zlib_path = os.path.normpath(os.path.join(path["libewf_64bit"],"zlib"))
     if not os.path.exists(zlib_path):
         gitClone(git_zlib_repository_url,"zlib",path["libewf_64bit"])
+        
+    # Clone the others
+    git_repository_url = "https://github.com/sleuthkit/"
     for library,base_library_path in path.items():
         library_path = os.path.normpath(os.path.join(base_library_path , library))
         if not os.path.exists(library_path):
             gitClone(git_repository_url, library, base_library_path)
 
+            
 def gitClone(URL, repo, path):
     # This method will clone the library if it does not exist
     cmd = ["git", "clone", URL + repo + ".git" ]
+    print("Cloning " + repo + " into " + path)
     ret = subprocess.call(cmd, stdout=sys.stdout, cwd=path)
     if ret != 0:
         sys.exit(1)
@@ -36,25 +43,28 @@ def main():
     libewf_home = os.getenv("LIBEWF_HOME")
     libvhdi_home = os.getenv("LIBVHDI_HOME")
     libvmdk_home = os.getenv("LIBVMDK_HOME")
+    
     base_Library_path = {}
+    
     if(libewf_home != None):
-        base_Library_path["libewf_64bit"] = os.path.dirname(libewf_home)
+        base_Library_path["libewf_64bit"] = ntpath.dirname(libewf_home)
     else:
         print('Please set the env variable LIBEWF_HOME')
         sys.exit(1)
 
     if(libvhdi_home != None):
-        base_Library_path["libvhdi_64bit"] = os.path.dirname(libvhdi_home)
+        base_Library_path["libvhdi_64bit"] = ntpath.dirname(libvhdi_home)
     else:
         print('Please set the env variable LIBVHDI_HOME')
         sys.exit(1)
+        
     if(libvmdk_home != None):
-        base_Library_path["libvmdk_64bit"] = os.path.dirname(os.path.dirname(libvmdk_home))
+        base_Library_path["libvmdk_64bit"] = ntpath.dirname(ntpath.dirname(libvmdk_home))
     else:
         print('Please set the env variable LIBVMDK_HOME')
         sys.exit(1)
 
-    setupLibrary(base_Library_path);
+    makeRepos(base_Library_path);
 
 if __name__ == '__main__':
     main()
diff --git a/travis_build.sh b/travis_build.sh
index 50468545b22564818036666c2e41a10279e0a157..a7689d774438c82b2574db969c85e5936050c1e9 100755
--- a/travis_build.sh
+++ b/travis_build.sh
@@ -20,7 +20,7 @@ elif test ${TRAVIS_OS_NAME} = "osx"; then
 	export PATH=${PATH}:/usr/local/opt/gettext/bin
 	brew install ant libewf gettext cppunit afflib
 fi
-installLib libvhdi 20181125
-installLib libvmdk 20181124
+installLib libvhdi 20181227
+installLib libvmdk 20181227
 ./bootstrap && ./configure --prefix=/usr && make > /dev/null
 cd bindings/java/ && ant -q dist-PostgreSQL
diff --git a/tsk/auto/db_postgresql.cpp b/tsk/auto/db_postgresql.cpp
index 77c39b22243937a539e8cd8d04934e4d14a42087..873eef1e7ce07d8c0ef84daf021caacece8e968f 100755
--- a/tsk/auto/db_postgresql.cpp
+++ b/tsk/auto/db_postgresql.cpp
@@ -540,7 +540,7 @@ int TskDbPostgreSQL::initialize() {
             "Error creating tsk_vs_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 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));",
             "Error creating data_source_info table: %s\n")
         ||
         attempt_exec
@@ -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 INTEGER NOT NULL, date_time BIGINT, 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 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))",
             "Error creating relationships table: %s\n")
         ||
         attempt_exec(