diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.cpp b/bindings/java/jni/dataModel_SleuthkitJNI.cpp
index 5ceffbe3bc0654c42c8c8f0226b1d89d6948b7bf..e4baa1abd4665b0489ddedd201111b767abd175d 100644
--- a/bindings/java/jni/dataModel_SleuthkitJNI.cpp
+++ b/bindings/java/jni/dataModel_SleuthkitJNI.cpp
@@ -3,7 +3,7 @@
  ** The Sleuth Kit 
  **
  ** Brian Carrier [carrier <at> sleuthkit [dot] org]
- ** Copyright (c) 2010-2013 Brian Carrier.  All Rights reserved
+ ** Copyright (c) 2010-2014 Brian Carrier.  All Rights reserved
  **
  ** This software is distributed under the Common Public License 1.0
  **
@@ -24,10 +24,8 @@ using std::string;
 using std::vector;
 using std::map;
 using std::stringstream;
-using std::for_each;
 
-static int m_nsrlHandle = -1;
-static std::vector<TSK_HDB_INFO *> m_hashDbs;
+static std::vector<TSK_HDB_INFO *> hashDbs;
 
 /*
 * JNI file handle structure encapsulates both
@@ -257,7 +255,6 @@ JNIEXPORT void JNICALL
     return;
 }
 
-
 /*
  * Open a hash database to use for hash lookups. It's added to the list.
  * @param env pointer to java environment this was called from
@@ -267,25 +264,21 @@ JNIEXPORT void JNICALL
  */
 JNIEXPORT jint JNICALL
     Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbOpenNat(JNIEnv * env,
-    jclass obj, jstring pathJ) {
-
+    jclass obj, jstring pathJ) 
+{
     TSK_TCHAR pathT[1024];
     toTCHAR(env, pathT, 1024, pathJ);
-
-    ///@todo Check if the db_file passed in is really an index filename
-
-    TSK_HDB_OPEN_ENUM flags = TSK_HDB_OPEN_NONE;
-    TSK_HDB_INFO * temp = tsk_hdb_open(pathT, flags);
-
-    if(temp == NULL)
+    TSK_HDB_INFO *db = tsk_hdb_open(pathT, TSK_HDB_OPEN_NONE);
+    if(!db)
     {
         setThrowTskCoreError(env);
         return -1;
     }
-
-    m_hashDbs.push_back(temp);
     
-    return m_hashDbs.size();
+    // The index of the pointer in the vector is used as a handle for the
+    // database.
+    hashDbs.push_back(db);
+    return hashDbs.size();
 }
 
 /*
@@ -301,7 +294,6 @@ JNIEXPORT jint JNICALL
 {
     TSK_TCHAR pathT[1024];
     toTCHAR(env, pathT, 1024, pathJ);
-
     if (1 == tsk_hdb_create(pathT)) {
         setThrowTskCoreError(env);
         return -1;
@@ -313,9 +305,10 @@ JNIEXPORT jint JNICALL
         return -1;
     }
 
-    m_hashDbs.push_back(db);
-    
-    return m_hashDbs.size();
+    // The index of the pointer in the vector is used as a handle for the
+    // database.
+    hashDbs.push_back(db);    
+    return hashDbs.size();
 }
 
 /*
@@ -334,12 +327,12 @@ JNIEXPORT jint JNICALL
     jclass obj, jstring filenameJ, jstring hashMd5J, jstring hashSha1J, jstring hashSha256J,
     jstring commentJ, jint dbHandle)
 {
-    if((size_t) dbHandle > m_hashDbs.size()) {
+    if((size_t) dbHandle > hashDbs.size()) {
         setThrowTskCoreError(env, "Invalid database handle");
         return 1;
     }
 
-    TSK_HDB_INFO * db = m_hashDbs.at(dbHandle-1);
+    TSK_HDB_INFO * db = hashDbs.at(dbHandle-1);
     if(!db) {
         setThrowTskCoreError(env, "Invalid database handle");
         return 1;
@@ -357,7 +350,7 @@ JNIEXPORT jint JNICALL
     const char * sha256 = hashSha256J ? (const char *) env->GetStringUTFChars(hashSha256J, &isCopy) : NULL;
     const char * comment = commentJ ? (const char *) env->GetStringUTFChars(commentJ, &isCopy) : NULL;
    
-    int8_t retval = tsk_hdb_add_str(db, name, md5, sha1, sha256, comment);
+    int8_t retval = tsk_hdb_add_hash(db, name, md5, sha1, sha256, comment);
     if (retval == 1) {
         setThrowTskCoreError(env, "Failed to add records to hash database");
     }
@@ -396,18 +389,18 @@ JNIEXPORT jboolean JNICALL
     Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbIsUpdateableNat(JNIEnv * env,
     jclass obj, jint dbHandle)
 {
-    bool retval = false;
-
-    if((size_t) dbHandle > m_hashDbs.size()) {
+    if((size_t)dbHandle > hashDbs.size()) {
         setThrowTskCoreError(env, "Invalid database handle");
-    } else {
-        TSK_HDB_INFO * db = m_hashDbs.at(dbHandle-1);
+        return (jboolean)false;
+    }
 
-        if(db != NULL) {
-            retval = (db->idx_info->updateable == 1) ? true : false;
-        }
+    TSK_HDB_INFO *db = hashDbs.at(dbHandle-1);
+    if (db == NULL) {
+        setThrowTskCoreError(env, "Invalid database handle");
+        return (jboolean)false;
     }
-    return retval;
+
+    return (jboolean)(db->updateable == 1);
 }
 
 /*
@@ -418,23 +411,21 @@ JNIEXPORT jboolean JNICALL
  * @return true if db is allowed to be reindexed
  */
 JNIEXPORT jboolean JNICALL
-    Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbIsReindexableNat(JNIEnv * env,
+    Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbUsesExternalIndexesNat(JNIEnv * env,
     jclass obj, jint dbHandle)
 {
-    bool retval = false;
-
-    if((size_t) dbHandle > m_hashDbs.size()) {
+    if((size_t)dbHandle > hashDbs.size()) {
         setThrowTskCoreError(env, "Invalid database handle");
-    } else {
-        TSK_HDB_INFO * db = m_hashDbs.at(dbHandle-1);
+        return (jboolean)false;
+    }
 
-        if(db != NULL) {
-            if (db->hDb != NULL) {
-                retval = true;
-            }
-        }
+    TSK_HDB_INFO *db = hashDbs.at(dbHandle-1);
+    if (db == NULL) {
+        setThrowTskCoreError(env, "Invalid database handle");
+        return (jboolean)false;
     }
-    return retval;
+
+    return (jboolean)(db->uses_external_indexes == 1);
 }
     
 /*
@@ -449,112 +440,29 @@ JNIEXPORT jstring JNICALL
     jclass obj, jint dbHandle)
 {
     char cpath[1024];
-    char * none = "None";   //on error or if no name is available
+    char *none = "None";   //on error or if no name is available // RJCTODO: Go back to using null if possible...or empty string
 
-    if((size_t) dbHandle > m_hashDbs.size()) {
+    if((size_t)dbHandle > hashDbs.size()) {
         setThrowTskCoreError(env, "Invalid database handle");
         return env->NewStringUTF(none);
-    } else {
-        TSK_HDB_INFO * db = m_hashDbs.at(dbHandle-1);
-
-
-        // Index might not be set up yet
-        if(tsk_hdb_idxsetup(db, db->hash_type)) {
-            // If this is a Tsk SQLite db+index, then use index fname as db fname.
-            if ((db->db_type == TSK_HDB_DBTYPE_IDXONLY_ID) && 
-                (db->idx_info->index_type == TSK_HDB_ITYPE_SQLITE_V1)) {
-
-                snprintf(cpath, 1024, "%" PRIttocTSK, db->idx_info->idx_fname);
-                jstring jname = env->NewStringUTF(cpath);
-                return jname;
-            }      
-        }
-
-        // Otherwise, try using the db fname.
-        if((db != NULL) && (db->hDb != NULL)) {
-            snprintf(cpath, 1024, "%" PRIttocTSK, db->db_fname);
-            jstring jname = env->NewStringUTF(cpath);
-            return jname;
-        } else {
-            return env->NewStringUTF(none);
-        }
-
     }
-}
 
-
-/*
- * Get index path.
- * @param env pointer to java environment this was called from
- * @param obj the java object this was called from
- * @param dbHandle Which DB.
- * @return path
- */
-JNIEXPORT jstring JNICALL
-    Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbIndexPathNat(JNIEnv * env,
-    jclass obj, jint dbHandle)
-{
-    char cpath[1024];
-    char * none = "None";   //on error or if no name is available
-
-    if((size_t) dbHandle > m_hashDbs.size()) {
+    TSK_HDB_INFO *db = hashDbs.at(dbHandle-1);
+    if (db == NULL) {
         setThrowTskCoreError(env, "Invalid database handle");
         return env->NewStringUTF(none);
-    } else {
-        TSK_HDB_INFO * db = m_hashDbs.at(dbHandle-1);
-        if (db == NULL) {
-            setThrowTskCoreError(env, "Invalid database");
-            return env->NewStringUTF(none);
-        }
-
-        ///@todo there isn't a db type for this (would be needed to get legacy index filename)
-        /*if(db->db_type == TSK_HDB_DBTYPE_NSRL_SHA1_ID) {
-            db->hash_type = TSK_HDB_HTYPE_SHA1_ID;
-        }*/
-        //else {
-            db->hash_type = TSK_HDB_HTYPE_MD5_ID;
-        //}
-
-        // Call setup to populate the idx_info struct so we can get the filename // RJCTODO: WTF?
-        tsk_hdb_idxsetup(db, db->hash_type);
-
-        if(db->idx_info != NULL) {
-            snprintf(cpath, 1024, "%" PRIttocTSK, db->idx_info->idx_fname);
-            jstring jname = env->NewStringUTF(cpath);
-            return jname;
-        } else {
-            return env->NewStringUTF(none);
-        }
-    }  
-}
-
-
-/*
- * Test for index only (no original Db file) legacy (IDX format).
- * @param env pointer to java environment this was called from
- * @param obj the java object this was called from
- * @param dbHandle Which DB.
- * @return true if index only AND is legacy
- */
-JNIEXPORT jboolean JNICALL
-    Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbIsIdxOnlyNat(JNIEnv * env,
-    jclass obj, jint dbHandle)
-{
-    bool retval = false;
-
-    if((size_t) dbHandle > m_hashDbs.size()) {
-        setThrowTskCoreError(env, "Invalid database handle");
-    } else {
-        TSK_HDB_INFO * db = m_hashDbs.at(dbHandle-1);
+    }
 
-        if(db != NULL) {
-            retval = (tsk_hdb_is_idxonly(db) == 1) ? true : false;
-        }
+    if((db->db_fname != NULL)) {
+        snprintf(cpath, 1024, "%" PRIttocTSK, db->db_fname);
+        jstring jname = env->NewStringUTF(cpath);
+        return jname;
+    } 
+    else {
+        return env->NewStringUTF(none);
     }
-    return retval;
 }
 
-
 /*
  * Get the name of the database pointed to by path
  * @param env pointer to java environment this was called from
@@ -564,20 +472,22 @@ JNIEXPORT jboolean JNICALL
 JNIEXPORT jstring JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbGetName
   (JNIEnv * env, jclass obj, jint dbHandle)
 {
-    if((size_t) dbHandle > m_hashDbs.size()) {
-        setThrowTskCoreError(env, "Invalid database handle");
-        return env->NewStringUTF("-1");
-    } else {
-        TSK_HDB_INFO * temp = m_hashDbs.at(dbHandle-1);
-        if (temp == NULL) {
-            setThrowTskCoreError(env, "Error: database object is null");
-            return env->NewStringUTF("-1");
-        }
-
-
-        jstring jname = env->NewStringUTF(temp->db_name);
-        return jname;
-    }
+    // RJCTODO: Decide the fate of this
+    //if((size_t) dbHandle > hashDbs.size()) {
+    //    setThrowTskCoreError(env, "Invalid database handle");
+    //    return env->NewStringUTF("-1");
+    //} else {
+    //    TSK_HDB_INFO * temp = hashDbs.at(dbHandle-1);
+    //    if (temp == NULL) {
+    //        setThrowTskCoreError(env, "Error: database object is null");
+    //        return env->NewStringUTF("-1");
+    //    }
+
+
+    //    jstring jname = env->NewStringUTF(temp->db_name);
+    //    return jname;
+    //}
+    return env->NewStringUTF("-1");
 }
 
 /*
@@ -589,13 +499,15 @@ JNIEXPORT jstring JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbGetNam
  */
 JNIEXPORT void JNICALL
     Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbCloseAll(JNIEnv * env,
-    jclass obj) {
-
-    for_each(m_hashDbs.begin(), m_hashDbs.end(), tsk_hdb_close);
-   
-    m_hashDbs.clear();
+    jclass obj) 
+{
+    for (std::vector<TSK_HDB_INFO *>::iterator it = hashDbs.begin(); it != hashDbs.end(); ++it) {
+        if (NULL != *it) {
+            tsk_hdb_close(*it);
+        }
+    }
 
-    m_nsrlHandle = -1;
+    hashDbs.clear();
 }
 
 /*
@@ -607,65 +519,60 @@ JNIEXPORT void JNICALL
  */
 JNIEXPORT void JNICALL
     Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbClose(JNIEnv * env,
-    jclass obj, jint dbHandle) {
-
-    if((size_t) dbHandle > m_hashDbs.size()) {
+    jclass obj, jint dbHandle) 
+{
+    if((size_t)dbHandle > hashDbs.size()) {
         setThrowTskCoreError(env, "Invalid database handle");
-    } else {
-        TSK_HDB_INFO * db = m_hashDbs.at(dbHandle-1);
+        return;
+    }
 
-        if(db != NULL) {
-            tsk_hdb_close(db);
+    TSK_HDB_INFO *db = hashDbs.at(dbHandle-1);
+    if (db == NULL) {
+        setThrowTskCoreError(env, "Invalid database handle");
+        return;
+    }
 
-            // We do NOT erase the element because that would shift the indices,
-            // messing up the existing handles.
-            m_hashDbs.at(dbHandle-1) = NULL;
+    tsk_hdb_close(db);
 
-            if (m_nsrlHandle == dbHandle) {
-                m_nsrlHandle = -1;
-            }
-        }
-    }
+    // Do NOT erase the element because that would shift the indices,
+    // messing up the existing handles.
+    hashDbs.at(dbHandle-1) = NULL;
 }
 
-
 /*
  * Class:     org_sleuthkit_datamodel_SleuthkitJNI
  * Method:    hashDbLookup
  * Signature: (Ljava/lang/String;)I
  */
 JNIEXPORT jboolean JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbLookup
-(JNIEnv * env, jclass obj, jstring hash, jint dbHandle) {
+(JNIEnv * env, jclass obj, jstring hash, jint dbHandle) 
+{
+    if((size_t)dbHandle > hashDbs.size()) {
+        setThrowTskCoreError(env, "Invalid database handle");
+        return (jboolean)false;
+    }
 
-    if((size_t) dbHandle > m_hashDbs.size()) {
+    TSK_HDB_INFO *db = hashDbs.at(dbHandle-1);
+    if (db == NULL) {
         setThrowTskCoreError(env, "Invalid database handle");
-        return -1;
+        return (jboolean)false;
     }
 
     jboolean isCopy;
-
     const char *md5 = (const char *) env->GetStringUTFChars(hash, &isCopy);
 
-    //TSK_DB_FILES_KNOWN_ENUM file_known = TSK_DB_FILES_KNOWN_UNKNOWN;
     jboolean file_known = false;
-    
-
-    TSK_HDB_INFO * db = m_hashDbs.at(dbHandle-1);
-
-    if(db != NULL) {
-        int8_t retval = tsk_hdb_lookup_str(db, md5, TSK_HDB_FLAG_QUICK, NULL, NULL);
-
-        if (retval == -1) {
-            setThrowTskCoreError(env);
-        } else if (retval) {
-            //file_known = TSK_DB_FILES_KNOWN_KNOWN_BAD;
-            file_known = true;
-        }
+    int8_t retval = tsk_hdb_lookup_str(db, md5, TSK_HDB_FLAG_QUICK, NULL, NULL);
+    if (retval == -1) {
+        setThrowTskCoreError(env);
+    } 
+    else if (retval) {
+        file_known = true;
     }
 
     env->ReleaseStringUTFChars(hash, (const char *) md5);
 
-    return (int) file_known;
+    return file_known;
 }
 
 /*
@@ -675,68 +582,75 @@ JNIEXPORT jboolean JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbLooku
  */
 JNIEXPORT jobject JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbLookupVerbose
 (JNIEnv * env, jclass obj, jstring hash, jint dbHandle) {
+    
+    // RJCTODO: This is the troubling stuff that needs to be enhanced with
+    // a query to determine if verbose lookup is supported; there then needs
+    // to be a function ptr in the TSKDHB_INFO to handle this;
+    // need to check to see how Sam's new code is handling this for the sake of integration
+    // (or is there code in this code base in AbstractAbstractFileNode?)
+    
     jobject object = NULL;
     SQliteHashStruct * hdata = NULL;
 
-    if((size_t) dbHandle > m_hashDbs.size()) {
-        setThrowTskCoreError(env, "Invalid database handle");
-        return NULL;
-    }
-
-    jboolean isCopy;
-    const char *inputHash = (const char *) env->GetStringUTFChars(hash, &isCopy);
-
-    TSK_HDB_INFO * db = m_hashDbs.at(dbHandle-1);
-    if (db != NULL) {
-        // tsk_hdb_lookup_str will also make sure the index struct is setup
-        int64_t hashId = tsk_hdb_lookup_str_id(db, inputHash);
-
-        if ((hashId > 0) && (db->idx_info->getAllData != NULL)) {
-            // Find the data associated with this hash
-            hdata = (SQliteHashStruct *)(db->idx_info->getAllData(db, hashId));
-
-            // Build the Java version of the HashInfo object
-            jclass clazz;
-            clazz = env->FindClass("org/sleuthkit/datamodel/HashInfo");
-            // get methods
-            jmethodID ctor = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
-            jmethodID addName = env->GetMethodID(clazz, "addName", "(Ljava/lang/String;)V");
-            jmethodID addComment = env->GetMethodID(clazz, "addComment", "(Ljava/lang/String;)V");
-
-            //convert hashes
-            const char *md5 = hdata->hashMd5.c_str();
-            jstring md5j = env->NewStringUTF(md5);
-            
-            const char *sha1 = hdata->hashSha1.c_str();
-            jstring sha1j = env->NewStringUTF(sha1);
-            
-            const char *sha256 = hdata->hashSha2_256.c_str();
-            jstring sha256j = env->NewStringUTF(sha256);
-
-            // make the object
-            object = env->NewObject(clazz, ctor, md5j, sha1j, sha256j);
-
-            // finish populating the object
-            std::vector<std::string>::iterator name_it = hdata->names.begin();
-            for (; name_it != hdata->names.end(); ++name_it) {
-                const char *name = name_it->c_str();
-                jstring namej = env->NewStringUTF(name);
-                env->CallVoidMethod(object, addName, namej);
-            }
-
-            std::vector<std::string>::iterator comment_it = hdata->comments.begin();
-            for (; comment_it != hdata->comments.end(); ++comment_it) {
-                const char *comment = comment_it->c_str();
-                jstring commentj = env->NewStringUTF(comment);
-                env->CallVoidMethod(object, addComment, commentj);
-            }
-
-        }
-    }
-
-    // Cleanup
-    env->ReleaseStringUTFChars(hash, (const char *) inputHash);
-    delete hdata;
+    //if((size_t) dbHandle > hashDbs.size()) {
+    //    setThrowTskCoreError(env, "Invalid database handle");
+    //    return NULL;
+    //}
+
+    //jboolean isCopy;
+    //const char *inputHash = (const char *) env->GetStringUTFChars(hash, &isCopy);
+
+    //TSK_HDB_INFO * db = hashDbs.at(dbHandle-1);
+    //if (db != NULL) {
+    //    // tsk_hdb_lookup_str will also make sure the index struct is setup
+    //    int64_t hashId = tsk_hdb_lookup_str_id(db, inputHash);
+
+    //    if ((hashId > 0) && (db->idx_info->getAllData != NULL)) {
+    //        // Find the data associated with this hash
+    //        hdata = (SQliteHashStruct *)(db->idx_info->getAllData(db, hashId));
+
+    //        // Build the Java version of the HashInfo object
+    //        jclass clazz;
+    //        clazz = env->FindClass("org/sleuthkit/datamodel/HashInfo");
+    //        // get methods
+    //        jmethodID ctor = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+    //        jmethodID addName = env->GetMethodID(clazz, "addName", "(Ljava/lang/String;)V");
+    //        jmethodID addComment = env->GetMethodID(clazz, "addComment", "(Ljava/lang/String;)V");
+
+    //        //convert hashes
+    //        const char *md5 = hdata->hashMd5.c_str();
+    //        jstring md5j = env->NewStringUTF(md5);
+    //        
+    //        const char *sha1 = hdata->hashSha1.c_str();
+    //        jstring sha1j = env->NewStringUTF(sha1);
+    //        
+    //        const char *sha256 = hdata->hashSha2_256.c_str();
+    //        jstring sha256j = env->NewStringUTF(sha256);
+
+    //        // make the object
+    //        object = env->NewObject(clazz, ctor, md5j, sha1j, sha256j);
+
+    //        // finish populating the object
+    //        std::vector<std::string>::iterator name_it = hdata->names.begin();
+    //        for (; name_it != hdata->names.end(); ++name_it) {
+    //            const char *name = name_it->c_str();
+    //            jstring namej = env->NewStringUTF(name);
+    //            env->CallVoidMethod(object, addName, namej);
+    //        }
+
+    //        std::vector<std::string>::iterator comment_it = hdata->comments.begin();
+    //        for (; comment_it != hdata->comments.end(); ++comment_it) {
+    //            const char *comment = comment_it->c_str();
+    //            jstring commentj = env->NewStringUTF(comment);
+    //            env->CallVoidMethod(object, addComment, commentj);
+    //        }
+
+    //    }
+    //}
+
+    //// Cleanup
+    //env->ReleaseStringUTFChars(hash, (const char *) inputHash);
+    //delete hdata;
 
     return object;
 }
@@ -1651,7 +1565,6 @@ Java_org_sleuthkit_datamodel_SleuthkitJNI_startVerboseLoggingNat
     tsk_verbose++;
 }
 
-
 /*
  * Create an index for the given database
  * @param env pointer to java environment this was called from
@@ -1663,66 +1576,71 @@ JNIEXPORT void JNICALL
 Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbCreateIndexNat (JNIEnv * env,
     jclass obj, jint dbHandle, jboolean overwrite)
 {
-    if((size_t) dbHandle > m_hashDbs.size()) {
+    if((size_t)dbHandle > hashDbs.size()) {
         setThrowTskCoreError(env, "Invalid database handle");
         return;
-    } else {
-        TSK_HDB_INFO * db = m_hashDbs.at(dbHandle-1);
-        if (db == NULL) {
-            setThrowTskCoreError(env, "Error: database object is null");
-            return;
-        }
+    }
 
-        if (db->db_type == TSK_HDB_DBTYPE_IDXONLY_ID) {
-            setThrowTskCoreError(env, "Error: index only");
-            return;
-        }
+    TSK_HDB_INFO *db = hashDbs.at(dbHandle-1);
+    if (db == NULL) {
+        setThrowTskCoreError(env, "Invalid database handle");
+        return;
+    }
 
-        TSK_TCHAR dbType[1024];
+    if (!db->uses_external_index) {
+        setThrowTskCoreError(env, "Database does not have an external index");
+        return;
+    }
 
-        if(db->db_type == TSK_HDB_DBTYPE_MD5SUM_ID) {
-            TSNPRINTF(dbType, 1024, _TSK_T("%") PRIcTSK, TSK_HDB_DBTYPE_MD5SUM_STR);
-        }
-        else if(db->db_type == TSK_HDB_DBTYPE_HK_ID) {
-            TSNPRINTF(dbType, 1024, _TSK_T("%") PRIcTSK, TSK_HDB_DBTYPE_HK_STR);
-        }
-        else if(db->db_type == TSK_HDB_DBTYPE_ENCASE_ID) {
-            TSNPRINTF(dbType, 1024, _TSK_T("%") PRIcTSK, TSK_HDB_DBTYPE_ENCASE_STR);
-        }
-        else {
-            TSNPRINTF(dbType, 1024, _TSK_T("%") PRIcTSK, TSK_HDB_DBTYPE_NSRL_MD5_STR);
-        }
+    TSK_TCHAR idx_type[1024];
+    if(db->db_type == TSK_HDB_DBTYPE_MD5SUM_ID) {
+        TSNPRINTF(idx_type, 1024, _TSK_T("%") PRIcTSK, TSK_HDB_DBTYPE_MD5SUM_STR);
+    }
+    else if(db->db_type == TSK_HDB_DBTYPE_HK_ID) {
+        TSNPRINTF(idx_type, 1024, _TSK_T("%") PRIcTSK, TSK_HDB_DBTYPE_HK_STR);
+    }
+    else if(db->db_type == TSK_HDB_DBTYPE_ENCASE_ID) {
+        TSNPRINTF(idx_type, 1024, _TSK_T("%") PRIcTSK, TSK_HDB_DBTYPE_ENCASE_STR);
+    }
+    else {
+        // The Java bindings only support the generation of md5 indexes for
+        // an NSRL hash database.
+        TSNPRINTF(idx_type, 1024, _TSK_T("%") PRIcTSK, TSK_HDB_DBTYPE_NSRL_MD5_STR);
+    }
   
-        // [Re]create the hash information and file
-        uint8_t err = tsk_hdb_regenerate_index(db, dbType, (overwrite ? 1 : 0));
-
-        // Make an error message
-        if (err > 0) {
-            char c_db_type[32];
-            snprintf(c_db_type, 32, "%" PRIttocTSK, dbType);
-            std::string dbTypeStr(c_db_type);
-
-            std::string msg("Error: index regeneration (db_type = " + dbTypeStr + "): ");
-            switch (err) {
-                case 1: 
-                    msg += "delete old failed.";
-                break;
-                case 2: 
-                    msg += "delete old (2nd pass) failed.";
-                break;
-                case 3: 
-                    msg += "tsk_hdb_makeindex failed.";
-                break;
-            }
-            setThrowTskCoreError(env, msg.c_str());
-            return;
-        }
-
-        // success
-        return;
+    if (tsk_hdb_makeindex(db, idx_type) != 0) {
+        setThrowTskCoreError(env);
     }
-}
 
+    // RJCTODO: Remove this
+    //// [Re]create the hash information and file
+    //uint8_t err = tsk_hdb_regenerate_index(db, dbType, (overwrite ? 1 : 0));
+
+    //// Make an error message
+    //if (err > 0) {
+    //    char c_db_type[32];
+    //    snprintf(c_db_type, 32, "%" PRIttocTSK, dbType);
+    //    std::string dbTypeStr(c_db_type);
+
+    //    std::string msg("Error: index regeneration (db_type = " + dbTypeStr + "): ");
+    //    switch (err) {
+    //        case 1: 
+    //            msg += "delete old failed.";
+    //        break;
+    //        case 2: 
+    //            msg += "delete old (2nd pass) failed.";
+    //        break;
+    //        case 3: 
+    //            msg += "tsk_hdb_makeindex failed.";
+    //        break;
+    //    }
+    //    setThrowTskCoreError(env, msg.c_str());
+    //    return;
+    //}
+
+    //// success
+    //return;
+}
 
 /*
  * Check if a lookup index exists for the given hash database.
@@ -1732,20 +1650,18 @@ Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbCreateIndexNat (JNIEnv * env,
  */
 JNIEXPORT jboolean JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbIndexExistsNat
   (JNIEnv * env, jclass obj, jint dbHandle) {
-
-    if((size_t) dbHandle > m_hashDbs.size()) {
+    if((size_t)dbHandle > hashDbs.size()) {
         setThrowTskCoreError(env, "Invalid database handle");
-        return (jboolean) false;
-    } else {
-        TSK_HDB_INFO * temp = m_hashDbs.at(dbHandle-1);
-        if (temp == NULL) {
-            return (jboolean) false;
-        }
-
-        uint8_t retval = tsk_hdb_hasindex(temp, TSK_HDB_HTYPE_MD5_ID);
+        return (jboolean)false;
+    }
 
-        return (jboolean) retval == 1;
+    TSK_HDB_INFO *db = hashDbs.at(dbHandle-1);
+    if (db == NULL) {
+        setThrowTskCoreError(env, "Invalid database handle");
+        return (jboolean)false;
     }
+
+    return (jboolean)(db->has_index(db, TSK_HDB_HTYPE_MD5_ID) == 1);
 }
 
 /*
diff --git a/bindings/java/jni/dataModel_SleuthkitJNI.h b/bindings/java/jni/dataModel_SleuthkitJNI.h
index 8f9061bfe558430f36bfe041cab4020571595096..10eb640b495dee453d3c29c47c15d45c4e0774cc 100644
--- a/bindings/java/jni/dataModel_SleuthkitJNI.h
+++ b/bindings/java/jni/dataModel_SleuthkitJNI.h
@@ -96,11 +96,11 @@ JNIEXPORT jboolean JNICALL
 
 /*
  * Class:     org_sleuthkit_datamodel_SleuthkitJNI
- * Method:    hashDbIsReindexableNat
+ * Method:    hashDbUsesExternalIndexesNat
  * Signature: 
  */
 JNIEXPORT jboolean JNICALL
-    Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbIsReindexableNat(JNIEnv * env,
+    Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbUsesExternalIndexesNat(JNIEnv * env,
     jclass obj, jint dbHandle);
 
 /*
@@ -112,15 +112,6 @@ JNIEXPORT jstring JNICALL
     Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbPathNat(JNIEnv * env,
     jclass obj, jint dbHandle);
 
-/*
- * Class:     org_sleuthkit_datamodel_SleuthkitJNI
- * Method:    hashDbIndexPathNat
- * Signature: 
- */
-JNIEXPORT jstring JNICALL
-    Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbIndexPathNat(JNIEnv * env,
-    jclass obj, jint dbHandle);
-
 /*
  * Class:     org_sleuthkit_datamodel_SleuthkitJNI
  * Method:    hashDbGetName
@@ -161,15 +152,6 @@ JNIEXPORT jboolean JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbLooku
 JNIEXPORT jobject JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_hashDbLookupVerbose
   (JNIEnv *, jclass, jstring, jint);
 
-/*
- * Class:     org_sleuthkit_datamodel_SleuthkitJNI
- * Method:    getIndexSizeNat
- * Signature: (Ljava/lang/String;)I
- */
-//@deprecated
-//JNIEXPORT jint JNICALL Java_org_sleuthkit_datamodel_SleuthkitJNI_getIndexSizeNat
-//  (JNIEnv *, jclass, jstring);
-
 /*
  * Class:     org_sleuthkit_datamodel_SleuthkitJNI
  * Method:    initAddImgNat
diff --git a/tsk/hashdb/encase.c b/tsk/hashdb/encase.c
index 73b219b2f8ba27b5f768203fa15afb73408699f6..116d331f17b7ea212b637bd76396e52116463c7f 100644
--- a/tsk/hashdb/encase.c
+++ b/tsk/hashdb/encase.c
@@ -44,21 +44,20 @@ encase_test(FILE * hFile)
  * @param hdb_info the hash database object
  */
 void
-encase_name(TSK_HDB_INFO * hdb_info)
+encase_name(TSK_HDB_INFO * hdb_info_base)
 {
-    TSK_TEXT_HDB_INFO *text_hdb_info = (TSK_TEXT_HDB_INFO*)hdb_info;
-    TSK_HDB_EXTERNAL_IDX_INFO *idx_info = (TSK_HDB_EXTERNAL_IDX_INFO*)text_hdb_info->idx;
-    FILE * hFile = text_hdb_info->hDb;
+    TSK_TEXT_HDB_INFO *hdb_info = (TSK_TEXT_HDB_INFO*)hdb_info_base;
+    FILE * hFile = hdb_info->hDb;
     wchar_t buf[40];
     UTF16 *utf16;
     UTF8 *utf8;
     size_t ilen;
-    memset(idx_info->db_name, '\0', TSK_HDB_NAME_MAXLEN);
+    memset(hdb_info->db_name, '\0', TSK_HDB_NAME_MAXLEN);
     if(!hFile) {
         if (tsk_verbose)
             fprintf(stderr,
                 "Error getting name from Encase hash db; using file name instead");
-        tsk_hdb_name_from_path(hdb_info);
+        tsk_hdb_name_from_path(hdb_info_base);
         return;
     }
 
@@ -69,14 +68,14 @@ encase_name(TSK_HDB_INFO * hdb_info)
         if (tsk_verbose)
             fprintf(stderr,
                 "Error getting name from Encase hash db; using file name instead");
-        tsk_hdb_name_from_path(hdb_info);
+        tsk_hdb_name_from_path(hdb_info_base);
         return;
     }
 
     // do some arithmetic on type sizes to be platform independent
     ilen = wcslen(buf) * (sizeof(wchar_t) / sizeof(UTF16));
 
-    utf8 = (UTF8 *) idx_info->db_name;
+    utf8 = (UTF8 *) hdb_info->db_name;
     utf16 = (UTF16 *) buf;
 
     tsk_UTF16toUTF8(TSK_LIT_ENDIAN,
@@ -258,37 +257,23 @@ encase_getentry(TSK_HDB_INFO * hdb_info, const char *hash,
 TSK_HDB_INFO *encase_open(FILE *hDb, const TSK_TCHAR *db_path)
 {
     TSK_TEXT_HDB_INFO *text_hdb_info = NULL;
-    size_t flen = 0;
 
     assert(NULL != hDb);
     assert(NULL != db_path);
     
-    if ((text_hdb_info = (TSK_TEXT_HDB_INFO*)tsk_malloc(sizeof(TSK_TEXT_HDB_INFO))) == NULL) {
-        return NULL;
-    }
-
-    flen = TSTRLEN(db_path) + 8; // RJCTODO: Check this change from 32 (change was in DF code) with Brian; was change in older code? What is the point, anyway?
-    text_hdb_info->base.db_fname = (TSK_TCHAR*)tsk_malloc(flen * sizeof(TSK_TCHAR));
-    if (NULL == text_hdb_info->base.db_fname) {
+    text_hdb_info = text_hdb_open(hDb, db_path);
+    if (NULL == text_hdb_info) {
         return NULL;
     }
 
-    TSTRNCPY(text_hdb_info->base.db_fname, db_path, flen);
     text_hdb_info->base.db_type = TSK_HDB_DBTYPE_ENCASE_ID;
-    text_hdb_info->base.updateable = 0;
-    text_hdb_info->base.uses_external_index = 1;
-    text_hdb_info->base.hash_type = TSK_HDB_HTYPE_INVALID_ID; // This will be set when the index is created/opened. 
-    text_hdb_info->base.hash_len = 0; // This will be set when the index is created/opened.
-    tsk_init_lock(&text_hdb_info->base.lock);
     text_hdb_info->base.makeindex = encase_makeindex;
+    text_hdb_info->getentry = encase_getentry;
     text_hdb_info->base.add_comment = NULL; // RJCTODO: Consider making no-ops for these or moving them
     text_hdb_info->base.add_filename = NULL; // RJCTODO: Consider making no-ops for these or moving them
 
-    text_hdb_info->hDb = hDb;
-    text_hdb_info->getentry = encase_getentry;
-
     // RJCTODO: Figure out when to do this
-    //md5sum_name((TSK_HDB_INFO*)hdb_info);
+    //encase_name((TSK_HDB_INFO*)hdb_info);
 
     return (TSK_HDB_INFO*)text_hdb_info;    
 }
diff --git a/tsk/hashdb/hashkeeper.c b/tsk/hashdb/hashkeeper.c
index d461468b691b2efa8facafa4584d44508261ab14..720a1d73a438abbe86eaf84eaaf5f521e8e68c54 100644
--- a/tsk/hashdb/hashkeeper.c
+++ b/tsk/hashdb/hashkeeper.c
@@ -476,35 +476,21 @@ hk_getentry(TSK_HDB_INFO * hdb_info, const char *hash, TSK_OFF_T offset,
 TSK_HDB_INFO *hk_open(FILE *hDb, const TSK_TCHAR *db_path)
 {
     TSK_TEXT_HDB_INFO *text_hdb_info = NULL;
-    size_t flen = 0;
 
     assert(NULL != hDb);
     assert(NULL != db_path);
     
-    if ((text_hdb_info = (TSK_TEXT_HDB_INFO*)tsk_malloc(sizeof(TSK_TEXT_HDB_INFO))) == NULL) {
+    text_hdb_info = text_hdb_open(hDb, db_path);
+    if (NULL == text_hdb_info) {
         return NULL;
     }
 
-    flen = TSTRLEN(db_path) + 8; // RJCTODO: Check this change from 32 (change was in DF code) with Brian; was change in older code? What is the point, anyway?
-    text_hdb_info->base.db_fname = (TSK_TCHAR*)tsk_malloc(flen * sizeof(TSK_TCHAR));
-    if (NULL == text_hdb_info->base.db_fname) {
-        return NULL;
-    }
-
-    TSTRNCPY(text_hdb_info->base.db_fname, db_path, flen);
     text_hdb_info->base.db_type = TSK_HDB_DBTYPE_HK_ID;
-    text_hdb_info->base.updateable = 0;
-    text_hdb_info->base.uses_external_index = 1;
-    text_hdb_info->base.hash_type = TSK_HDB_HTYPE_INVALID_ID; // This will be set when the index is created/opened. 
-    text_hdb_info->base.hash_len = 0; // This will be set when the index is created/opened.
-    tsk_init_lock(&text_hdb_info->base.lock);
     text_hdb_info->base.makeindex = hk_makeindex;
+    text_hdb_info->getentry = hk_getentry;
     text_hdb_info->base.add_comment = NULL; // RJCTODO: Consider making no-ops for these or moving them
     text_hdb_info->base.add_filename = NULL; // RJCTODO: Consider making no-ops for these or moving them
 
-    text_hdb_info->hDb = hDb;
-    text_hdb_info->getentry = hk_getentry;
-
     // RJCTODO: Figure out when to do this
     //hk_name((TSK_HDB_INFO*)hdb_info);
 
diff --git a/tsk/hashdb/hdb_index.cpp b/tsk/hashdb/hdb_index.cpp
index b155ed62ac550d2e7e48f215424560a9e610caa6..3220df8085b513763702ddc49d9119a7f62c583d 100644
--- a/tsk/hashdb/hdb_index.cpp
+++ b/tsk/hashdb/hdb_index.cpp
@@ -737,44 +737,6 @@ tsk_hdb_makeindex(TSK_HDB_INFO * a_hdb_info, TSK_TCHAR * a_type)
     return a_hdb_info->makeindex(a_hdb_info, a_type);
 }
 
-// RJCTODO: Remove this
-///**
-// * \ingroup hashdblib
-// * Create a new hash database that can be written to.
-// * @param db_file Filename.
-// * @returns NULL on error
-// */
-//TSK_HDB_INFO *
-//tsk_hdb_newdb(TSK_TCHAR * db_file)
-//{
-//    // @@@ THis seems like a hack. We should probably pass in a "NEW/CREATE" flag into open to signal this use of the method.
-//    // though, I'm not sure what hdb_open is really doing of value in this case....
-//    TSK_HDB_OPEN_ENUM flags = TSK_HDB_OPEN_IDXONLY;
-//    TSK_HDB_INFO * hdb_info = tsk_hdb_open(db_file, flags);
-//    
-//    if (hdb_info != NULL) {
-//        TSK_TCHAR * dbtype = NULL; //ignored for IDX only
-//        // @@@ This currently goes to idxonly_initidx, which makes the file.
-//        if (hdb_info->makeindex(hdb_info, dbtype) != 0) {
-//            tsk_hdb_close(hdb_info);
-//            hdb_info = NULL;
-//            tsk_error_reset();
-//            tsk_error_set_errno(TSK_ERR_HDB_CREATE);
-//            tsk_error_set_errstr("tsk_hdb_new: making new index failed");
-//        }
-//        else {
-//            if (tsk_hdb_idxfinalize(hdb_info) != 0) {
-//                tsk_hdb_close(hdb_info);
-//                hdb_info = NULL;
-//                tsk_error_reset();
-//                tsk_error_set_errno(TSK_ERR_HDB_WRITE);
-//                tsk_error_set_errstr("tsk_hdb_new: finalizing new index failed");
-//            }
-//        }    
-//    }
-//    return hdb_info;
-//}
-//
 /**
  * \ingroup hashdblib
  * Add a binary hash entry to the index
@@ -787,7 +749,7 @@ tsk_hdb_makeindex(TSK_HDB_INFO * a_hdb_info, TSK_TCHAR * a_type)
  * @return 1 on error, 0 on success, -1 if not updateable
  */
 int8_t
-tsk_hdb_add_str(TSK_HDB_INFO * hdb_info, 
+tsk_hdb_add_hash(TSK_HDB_INFO * hdb_info, 
                 const char * filename, 
                 const char * md5, 
                 const char * sha1, 
diff --git a/tsk/hashdb/hdb_open.cpp b/tsk/hashdb/hdb_open.cpp
index 16a85894783bc4d143c9e2c9aae8d6cca01f4deb..f91c356aec5de90f1a5bcafa9380ff0540409b38 100644
--- a/tsk/hashdb/hdb_open.cpp
+++ b/tsk/hashdb/hdb_open.cpp
@@ -20,7 +20,7 @@
  * Contains the code to open and close all supported hash database types.
  */
 
-static uint8_t 
+uint8_t 
 hdb_file_exists(TSK_TCHAR *file_path)
 {
 #ifdef TSK_WIN32
@@ -150,7 +150,7 @@ tsk_hdb_open(TSK_TCHAR *file_path, TSK_HDB_OPEN_ENUM flags)
     assert(NULL != file_path);
     if (NULL == file_path) {
         tsk_error_reset();
-        tsk_error_set_errno(TSK_ERR_HDB_INVALID_PARAM); // RJCTODO: COnsider changing this to INVALID_PATH
+        tsk_error_set_errno(TSK_ERR_HDB_INVALID_PARAM); // RJCTODO: COnsider changing this to INVALID_PATH...actually, don't need this there is an ARG
         tsk_error_set_errstr("%s: NULL file path", func_name);
         return NULL;
     }
diff --git a/tsk/hashdb/idxonly.c b/tsk/hashdb/idxonly.c
index 6e6d4ac9db51dbe08f92eec53ca9ecacf77080cb..64a80f73a0b0a956a287b9dbb82dc0e34b6779f2 100644
--- a/tsk/hashdb/idxonly.c
+++ b/tsk/hashdb/idxonly.c
@@ -120,33 +120,20 @@ idxonly_getentry(TSK_HDB_INFO * hdb_info, const char *hash,
 TSK_HDB_INFO *idxonly_open(const TSK_TCHAR *db_path)
 {
     TSK_TEXT_HDB_INFO *text_hdb_info = NULL;
-    size_t flen = 0;
 
     assert(NULL != db_path);
     
-    if ((text_hdb_info = (TSK_TEXT_HDB_INFO*)tsk_malloc(sizeof(TSK_TEXT_HDB_INFO))) == NULL) {
+    text_hdb_info = text_hdb_open(NULL, db_path);
+    if (NULL == text_hdb_info) {
         return NULL;
     }
 
-    flen = TSTRLEN(db_path) + 8; // RJCTODO: Check this change from 32 (change was in DF code) with Brian; was change in older code? What is the point, anyway?
-    text_hdb_info->base.idx_fname = (TSK_TCHAR*)tsk_malloc(flen * sizeof(TSK_TCHAR));
-    if (NULL == text_hdb_info->base.idx_fname) {
-        return NULL;
-    }
-
-    TSTRNCPY(text_hdb_info->base.idx_fname, db_path, flen);
     text_hdb_info->base.db_type = TSK_HDB_DBTYPE_IDXONLY_ID;
-    text_hdb_info->base.updateable = 0;
-    text_hdb_info->base.uses_external_index = 1;
-    text_hdb_info->base.hash_type = TSK_HDB_HTYPE_INVALID_ID; // This will be set when the index is created/opened. 
-    text_hdb_info->base.hash_len = 0; // This will be set when the index is created/opened.
-    tsk_init_lock(&text_hdb_info->base.lock);
+    text_hdb_info->getentry = idxonly_getentry;
     text_hdb_info->base.makeindex = idxonly_makeindex;
     text_hdb_info->base.add_comment = NULL; // RJCTODO: Consider making no-ops for these or moving them
     text_hdb_info->base.add_filename = NULL; // RJCTODO: Consider making no-ops for these or moving them
 
-    text_hdb_info->getentry = idxonly_getentry;
-
     // RJCTODO: Figure out when to do this
     //idxonly_name((TSK_HDB_INFO*)hdb_info);
 
diff --git a/tsk/hashdb/md5sum.c b/tsk/hashdb/md5sum.c
index 625284b3a27a7fee174faeb0b458878a1992c067..45c87458b5682dfec4371a9f5b1d2ae607758d84 100644
--- a/tsk/hashdb/md5sum.c
+++ b/tsk/hashdb/md5sum.c
@@ -397,37 +397,23 @@ md5sum_getentry(TSK_HDB_INFO * hdb_info, const char *hash,
 TSK_HDB_INFO *md5sum_open(FILE *hDb, const TSK_TCHAR *db_path)
 {
     TSK_TEXT_HDB_INFO *text_hdb_info = NULL;
-    size_t flen = 0;
 
     assert(NULL != hDb);
     assert(NULL != db_path);
     
-    if ((text_hdb_info = (TSK_TEXT_HDB_INFO*)tsk_malloc(sizeof(TSK_TEXT_HDB_INFO))) == NULL) {
+    text_hdb_info = text_hdb_open(hDb, db_path);
+    if (NULL == text_hdb_info) {
         return NULL;
     }
 
-    flen = TSTRLEN(db_path) + 8; // RJCTODO: Check this change from 32 (change was in DF code) with Brian; was change in older code? What is the point, anyway?
-    text_hdb_info->base.db_fname = (TSK_TCHAR*)tsk_malloc(flen * sizeof(TSK_TCHAR));
-    if (NULL == text_hdb_info->base.db_fname) {
-        return NULL;
-    }
-
-    TSTRNCPY(text_hdb_info->base.db_fname, db_path, flen);
     text_hdb_info->base.db_type = TSK_HDB_DBTYPE_MD5SUM_ID;
-    text_hdb_info->base.updateable = 0;
-    text_hdb_info->base.uses_external_index = 1;
-    text_hdb_info->base.hash_type = TSK_HDB_HTYPE_INVALID_ID; // This will be set when the index is created/opened. 
-    text_hdb_info->base.hash_len = 0; // This will be set when the index is created/opened.
-    tsk_init_lock(&text_hdb_info->base.lock);
+    text_hdb_info->getentry = md5sum_getentry;
     text_hdb_info->base.makeindex = md5sum_makeindex;
     text_hdb_info->base.add_comment = NULL; // RJCTODO: Consider making no-ops for these or moving them
     text_hdb_info->base.add_filename = NULL; // RJCTODO: Consider making no-ops for these or moving them
 
-    text_hdb_info->hDb = hDb;
-    text_hdb_info->getentry = md5sum_getentry;
-
     // RJCTODO: Figure out when to do this
-    //encase_name((TSK_HDB_INFO*)hdb_info);
+    //md5sum_name((TSK_HDB_INFO*)hdb_info);
 
     return (TSK_HDB_INFO*)text_hdb_info;    
 }
\ No newline at end of file
diff --git a/tsk/hashdb/nsrl.c b/tsk/hashdb/nsrl.c
index a34948b8b0528424738a26e8a6e3d9f9dcd1a04b..9d7de5523a40f0b7002d9209a2ef30e8112751a2 100644
--- a/tsk/hashdb/nsrl.c
+++ b/tsk/hashdb/nsrl.c
@@ -2,7 +2,7 @@
  * The Sleuth Kit
  *
  * Brian Carrier [carrier <at> sleuthkit [dot] org]
- * Copyright (c) 2003-2011 Brian Carrier.  All rights reserved
+ * Copyright (c) 2003-2014 Brian Carrier.  All rights reserved
  *
  *
  * This software is distributed under the Common Public License 1.0
@@ -367,9 +367,6 @@ nsrl_parse_md5(char *str, char **md5, char **name, int ver)
     return 1;
 }
 
-
-
-
 /**
  * Process the database to create a sorted index of it. Consecutive
  * entries with the same hash value are not added to the index, but
@@ -381,9 +378,9 @@ nsrl_parse_md5(char *str, char **md5, char **name, int ver)
  * @return 1 on error and 0 on success.
  */
 uint8_t
-nsrl_makeindex(TSK_HDB_INFO * hdb_info, TSK_TCHAR * dbtype)
+nsrl_makeindex(TSK_HDB_INFO * hdb_info_base, TSK_TCHAR * dbtype)
 {
-    TSK_TEXT_HDB_INFO *text_hdb_info = (TSK_TEXT_HDB_INFO*)hdb_info; 
+    TSK_TEXT_HDB_INFO *hdb_info = (TSK_TEXT_HDB_INFO*)hdb_info_base;
     size_t i, len;
     char buf[TSK_HDB_MAXLEN];
     char *hash = NULL, phash[TSK_HDB_HTYPE_SHA1_LEN + 1];
@@ -391,7 +388,7 @@ nsrl_makeindex(TSK_HDB_INFO * hdb_info, TSK_TCHAR * dbtype)
     int ver = 0;
     int db_cnt = 0, idx_cnt = 0, ig_cnt = 0;
 
-    if (tsk_hdb_idxinitialize(hdb_info, dbtype)) {
+    if (text_hdb_idx_init(hdb_info_base, dbtype)) {
         tsk_error_set_errstr2( "nsrl_makeindex");
         return 1;
     }
@@ -399,14 +396,14 @@ nsrl_makeindex(TSK_HDB_INFO * hdb_info, TSK_TCHAR * dbtype)
     /* Status */
     if (tsk_verbose)
         TFPRINTF(stderr, _TSK_T("Extracting Data from Database (%s)\n"),
-                 hdb_info->db_fname);
+                 hdb_info_base->db_fname);
 
     /* Allocate a buffer for the previous hash value */
     memset(phash, '0', TSK_HDB_HTYPE_SHA1_LEN + 1);
 
     /* read the file */
-    fseek(text_hdb_info->hDb, 0, SEEK_SET);
-    for (i = 0; NULL != fgets(buf, TSK_HDB_MAXLEN, text_hdb_info->hDb);
+    fseek(hdb_info->hDb, 0, SEEK_SET);
+    for (i = 0; NULL != fgets(buf, TSK_HDB_MAXLEN, hdb_info->hDb);
          offset += len, i++) {
 
         len = strlen(buf);
@@ -442,7 +439,7 @@ nsrl_makeindex(TSK_HDB_INFO * hdb_info, TSK_TCHAR * dbtype)
         }
 
         /* Add the entry to the index */
-        if (tsk_hdb_idxaddentry(hdb_info, hash, offset)) {
+        if (text_hdb_idx_add_entry(hdb_info_base, hash, offset)) {
             tsk_error_set_errstr2( "nsrl_makeindex");
             return 1;
         }
@@ -464,7 +461,7 @@ nsrl_makeindex(TSK_HDB_INFO * hdb_info, TSK_TCHAR * dbtype)
         }
 
         /* Close and sort the index */
-        if (tsk_hdb_idxfinalize(hdb_info)) {
+        if (text_hdb_idx_finalize(hdb_info_base)) {
             tsk_error_set_errstr2( "nsrl_makeindex");
             return 1;
         }
@@ -497,14 +494,14 @@ nsrl_makeindex(TSK_HDB_INFO * hdb_info, TSK_TCHAR * dbtype)
  * @return 1 on error and 0 on success
  */
 uint8_t
-nsrl_getentry(TSK_HDB_INFO * hdb_info, const char *hash, TSK_OFF_T offset,
+nsrl_getentry(TSK_HDB_INFO * hdb_info_base, const char *hash, TSK_OFF_T offset,
               TSK_HDB_FLAG_ENUM flags,
               TSK_HDB_LOOKUP_FN action, void *cb_ptr)
 {
+    TSK_TEXT_HDB_INFO *hdb_info = (TSK_TEXT_HDB_INFO*)hdb_info_base; 
     char buf[TSK_HDB_MAXLEN], *name, *cur_hash, pname[TSK_HDB_MAXLEN];
     int found = 0;
     int ver;
-    TSK_TEXT_HDB_INFO *text_db_info = (TSK_TEXT_HDB_INFO*)hdb_info; 
 
     if (tsk_verbose)
         fprintf(stderr,
@@ -531,8 +528,8 @@ nsrl_getentry(TSK_HDB_INFO * hdb_info, const char *hash, TSK_OFF_T offset,
     }
 
     /* read the header line ... -- this should be done only once... */
-    fseeko(text_db_info->hDb, 0, SEEK_SET);
-    if (NULL == fgets(buf, TSK_HDB_MAXLEN, text_db_info->hDb)) {
+    fseeko(hdb_info->hDb, 0, SEEK_SET);
+    if (NULL == fgets(buf, TSK_HDB_MAXLEN, hdb_info->hDb)) {
         tsk_error_reset();
         tsk_error_set_errno(TSK_ERR_HDB_READDB);
         tsk_error_set_errstr(
@@ -551,7 +548,7 @@ nsrl_getentry(TSK_HDB_INFO * hdb_info, const char *hash, TSK_OFF_T offset,
     while (1) {
         size_t len;
 
-        if (0 != fseeko(text_db_info->hDb, offset, SEEK_SET)) {
+        if (0 != fseeko(hdb_info->hDb, offset, SEEK_SET)) {
             tsk_error_reset();
             tsk_error_set_errno(TSK_ERR_HDB_READDB);
             tsk_error_set_errstr(
@@ -560,8 +557,8 @@ nsrl_getentry(TSK_HDB_INFO * hdb_info, const char *hash, TSK_OFF_T offset,
             return 1;
         }
 
-        if (NULL == fgets(buf, TSK_HDB_MAXLEN, text_db_info->hDb)) {
-            if (feof(text_db_info->hDb))
+        if (NULL == fgets(buf, TSK_HDB_MAXLEN, hdb_info->hDb)) {
+            if (feof(hdb_info->hDb))
                 break;
 
             tsk_error_reset();
@@ -611,7 +608,7 @@ nsrl_getentry(TSK_HDB_INFO * hdb_info, const char *hash, TSK_OFF_T offset,
         /* Check if this is the same name as the previous entry */
         if (strcmp(name, pname) != 0) {
             int retval;
-            retval = action(hdb_info, hash, name, cb_ptr);
+            retval = action(hdb_info_base, hash, name, cb_ptr);
             if (retval == TSK_WALK_STOP)
                 return 0;
             else if (retval == TSK_WALK_ERROR)
@@ -640,36 +637,23 @@ nsrl_getentry(TSK_HDB_INFO * hdb_info, const char *hash, TSK_OFF_T offset,
 TSK_HDB_INFO *nsrl_open(FILE *hDb, const TSK_TCHAR *db_path)
 {
     TSK_TEXT_HDB_INFO *text_hdb_info = NULL;
-    size_t flen = 0;
 
     assert(NULL != hDb);
     assert(NULL != db_path);
     
-    if ((text_hdb_info = (TSK_TEXT_HDB_INFO*)tsk_malloc(sizeof(TSK_TEXT_HDB_INFO))) == NULL) {
+    text_hdb_info = text_hdb_open(hDb, db_path);
+    if (NULL == text_hdb_info) {
         return NULL;
     }
 
-    flen = TSTRLEN(db_path) + 8; // RJCTODO: Check this change from 32 (change was in DF code) with Brian; was change in older code? What is the point, anyway?
-    text_hdb_info->base.db_fname = (TSK_TCHAR*)tsk_malloc(flen * sizeof(TSK_TCHAR));
-    if (NULL == text_hdb_info->base.db_fname) {
-        return NULL;
-    }
-
-    TSTRNCPY(text_hdb_info->base.db_fname, db_path, flen);
     text_hdb_info->base.db_type = TSK_HDB_DBTYPE_NSRL_ID;
-    text_hdb_info->base.updateable = 0;
-    text_hdb_info->base.uses_external_index = 1;
-    text_hdb_info->base.hash_type = TSK_HDB_HTYPE_INVALID_ID; // This will be set when the index is created/opened. 
-    text_hdb_info->base.hash_len = 0; // This will be set when the index is created/opened.
-    tsk_init_lock(&text_hdb_info->base.lock);
     text_hdb_info->base.makeindex = nsrl_makeindex;
+    text_hdb_info->getentry = nsrl_getentry;
     text_hdb_info->base.add_comment = NULL; // RJCTODO: Consider making no-ops for these or moving them
     text_hdb_info->base.add_filename = NULL; // RJCTODO: Consider making no-ops for these or moving them
 
-    text_hdb_info->hDb = hDb;
-    text_hdb_info->getentry = nsrl_getentry;
-
     // RJCTODO: Figure out when to do this
+    // Looks like there can be a base open, with call out to set name and db type param 
     //nsrl_name((TSK_HDB_INFO*)text_hdb_info);
 
     return (TSK_HDB_INFO*)text_hdb_info;
diff --git a/tsk/hashdb/sqlite_index.cpp b/tsk/hashdb/sqlite_index.cpp
index 293d804a86456423c89e9d989836b6fd5fa56be6..6219fe31db73b28b152d58192ddff51e80b92a90 100644
--- a/tsk/hashdb/sqlite_index.cpp
+++ b/tsk/hashdb/sqlite_index.cpp
@@ -184,34 +184,34 @@ uint8_t sqlite_hdb_create_db(TSK_TCHAR *db_file_path)
 // Are there prepared statements that are not finalized?
 // Why are the statements prepared on every round? This should be done on open, and finalization should happen on close.
 // This code is not really needed for index building now, but it is still probably worthwhile for add operations.
-uint8_t
-sqlite_v1_begin(TSK_HDB_INFO * hdb_info)
-{
-    TSK_SQLITE_HDB_INFO *sqlite_hdb_info = (TSK_SQLITE_HDB_INFO*)hdb_info;
-	char * insertStmt;
-
-	if (hdb_info->hash_type == TSK_HDB_HTYPE_MD5_ID) {
-		insertStmt = "INSERT INTO hashes (md5, database_offset) VALUES (?, ?)";
-	} else if (hdb_info->hash_type == TSK_HDB_HTYPE_SHA1_ID) {
-		insertStmt = "INSERT INTO hashes (sha1, database_offset) VALUES (?, ?)";
-	} else {
-        return 1;
-    }
-
-	prepare_stmt(insertStmt, &m_stmt, sqlite_hdb_info->db);
-
-	if (begin_transaction(hdb_info)) {
-		return 1;
-	} else {
-        return 0;
-    }
-}
+//uint8_t
+//sqlite_v1_begin(TSK_HDB_INFO * hdb_info)
+//{
+//    TSK_SQLITE_HDB_INFO *sqlite_hdb_info = (TSK_SQLITE_HDB_INFO*)hdb_info;
+//	char * insertStmt;
+//
+//	if (hdb_info->hash_type == TSK_HDB_HTYPE_MD5_ID) {
+//		insertStmt = "INSERT INTO hashes (md5, database_offset) VALUES (?, ?)";
+//	} else if (hdb_info->hash_type == TSK_HDB_HTYPE_SHA1_ID) {
+//		insertStmt = "INSERT INTO hashes (sha1, database_offset) VALUES (?, ?)";
+//	} else {
+//        return 1;
+//    }
+//
+//	prepare_stmt(insertStmt, &m_stmt, sqlite_hdb_info->db);
+//
+//	if (begin_transaction(hdb_info)) {
+//		return 1;
+//	} else {
+//        return 0;
+//    }
+//}
 
 /**
  * This function is a no-op for SQLite hash database. The index is "internal" to the RDBMS.
  * @return 1 on error and 0 on success
  */
-uint8_t sqlite_hdb_make_index(TSK_HDB_INFO * hdb_info, TSK_TCHAR * dbtype)
+uint8_t sqlite_hdb_make_index(TSK_HDB_INFO * hdb_info, TSK_TCHAR * htype)
 {
     // RJCTODO: Add should not be called error stuff
     return 0;
@@ -277,10 +277,10 @@ sqlite_hdb_add(TSK_HDB_INFO * hdb_info, const char * filename, const char * md5,
  * This function is a no-op for SQLite hash database. The index is "internal" to the RDBMS.
  * @return 1 on error and 0 on success
  */
-uint8_t
-sqlite_v1_addentry_bin(TSK_HDB_INFO * hdb_info, uint8_t* hvalue, int hlen,
-                    TSK_OFF_T offset)
-{
+//uint8_t
+//sqlite_v1_addentry_bin(TSK_HDB_INFO * hdb_info, uint8_t* hvalue, int hlen,
+//                    TSK_OFF_T offset)
+//{
 // RJCTODO: This needs to go into a separate add to hash database function, as opposed to an add to index function
  //   if (attempt(sqlite3_bind_blob(m_stmt, 1, hvalue, hlen, SQLITE_TRANSIENT),
 	//	SQLITE_OK,
@@ -311,16 +311,16 @@ sqlite_v1_addentry_bin(TSK_HDB_INFO * hdb_info, uint8_t* hvalue, int hlen,
  //   }
 
  //   return 0;
-    return 0;
-}
+//    return 0;
+//}
 
 /**
  * This function is a no-op for SQLite hash database. The index is "internal" to the RDBMS.
  * @return 1 on error and 0 on success
  */
-uint8_t
-addentry_text(TSK_HDB_INFO * hdb_info, char* hvalue, TSK_OFF_T offset)
-{
+//uint8_t
+//addentry_text(TSK_HDB_INFO * hdb_info, char* hvalue, TSK_OFF_T offset)
+//{
 // RJCTODO: This needs to go into a separate add to hash database function, as opposed to an add to index function
  //   if (attempt(sqlite3_bind_text(m_stmt, 1, hvalue, strlen(hvalue), SQLITE_TRANSIENT),
 	//	SQLITE_OK,
@@ -351,8 +351,8 @@ addentry_text(TSK_HDB_INFO * hdb_info, char* hvalue, TSK_OFF_T offset)
  //   }
 
  //   return 0;
-    return 0;
-}
+//    return 0;
+//}
 
 /**
  * Add new comment (e.g. the case name)
@@ -402,9 +402,9 @@ sqlite_v1_addfilename(TSK_HDB_INFO * hdb_info, char* value, int64_t id)
  * This function is a no-op for SQLite hash database. The index is "internal" to the RDBMS.
  * @return 1 on error and 0 on success
  */
-uint8_t
-sqlite_v1_finalize(TSK_HDB_INFO * hdb_info)
-{
+//uint8_t
+//sqlite_v1_finalize(TSK_HDB_INFO * hdb_info)
+//{
     // RJCTODO: Remove this after add to hash database function is made
     //if (end_transaction(hdb_info->idx_info)) {
 	//	tsk_error_reset();
@@ -427,8 +427,8 @@ sqlite_v1_finalize(TSK_HDB_INFO * hdb_info)
  //   } else {
  //       return 0;
  //   }
-    return 0;
-}
+//    return 0;
+//}
 
 /**
  * \ingroup hashdblib
@@ -783,48 +783,48 @@ void * sqlite_v1_getAllData(TSK_HDB_INFO * hdb_info, unsigned long hashId)
  * @param hdb_info Open hash database (with index)
  * @return -1 on error, 0 on success.
  */
-int8_t
-sqlite_v1_get_properties(TSK_HDB_INFO * hdb_info)
-{
-    int8_t ret = 0;
-	sqlite3_stmt* stmt = NULL;
-    char selectStmt[1024];
-
-    tsk_take_lock(&hdb_info->lock);
-    
-    snprintf(selectStmt, 1024, "SELECT value from db_properties where name='%s'", IDX_HASHSET_UPDATEABLE);
-    prepare_stmt(selectStmt, &stmt, hdb_info->idx_info->idx_struct.idx_sqlite_v1->hIdx_sqlite);
-
-	if (sqlite3_step(stmt) == SQLITE_ROW) {
-		const char* value = (const char *)sqlite3_column_text(stmt, 0);
-
-        if (value == NULL) {
-            tsk_error_set_errstr2("sqlite_v1_get_properties: null value");
-            ret = -1;
-        } else {
-            // Set the updateable flag
-            if (strcmp(value, "true") == 0) {
-                hdb_info->idx_info->updateable = 1;
-            }
-        }
-	} else {
-        tsk_error_set_errstr2("sqlite_v1_get_properties");
-        ret = -1;
-    }
-
-	sqlite3_reset(stmt);
-    
-    if (stmt) {
-        finalize_stmt(stmt);
-    }
-
-
-    ///@todo load db name property as well?
-
-    tsk_release_lock(&hdb_info->lock);
-
-	return ret;
-}
+//int8_t
+//sqlite_v1_get_properties(TSK_HDB_INFO * hdb_info)
+//{
+//    int8_t ret = 0;
+//	sqlite3_stmt* stmt = NULL;
+//    char selectStmt[1024];
+//
+//    tsk_take_lock(&hdb_info->lock);
+//    
+//    snprintf(selectStmt, 1024, "SELECT value from db_properties where name='%s'", IDX_HASHSET_UPDATEABLE);
+//    prepare_stmt(selectStmt, &stmt, hdb_info->idx_info->idx_struct.idx_sqlite_v1->hIdx_sqlite);
+//
+//	if (sqlite3_step(stmt) == SQLITE_ROW) {
+//		const char* value = (const char *)sqlite3_column_text(stmt, 0);
+//
+//        if (value == NULL) {
+//            tsk_error_set_errstr2("sqlite_v1_get_properties: null value");
+//            ret = -1;
+//        } else {
+//            // Set the updateable flag
+//            if (strcmp(value, "true") == 0) {
+//                hdb_info->idx_info->updateable = 1;
+//            }
+//        }
+//	} else {
+//        tsk_error_set_errstr2("sqlite_v1_get_properties");
+//        ret = -1;
+//    }
+//
+//	sqlite3_reset(stmt);
+//    
+//    if (stmt) {
+//        finalize_stmt(stmt);
+//    }
+//
+//
+//    ///@todo load db name property as well?
+//
+//    tsk_release_lock(&hdb_info->lock);
+//
+//	return ret;
+//}
 
 /*
  * Close the sqlite index handle
@@ -845,6 +845,8 @@ sqlite_hdb_close(TSK_HDB_INFO* hdb_info)
     if (db_info->db) {
         sqlite3_close(db_info->db);
     }
+
+    // RJCTODO: Cleanup the base stuff...
 }
 
 /**
@@ -875,21 +877,6 @@ sqlite3_test(FILE * hFile)
     return 0;
 }
 
-// RJCTODO: Comment
-uint8_t
-sqlite_hdb_set_index_params(TSK_HDB_INFO *hdb_info, TSK_HDB_DBTYPE_ENUM hash_type)
-{
-    // The index is internal to the database, there is nothing to do.
-    return 0; 
-}
-
-// RJCTODO: Comment
-uint8_t sqlite_hdb_make_index(TSK_HDB_INFO *hdb_info, TSK_HDB_DBTYPE_ENUM hash_type)
-{
-    // The index is internal to the database, there is nothing to do.
-    return 0; 
-}
-
 // RJCTODO: Comment
 TSK_HDB_INFO *sqlite_hdb_open(TSK_TCHAR *db_path)
 {
diff --git a/tsk/hashdb/text_db.c b/tsk/hashdb/text_db.c
index f6cc96a7d548c0b477ae1e5f4d338c3cb7e9066d..aeb5641f9598439b787b8f4f552482fdeeaeed6d 100755
--- a/tsk/hashdb/text_db.c
+++ b/tsk/hashdb/text_db.c
@@ -16,6 +16,1132 @@
  * Functions common to all text hash databases.
  */
 
+// RJCTODO: Fix up function names in error messages
+// RJCTODO: Comment, etc.
+TSK_TEXT_HDB_INFO *text_hdb_open_db(FILE *hDb, const TSK_TCHAR *db_path)
+{
+    TSK_TEXT_HDB_INFO *text_hdb_info = NULL;
+    size_t flen = 0;
+
+    assert(NULL != db_path);
+    // RJCTODO: Add release build check
+
+    if ((text_hdb_info = (TSK_TEXT_HDB_INFO*)tsk_malloc(sizeof(TSK_TEXT_HDB_INFO))) == NULL) {
+        return NULL;
+    }
+
+    text_hdb_info->hDb = hDb;
+
+    flen = TSTRLEN(db_path) + 8; // RJCTODO: Check this change from 32 (change was in DF code) with Brian; was change in older code? What is the point, anyway?
+    text_hdb_info->base.db_fname = (TSK_TCHAR*)tsk_malloc(flen * sizeof(TSK_TCHAR));
+    if (NULL == text_hdb_info->base.db_fname) {
+        return NULL;
+    }
+    TSTRNCPY(text_hdb_info->base.db_fname, db_path, flen);
+    
+    text_hdb_info->base.updateable = 0;
+    text_hdb_info->base.uses_external_indexes = 1;
+    tsk_init_lock(&text_hdb_info->base.lock);
+
+    // Some text hash database types support indexes for more than one hash 
+    // type, so setting the hash type and length are deferred until the desired 
+    // index is created/opened.
+    text_hdb_info->hash_type = TSK_HDB_HTYPE_INVALID_ID; 
+    text_hdb_info->hash_len = 0; 
+
+    // The name, database type, and function pointers will need to be set 
+    // by the "derived class" caller these things vary by database type.
+    text_hdb_info->base.db_type = TSK_HDB_DBTYPE_INVALID_ID;
+    text_hdb_info->base.makeindex = NULL;
+    text_hdb_info->getentry = NULL;
+
+    return text_hdb_info;    
+}
+
+/** \internal
+ * Setup the hash-type specific information (such as length, index entry
+ * sizes, index name etc.) in the HDB_INFO structure.
+ *
+ * @param hdb_info Structure to fill in.
+ * @param htype Hash type being used
+ * @return 1 on error and 0 on success
+ */
+static uint8_t
+text_hdb_init_idx_hash_type_info(TSK_HDB_INFO * hdb_info_base, TSK_HDB_HTYPE_ENUM htype) // RJCTODO: Change to enum
+{
+    TSK_TEXT_HDB_INFO *hdb_info = (TSK_TEXT_HDB_INFO*)hdb_info_base; 
+    size_t flen = 0;
+
+    if (hdb_info->hash_type != 0) {
+        return 0;
+    }
+
+    /* Make the name for the index file */
+    flen = TSTRLEN(hdb_info_base->db_fname) + 32;
+    hdb_info->idx_fname =
+        (TSK_TCHAR *) tsk_malloc(flen * sizeof(TSK_TCHAR));
+    if (hdb_info->idx_fname == NULL) {
+        return 1;
+    }
+
+    /* Get hash type specific information */
+    switch (htype) {
+    case TSK_HDB_HTYPE_MD5_ID:
+        hdb_info->hash_type = htype;
+        hdb_info->hash_len = TSK_HDB_HTYPE_MD5_LEN;
+        hdb_info->idx_llen = TSK_HDB_IDX_LEN(htype);
+        TSNPRINTF(hdb_info->idx_fname, flen,
+                  _TSK_T("%s-%") PRIcTSK _TSK_T(".idx"),
+                  hdb_info_base->db_fname, TSK_HDB_HTYPE_MD5_STR);
+        return 0;
+    case TSK_HDB_HTYPE_SHA1_ID:
+        hdb_info->hash_type = htype;
+        hdb_info->hash_len = TSK_HDB_HTYPE_SHA1_LEN;
+        hdb_info->idx_llen = TSK_HDB_IDX_LEN(htype);
+        TSNPRINTF(hdb_info->idx_fname, flen,
+                  _TSK_T("%s-%") PRIcTSK _TSK_T(".idx"),
+                  hdb_info_base->db_fname, TSK_HDB_HTYPE_SHA1_STR);
+        return 0;
+    }
+
+    tsk_error_reset();
+    tsk_error_set_errno(TSK_ERR_HDB_ARG);
+    tsk_error_set_errstr(
+             "text_hdb_init_idx_hash_type_info: Invalid hash type as argument: %d", htype);
+    return 1;
+}
+
+/** \internal
+ * Setup the internal variables to read an index. This
+ * opens the index and sets the needed size information.
+ *
+ * @param hdb_info Hash database to analyze
+ * @param hash The hash type that was used to make the index.
+ *
+ * @return 1 on error and 0 on success
+ */
+static uint8_t
+text_hdb_open_idx(TSK_HDB_INFO * hdb_info_base, TSK_HDB_HTYPE_ENUM htype)
+{
+    TSK_TEXT_HDB_INFO *hdb_info = (TSK_TEXT_HDB_INFO*)hdb_info_base; 
+    char head[TSK_HDB_MAXLEN];
+    char head2[TSK_HDB_MAXLEN];
+    char *ptr;
+ 
+    // Lock for lazy load of hIdx and lazy alloc of idx_lbuf.
+    tsk_take_lock(&hdb_info_base->lock);
+
+    if (hdb_info->hIdx != NULL) {
+        tsk_release_lock(&hdb_info_base->lock);
+        return 0;
+    }
+
+    if ((htype != TSK_HDB_HTYPE_MD5_ID)
+        && (htype != TSK_HDB_HTYPE_SHA1_ID)) {
+        tsk_release_lock(&hdb_info_base->lock);
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_ARG);
+        tsk_error_set_errstr(
+                 "text_hdb_open_idx: Invalid hash type : %d", htype);
+        return 1;
+    }
+
+    if (text_hdb_init_idx_hash_type_info(hdb_info_base, htype)) {
+        tsk_release_lock(&hdb_info_base->lock);
+        return 1;
+    }
+
+    /* Verify the index exists, get its size, and open it */
+#ifdef TSK_WIN32
+    {
+        HANDLE hWin;
+        DWORD szLow, szHi;
+
+        if (-1 == GetFileAttributes(hdb_info->idx_fname)) {
+            tsk_release_lock(&hdb_info_base->lock);
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_MISSING);
+            tsk_error_set_errstr(
+                     "text_hdb_open_idx: Error finding index file: %"PRIttocTSK,
+                     hdb_info->idx_fname);
+            return 1;
+        }
+
+        if ((hWin = CreateFile(hdb_info->idx_fname, GENERIC_READ,
+                               FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0)) ==
+            INVALID_HANDLE_VALUE) {
+            tsk_release_lock(&hdb_info_base->lock);
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_OPEN);
+            tsk_error_set_errstr(
+                     "text_hdb_open_idx: Error opening index file: %"PRIttocTSK,
+                     hdb_info->idx_fname);
+            return 1;
+        }
+        hdb_info->hIdx =
+            _fdopen(_open_osfhandle((intptr_t) hWin, _O_RDONLY), "r");
+        if (hdb_info->hIdx == NULL) {
+            tsk_release_lock(&hdb_info_base->lock);
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_OPEN);
+            tsk_error_set_errstr(
+                     "text_hdb_open_idx: Error converting Windows handle to C handle");
+            return 1;
+        }
+
+        szLow = GetFileSize(hWin, &szHi);
+        if (szLow == 0xffffffff) {
+            tsk_release_lock(&hdb_info_base->lock);
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_OPEN);
+            tsk_error_set_errstr(
+                     "text_hdb_open_idx: Error getting size of index file: %"PRIttocTSK" - %d",
+                     hdb_info->idx_fname, (int)GetLastError());
+            return 1;
+        }
+        hdb_info->idx_size = szLow | ((uint64_t) szHi << 32);
+    }
+
+#else
+    {
+        struct stat sb;
+        if (stat(hdb_info->idx_fname, &sb) < 0) {
+            tsk_release_lock(&hdb_info_base->lock);
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_MISSING);
+            tsk_error_set_errstr(
+                     "text_hdb_open_idx: Error finding index file: %s",
+                     hdb_info->idx_fname);
+            return 1;
+        }
+        hdb_info->idx_size = sb.st_size;
+
+        if (NULL == (hdb_info->hIdx = fopen(hdb_info->idx_fname, "r"))) {
+            tsk_release_lock(&hdb_info_base->lock);
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_OPEN);
+            tsk_error_set_errstr(
+                     "text_hdb_open_idx: Error opening index file: %s",
+                     hdb_info->idx_fname);
+            return 1;
+        }
+    }
+#endif
+
+    /* Do some testing on the first line */
+    if (NULL == fgets(head, TSK_HDB_MAXLEN, hdb_info->hIdx)) {
+        tsk_release_lock(&hdb_info_base->lock);
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_READIDX);
+        tsk_error_set_errstr(
+                 "text_hdb_open_idx: Header line of index file");
+        return 1;
+    }
+
+    if (strncmp(head, TSK_HDB_IDX_HEAD_TYPE_STR, strlen(TSK_HDB_IDX_HEAD_TYPE_STR))
+        != 0) {
+        tsk_release_lock(&hdb_info_base->lock);
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_UNKTYPE);
+        tsk_error_set_errstr(
+                 "text_hdb_open_idx: Invalid index file: Missing header line");
+        return 1;
+    }
+
+    /* Do some testing on the second line */
+    if (NULL == fgets(head2, TSK_HDB_MAXLEN, hdb_info->hIdx)) {
+        tsk_release_lock(&hdb_info_base->lock);
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_READIDX);
+        tsk_error_set_errstr(
+                 "text_hdb_open_idx: Error reading line 2 of index file");
+        return 1;
+    }
+
+    /* Set the offset to the start of the index entries */
+    if (strncmp(head2, TSK_HDB_IDX_HEAD_NAME_STR, strlen(TSK_HDB_IDX_HEAD_NAME_STR))
+        != 0) {
+        hdb_info->idx_off = (uint16_t) (strlen(head));
+    } else {
+        hdb_info->idx_off = (uint16_t) (strlen(head) + strlen(head2));
+    }
+
+
+    /* Skip the space */
+    ptr = &head[strlen(TSK_HDB_IDX_HEAD_TYPE_STR) + 1];
+
+    ptr[strlen(ptr) - 1] = '\0';
+    if ((ptr[strlen(ptr) - 1] == 10) || (ptr[strlen(ptr) - 1] == 13)) {
+        ptr[strlen(ptr) - 1] = '\0';
+        hdb_info->idx_llen++;   // make the expected index length longer to account for different cr/nl/etc.
+    }
+
+    /* Verify the header value in the index */
+    if (strcmp(ptr, TSK_HDB_DBTYPE_NSRL_STR) == 0) {
+        if ((hdb_info_base->db_type != TSK_HDB_DBTYPE_NSRL_ID) &&
+            (hdb_info_base->db_type != TSK_HDB_DBTYPE_IDXONLY_ID)) {
+            tsk_release_lock(&hdb_info_base->lock);
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_UNKTYPE);
+            tsk_error_set_errstr(
+                     "hdb_indexsetup: DB detected as %s, index type has NSRL",
+                     ptr);
+            return 1;
+        }
+    }
+    else if (strcmp(ptr, TSK_HDB_DBTYPE_MD5SUM_STR) == 0) {
+        if ((hdb_info_base->db_type != TSK_HDB_DBTYPE_MD5SUM_ID) &&
+            (hdb_info_base->db_type != TSK_HDB_DBTYPE_IDXONLY_ID)) {
+            tsk_release_lock(&hdb_info_base->lock);
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_UNKTYPE);
+            tsk_error_set_errstr(
+                     "hdb_indexsetup: DB detected as %s, index type has MD5SUM",
+                     ptr);
+            return 1;
+        }
+    }
+    else if (strcmp(ptr, TSK_HDB_DBTYPE_HK_STR) == 0) {
+        if ((hdb_info_base->db_type != TSK_HDB_DBTYPE_HK_ID) &&
+            (hdb_info_base->db_type != TSK_HDB_DBTYPE_IDXONLY_ID)) {
+            tsk_release_lock(&hdb_info_base->lock);
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_UNKTYPE);
+            tsk_error_set_errstr(
+                     "hdb_indexsetup: DB detected as %s, index type has hashkeeper",
+                     ptr);
+            return 1;
+        }
+    }
+    else if (strcmp(ptr, TSK_HDB_DBTYPE_ENCASE_STR) == 0) {
+        if ((hdb_info_base->db_type != TSK_HDB_DBTYPE_ENCASE_ID) &&
+            (hdb_info_base->db_type != TSK_HDB_DBTYPE_IDXONLY_ID)) {
+            tsk_release_lock(&hdb_info_base->lock);
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_UNKTYPE);
+            tsk_error_set_errstr(
+                     "hdb_indexsetup: DB detected as %s, index type has EnCase",
+                     ptr);
+            return 1;
+        }
+    }
+    else if (hdb_info_base->db_type != TSK_HDB_DBTYPE_IDXONLY_ID) {
+        tsk_release_lock(&hdb_info_base->lock);
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_UNKTYPE);
+        tsk_error_set_errstr(
+                 "text_hdb_open_idx: Unknown Database Type in index header: %s",
+                 ptr);
+        return 1;
+    }
+
+    /* Do some sanity checking */
+    if (((hdb_info->idx_size - hdb_info->idx_off) % hdb_info->idx_llen) !=
+        0) {
+        tsk_release_lock(&hdb_info_base->lock);
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_CORRUPT);
+        tsk_error_set_errstr(
+                 "text_hdb_open_idx: Error, size of index file is not a multiple of row size");
+        return 1;
+    }
+
+    /* allocate a buffer for a row */
+    if ((hdb_info->idx_lbuf = tsk_malloc(hdb_info->idx_llen + 1)) == NULL) { // RJCTODO: Fix the warning/err
+        tsk_release_lock(&hdb_info_base->lock);
+        return 1;
+    }
+
+    tsk_release_lock(&hdb_info_base->lock);
+
+    return 0;
+}
+
+// RJCTODO: Put common open function for text hdbs here.
+
+/**
+ * \ingroup hashdblib
+ * Determine if the open hash database has an index.
+ *
+ * @param hdb_info Hash database to consider
+ * @param htype Hash type that index should be of
+ *
+ * @return 1 if index exists and 0 if not // RJCTODO: Consider changing to intb_t to allow for error code
+ */
+uint8_t
+tsk_text_hdb_has_index(TSK_HDB_INFO *hdb_info, TSK_HDB_HTYPE_ENUM htype)
+{
+    uint8_t ret_val = 0;
+    size_t flen = 0;
+    TSK_TCHAR *idx_path = NULL; 
+
+    flen = TSTRLEN(hdb_info->db_fname) + 32; // RJCTODO: Here it is again...
+    idx_path = (TSK_TCHAR*)tsk_malloc(flen * sizeof(TSK_TCHAR));
+    if (NULL == idx_path) {
+        return 0;
+    }
+
+    switch (htype) {
+        case TSK_HDB_HTYPE_MD5_ID:
+            TSNPRINTF(idx_path, flen,
+                      _TSK_T("%s-%") PRIcTSK _TSK_T(".idx"),
+                      hdb_info->db_fname, TSK_HDB_HTYPE_MD5_STR);
+            break;
+        case TSK_HDB_HTYPE_SHA1_ID:
+            TSNPRINTF(idx_path, flen,
+                      _TSK_T("%s-%") PRIcTSK _TSK_T(".idx"),
+                      hdb_info->db_fname, TSK_HDB_HTYPE_SHA1_STR);
+            break;
+        default:
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_ARG);
+            tsk_error_set_errstr(
+                     "tsk_text_hdb_has_index: Invalid hash type as argument: %d", htype);
+            return 0;
+    }
+
+    ret_val = hdb_file_exists(idx_path);
+    free(idx_path);
+    return ret_val;
+}
+
+// RJCTODO: Improve comment
+/** Initialize the TSK hash DB index file. This creates the intermediate file,
+ * which will have entries added to it.  This file must be sorted before the 
+ * process is finished.
+ *
+ * @param hdb_info Hash database state structure
+ * @param htype String of index type to create
+ *
+ * @return 1 on error and 0 on success
+ *
+ */
+uint8_t
+text_hdb_idx_init(TSK_HDB_INFO * hdb_info_base, TSK_TCHAR * htype)
+{
+    const char *func_name = "text_hdb_idx_init";
+    TSK_TEXT_HDB_INFO *hdb_info = (TSK_TEXT_HDB_INFO*)hdb_info_base; 
+    TSK_HDB_HTYPE_ENUM hash_type = TSK_HDB_HTYPE_INVALID_ID;
+    size_t flen = 0;
+    char dbtmp[32];
+    int i = 0;
+
+    /* Use the string of the index/hash type to figure out some
+     * settings */
+
+    // convert to char -- cheating way to deal with WCHARs..
+    for (i = 0; i < 31 && htype[i] != '\0'; i++) {
+        dbtmp[i] = (char) htype[i];
+    }
+    dbtmp[i] = '\0';
+
+    if (strcmp(dbtmp, TSK_HDB_DBTYPE_NSRL_MD5_STR) == 0) {
+
+        if (hdb_info_base->db_type != TSK_HDB_DBTYPE_NSRL_ID) {
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_ARG);
+            tsk_error_set_errstr(
+                     "%s: database detected as: %d index creation as: %d",
+                     func_name, hdb_info_base->db_type, TSK_HDB_DBTYPE_NSRL_ID);
+            return 1;
+        }
+        hash_type = TSK_HDB_HTYPE_MD5_ID;
+    }
+    else if (strcmp(dbtmp, TSK_HDB_DBTYPE_NSRL_SHA1_STR) == 0) {
+        if (hdb_info_base->db_type != TSK_HDB_DBTYPE_NSRL_ID) {
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_ARG);
+            tsk_error_set_errstr(
+                     "%s: database detected as: %d index creation as: %d",
+                     func_name, hdb_info_base->db_type, TSK_HDB_DBTYPE_NSRL_ID);
+            return 1;
+        }
+        hash_type = TSK_HDB_HTYPE_SHA1_ID;
+    }
+    else if (strcmp(dbtmp, TSK_HDB_DBTYPE_MD5SUM_STR) == 0) {
+        if (hdb_info_base->db_type != TSK_HDB_DBTYPE_MD5SUM_ID) {
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_ARG);
+            tsk_error_set_errstr(
+                     "%s: database detected as: %d index creation as: %d",
+                     func_name, hdb_info_base->db_type, TSK_HDB_DBTYPE_MD5SUM_ID);
+            return 1;
+        }
+        hash_type = TSK_HDB_HTYPE_MD5_ID;
+    }
+    else if (strcmp(dbtmp, TSK_HDB_DBTYPE_HK_STR) == 0) {
+        if (hdb_info_base->db_type != TSK_HDB_DBTYPE_HK_ID) {
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_ARG);
+            tsk_error_set_errstr(
+                     "%s: database detected as: %d index creation as: %d",
+                     func_name, hdb_info_base->db_type, TSK_HDB_DBTYPE_HK_ID);
+            return 1;
+        }
+        hash_type = TSK_HDB_HTYPE_MD5_ID;
+    }
+    else if (strcmp(dbtmp, TSK_HDB_DBTYPE_ENCASE_STR) == 0) {
+        if (hdb_info_base->db_type != TSK_HDB_DBTYPE_ENCASE_ID) {
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_ARG);
+            tsk_error_set_errstr(
+                     "%s: database detected as: %d index creation as: %d",
+                     func_name, hdb_info_base->db_type, TSK_HDB_DBTYPE_ENCASE_ID);
+            return 1;
+        }
+        hash_type = TSK_HDB_HTYPE_MD5_ID;
+    }
+    else {
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_ARG);
+        tsk_error_set_errstr(
+                 "%s: Unknown database/hash type request: %s",
+                 func_name, dbtmp);
+        return 1;
+    }
+
+    /* Setup the internal hash information */
+    if (text_hdb_init_idx_hash_type_info(hdb_info_base, hash_type = )) {
+        return 1;
+    }
+
+    /* Make the name for the unsorted intermediate index file */
+    flen = TSTRLEN(hdb_info_base->db_fname) + 32;
+    hdb_info->uns_fname =
+        (TSK_TCHAR *) tsk_malloc(flen * sizeof(TSK_TCHAR));
+    if (hdb_info->uns_fname == NULL) {
+        return 1;
+    }
+    TSNPRINTF(hdb_info->uns_fname, flen,
+              _TSK_T("%s-%") PRIcTSK _TSK_T("-ns.idx"), hdb_info_base->db_fname,
+              TSK_HDB_HTYPE_STR(hdb_info->hash_type));
+
+
+    /* Create temp unsorted file of offsets */
+#ifdef TSK_WIN32
+    {
+        HANDLE hWin;
+
+        if ((hWin = CreateFile(hdb_info->uns_fname, GENERIC_WRITE,
+                               0, 0, CREATE_ALWAYS, 0, 0)) ==
+            INVALID_HANDLE_VALUE) {
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_CREATE);
+            tsk_error_set_errstr(
+                     "%s: %"PRIttocTSK" GetFileSize: %d",
+                     func_name, hdb_info->uns_fname, (int)GetLastError());
+            return 1;
+        }
+
+        hdb_info->hIdxTmp =
+            _fdopen(_open_osfhandle((intptr_t) hWin, _O_WRONLY), "wb");
+        if (hdb_info->hIdxTmp == NULL) {
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_OPEN);
+            tsk_error_set_errstr(
+                     "%s: Error converting Windows handle to C handle", func_name);
+            free(hdb_info);
+            return 1;
+        }
+    }
+#else
+    if (NULL == (hdb_info->hIdxTmp = fopen(hdb_info->uns_fname, "w"))) {
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_CREATE);
+        tsk_error_set_errstr(
+                 "%s: Error creating temp index file: %s",
+                 func_name, hdb_info->uns_fname);
+        return 1;
+    }
+#endif
+
+    /* Print the header */
+    fprintf(hdb_info->hIdxTmp, "%s|%s\n", TSK_HDB_IDX_HEAD_NAME_STR,
+        hdb_info->db_name);
+    switch (hdb_info_base->db_type) {
+    case TSK_HDB_DBTYPE_NSRL_ID:
+       fprintf(hdb_info->hIdxTmp, "%s|%s\n", TSK_HDB_IDX_HEAD_TYPE_STR,
+            TSK_HDB_DBTYPE_NSRL_STR);
+        break;
+    case TSK_HDB_DBTYPE_MD5SUM_ID:
+        fprintf(hdb_info->hIdxTmp, "%s|%s\n", TSK_HDB_IDX_HEAD_TYPE_STR,
+            TSK_HDB_DBTYPE_MD5SUM_STR);
+        break;
+    case TSK_HDB_DBTYPE_HK_ID:
+        fprintf(hdb_info->hIdxTmp, "%s|%s\n", TSK_HDB_IDX_HEAD_TYPE_STR,
+            TSK_HDB_DBTYPE_HK_STR);
+        break;
+    case TSK_HDB_DBTYPE_ENCASE_ID:
+        fprintf(hdb_info->hIdxTmp, "%s|%s\n", TSK_HDB_IDX_HEAD_TYPE_STR,
+            TSK_HDB_DBTYPE_ENCASE_STR);
+        break;
+        /* Used to stop warning messages about missing enum value */
+    case TSK_HDB_DBTYPE_IDXONLY_ID:
+    default:
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_CREATE);
+        tsk_error_set_errstr("%s: Invalid db type", func_name);
+        return 1;
+    }
+
+    return 0;
+}
+
+/**
+ * Add a string entry to the intermediate index file.
+ *
+ * @param hdb_info Hash database state info
+ * @param hvalue String of hash value to add
+ * @param offset Byte offset of hash entry in original database.
+ * @return 1 on error and 0 on success
+ */
+uint8_t
+text_hdb_idx_add_entry(TSK_HDB_INFO * hdb_info_base, char *hvalue, TSK_OFF_T offset)
+{
+    TSK_TEXT_HDB_INFO *hdb_info = (TSK_TEXT_HDB_INFO*)hdb_info_base; 
+    int i;
+
+    // make the hashes all upper case
+    for (i = 0; hvalue[i] != '\0'; i++) {
+        if (islower((int) hvalue[i]))
+            fprintf(hdb_info->hIdxTmp, "%c", toupper((int) hvalue[i]));
+        else
+            fprintf(hdb_info->hIdxTmp, "%c", hvalue[i]);
+    }
+
+    /* Print the entry to the unsorted index file */
+    fprintf(hdb_info->hIdxTmp, "|%.16llu\n", (unsigned long long) offset);
+
+    return 0;
+}
+
+/**
+ * Add a binary entry to the intermediate index file.
+ *
+ * @param hdb_info Hash database state info
+ * @param hvalue Array of integers of hash value to add
+ * @param hlen Number of bytes in hvalue
+ * @param offset Byte offset of hash entry in original database.
+ * @return 1 on error and 0 on success
+ */
+uint8_t
+text_hdb_idx_add_entry_bin(TSK_HDB_INFO * hdb_info_base, unsigned char *hvalue, int hlen, TSK_OFF_T offset)
+{
+    TSK_TEXT_HDB_INFO *hdb_info = (TSK_TEXT_HDB_INFO*)hdb_info_base; 
+    int i;
+
+    for (i = 0; i < hlen; i++) {
+        fprintf(hdb_info->hIdxTmp, "%02X", hvalue[i]);
+    }
+
+    /* Print the entry to the unsorted index file */
+    fprintf(hdb_info->hIdxTmp, "|%.16llu\n", (unsigned long long) offset);
+
+    return 0;
+}
+
+/**
+ * Finalize index creation process by sorting the index and removing the
+ * intermediate temp file.
+ *
+ * @param hdb_info Hash database state info structure.
+ * @return 1 on error and 0 on success
+ */
+uint8_t
+text_hdb_idx_finalize(TSK_HDB_INFO * hdb_info_base)
+{
+    TSK_TEXT_HDB_INFO *hdb_info = (TSK_TEXT_HDB_INFO*)hdb_info_base; 
+
+#ifdef TSK_WIN32
+    wchar_t buf[TSK_HDB_MAXLEN];
+    /// @@ Expand this to be SYSTEM_ROOT -- GetWindowsDirectory()
+    wchar_t *sys32 = _TSK_T("C:\\WINDOWS\\System32\\sort.exe");
+    DWORD stat;
+    STARTUPINFO myStartInfo;
+    PROCESS_INFORMATION pinfo;
+
+    /* Close the unsorted file */
+    fclose(hdb_info->hIdxTmp);
+    hdb_info->hIdxTmp = NULL;
+
+    /* Close the existing index if it is open */
+    if (hdb_info->hIdx) {
+        fclose(hdb_info->hIdx);
+        hdb_info->hIdx = NULL;
+    }
+
+    if (tsk_verbose)
+        tsk_fprintf(stderr, "hdb_idxfinalize: Sorting index\n");
+
+    stat = GetFileAttributes(sys32);
+    if ((stat != -1) && ((stat & FILE_ATTRIBUTE_DIRECTORY) == 0)) {
+        TSNPRINTF(buf, TSK_HDB_MAXLEN, _TSK_T("%s /o \"%s\" \"%s\""),
+                  sys32, hdb_info->idx_fname, hdb_info->uns_fname);
+    }
+    else {
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_MISSING);
+        tsk_error_set_errstr("Cannot find sort executable");
+        return 1;
+    }
+
+    GetStartupInfo(&myStartInfo);
+
+    if (FALSE ==
+        CreateProcess(NULL, buf, NULL, NULL, FALSE, 0, NULL, NULL,
+                      &myStartInfo, &pinfo)) {
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_PROC);
+        tsk_error_set_errstr(
+                 "Error starting sorting index file using %S", buf);
+        return 1;
+    }
+
+    if (WAIT_FAILED == WaitForSingleObject(pinfo.hProcess, INFINITE)) {
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_PROC);
+        tsk_error_set_errstr(
+                 "Error (waiting) sorting index file using %S", buf);
+        return 1;
+    }
+
+    if (FALSE == DeleteFile(hdb_info->uns_fname)) {
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_DELETE);
+        tsk_error_set_errstr(
+                 "Error deleting temp file: %d", (int)GetLastError());
+        return 1;
+    }
+#else
+    char buf[TSK_HDB_MAXLEN];
+    char *root = "/bin/sort";
+    char *usr = "/usr/bin/sort";
+    char *local = "/usr/local/bin/sort";
+    struct stat stats;
+
+    if (tsk_verbose)
+        tsk_fprintf(stderr, "hdb_idxfinalize: Sorting index\n");
+
+    /* Close the unsorted file */
+    fclose(hdb_info->hIdxTmp);
+    hdb_info->hIdxTmp = NULL;
+
+    /* Close the existing index if it is open */
+    if (hdb_info->hIdx) {
+        fclose(hdb_info->hIdx);
+        hdb_info->hIdx = NULL;
+    }
+
+    if (0 == stat(local, &stats)) {
+        snprintf(buf, TSK_HDB_MAXLEN, "%s -o %s %s", local,
+                 hdb_info->idx_fname, hdb_info->uns_fname);
+    }
+    else if (0 == stat(usr, &stats)) {
+        snprintf(buf, TSK_HDB_MAXLEN, "%s -o \"%s\" \"%s\"",
+                 usr, hdb_info->idx_fname, hdb_info->uns_fname);
+    }
+    else if (0 == stat(root, &stats)) {
+        snprintf(buf, TSK_HDB_MAXLEN, "%s -o \"%s\" \"%s\"",
+                 root, hdb_info->idx_fname, hdb_info->uns_fname);
+    }
+    else {
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_MISSING);
+        tsk_error_set_errstr("Cannot find sort executable");
+        return 1;
+    }
+
+    if (0 != system(buf)) {
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_PROC);
+        tsk_error_set_errstr(
+                 "Error sorting index file using %s", buf);
+        return 1;
+    }
+
+    unlink(hdb_info->uns_fname);
+#endif
+
+    return 0;
+}
+
+/**
+ * \ingroup hashdblib
+ * Search the index for a text/ASCII hash value
+ *
+ * @param hdb_info Open hash database (with index)
+ * @param hash Hash value to search for (NULL terminated string)
+ * @param flags Flags to use in lookup
+ * @param action Callback function to call for each hash db entry 
+ * (not called if QUICK flag is given)
+ * @param ptr Pointer to data to pass to each callback
+ *
+ * @return -1 on error, 0 if hash value not found, and 1 if value was found.
+ */
+int8_t
+tsk_hdb_lookup_str(TSK_HDB_INFO * hdb_info_base, const char *hash,
+                   TSK_HDB_FLAG_ENUM flags, TSK_HDB_LOOKUP_FN action,
+                   void *ptr)
+{
+    TSK_TEXT_HDB_INFO *hdb_info = (TSK_TEXT_HDB_INFO*)hdb_info_base; 
+    TSK_OFF_T poffset;
+    TSK_OFF_T up;               // Offset of the first byte past the upper limit that we are looking in
+    TSK_OFF_T low;              // offset of the first byte of the lower limit that we are looking in
+    int cmp;
+    uint8_t wasFound = 0;
+    size_t i;
+    uint8_t htype;
+
+
+    /* Sanity checks on the hash input */
+    if (strlen(hash) == TSK_HDB_HTYPE_MD5_LEN) {
+        htype = TSK_HDB_HTYPE_MD5_ID;
+    }
+    else if (strlen(hash) == TSK_HDB_HTYPE_SHA1_LEN) {
+        htype = TSK_HDB_HTYPE_SHA1_ID;
+    }
+    else {
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_ARG);
+        tsk_error_set_errstr(
+                 "hdb_lookup: Invalid hash length: %s", hash);
+        return -1;
+    }
+
+    for (i = 0; i < strlen(hash); i++) {
+        if (isxdigit((int) hash[i]) == 0) {
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_ARG);
+            tsk_error_set_errstr(
+                     "hdb_lookup: Invalid hash value (hex only): %s",
+                     hash);
+            return -1;
+        }
+    }
+
+    if (text_hdb_open_idx(hdb_info_base, htype))
+        return -1;
+
+
+    /* Sanity check */
+    if (hdb_info->hash_len != strlen(hash)) {
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_ARG);
+        tsk_error_set_errstr(
+                 "hdb_lookup: Hash passed is different size than expected (%d vs %Zd)",
+                 hdb_info->hash_len, strlen(hash));
+        return -1;
+    }
+
+
+    low = hdb_info->idx_off;
+    up = hdb_info->idx_size;
+
+    poffset = 0;
+
+    // We have to lock access to idx_lbuf, but since we're in a loop,
+    // I'm assuming one lock up front is better than many inside.
+    tsk_take_lock(&hdb_info_base->lock);
+
+    while (1) {
+        TSK_OFF_T offset;
+
+        /* If top and bottom are the same, it's not there */
+        if (up == low) {
+            tsk_release_lock(&hdb_info_base->lock);
+            return 0;
+        }
+
+        /* Get the middle of the windows that we are looking at */
+        offset = rounddown(((up - low) / 2), hdb_info->idx_llen);
+
+        /* Sanity Check */
+        if ((offset % hdb_info->idx_llen) != 0) {
+            tsk_release_lock(&hdb_info_base->lock);
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_CORRUPT);
+            tsk_error_set_errstr(
+                     "hdb_lookup: Error, new offset is not a multiple of the line length");
+            return -1;
+        }
+
+        /* The middle offset is relative to the low offset, so add them */
+        offset += low;
+
+        /* If we didn't move, then it's not there */
+        if (poffset == offset) {
+            tsk_release_lock(&hdb_info_base->lock);
+            return 0;
+        }
+
+        /* Seek to the offset and read it */
+        if (0 != fseeko(hdb_info->hIdx, offset, SEEK_SET)) {
+            tsk_release_lock(&hdb_info_base->lock);
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_READIDX);
+            tsk_error_set_errstr(
+                     "hdb_lookup: Error seeking in search: %" PRIuOFF,
+                     offset);
+            return -1;
+        }
+
+        if (NULL ==
+            fgets(hdb_info->idx_lbuf, (int) hdb_info->idx_llen + 1,
+                  hdb_info->hIdx)) {
+            if (feof(hdb_info->hIdx)) {
+                tsk_release_lock(&hdb_info_base->lock);
+                return 0;
+            }
+            tsk_release_lock(&hdb_info_base->lock);
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_READIDX);
+            tsk_error_set_errstr(
+                     "Error reading index file: %lu",
+                     (unsigned long) offset);
+            return -1;
+        }
+
+        /* Sanity Check */
+        if ((strlen(hdb_info->idx_lbuf) < hdb_info->idx_llen) ||
+            (hdb_info->idx_lbuf[hdb_info->hash_len] != '|')) {
+            tsk_release_lock(&hdb_info_base->lock);
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_HDB_CORRUPT);
+            tsk_error_set_errstr(
+                     "Invalid line in index file: %lu (%s)",
+                     (unsigned long) (offset / hdb_info->idx_llen),
+                     hdb_info->idx_lbuf);
+            return -1;
+        }
+
+        /* Set the delimter to NULL so we can treat the hash as a string */
+        hdb_info->idx_lbuf[hdb_info->hash_len] = '\0';
+        cmp = strcasecmp(hdb_info->idx_lbuf, hash);
+
+        /* The one we just read is too small, so set the new lower bound
+         * at the start of the next row */
+        if (cmp < 0) {
+            low = offset + hdb_info->idx_llen;
+        }
+
+        /* The one we just read is too big, so set the upper bound at this
+         * entry */
+        else if (cmp > 0) {
+            up = offset;
+        }
+
+        /* We found it */
+        else {
+            wasFound = 1;
+
+            if ((flags & TSK_HDB_FLAG_QUICK)
+                || (hdb_info_base->db_type == TSK_HDB_DBTYPE_IDXONLY_ID)) {
+                tsk_release_lock(&hdb_info_base->lock);
+                return 1;
+            }
+            else {
+                TSK_OFF_T tmpoff, db_off;
+
+#ifdef TSK_WIN32
+                db_off =
+                    _atoi64(&hdb_info->idx_lbuf[hdb_info->hash_len + 1]);
+#else
+                db_off =
+                    strtoull(&hdb_info->idx_lbuf[hdb_info->hash_len + 1],
+                             NULL, 10);
+#endif
+
+                /* Print the one that we found first */
+                if (hdb_info->
+                    getentry(hdb_info_base, hash, db_off, flags, action, ptr)) {
+                    tsk_release_lock(&hdb_info_base->lock);
+                    tsk_error_set_errstr2( "hdb_lookup");
+                    return -1;
+                }
+
+
+                /* there could be additional entries both before and after
+                 * this entry - but we can restrict ourselves to the up
+                 * and low bounds from our previous hunting 
+                 */
+
+                tmpoff = offset - hdb_info->idx_llen;
+                while (tmpoff >= low) {
+
+                    /* Break if we are at the header */
+                    if (tmpoff <= 0)
+                        break;
+
+                    if (0 != fseeko(hdb_info->hIdx, tmpoff, SEEK_SET)) {
+                        tsk_release_lock(&hdb_info_base->lock);
+                        tsk_error_reset();
+                        tsk_error_set_errno(TSK_ERR_HDB_READIDX);
+                        tsk_error_set_errstr(
+                                 "hdb_lookup: Error seeking for prev entries: %"
+                                 PRIuOFF, tmpoff);
+                        return -1;
+                    }
+
+                    if (NULL ==
+                        fgets(hdb_info->idx_lbuf,
+                              (int) hdb_info->idx_llen + 1,
+                              hdb_info->hIdx)) {
+                        tsk_release_lock(&hdb_info_base->lock);
+                        tsk_error_reset();
+                        tsk_error_set_errno(TSK_ERR_HDB_READIDX);
+                        tsk_error_set_errstr(
+                                 "Error reading index file (prev): %lu",
+                                 (unsigned long) tmpoff);
+                        return -1;
+                    }
+                    else if (strlen(hdb_info->idx_lbuf) <
+                             hdb_info->idx_llen) {
+                        tsk_release_lock(&hdb_info_base->lock);
+                        tsk_error_reset();
+                        tsk_error_set_errno(TSK_ERR_HDB_CORRUPT);
+                        tsk_error_set_errstr(
+                                 "Invalid index file line (prev): %lu",
+                                 (unsigned long) tmpoff);
+                        return -1;
+                    }
+
+                    hdb_info->idx_lbuf[hdb_info->hash_len] = '\0';
+                    if (strcasecmp(hdb_info->idx_lbuf, hash) != 0) {
+                        break;
+                    }
+
+#ifdef TSK_WIN32
+                    db_off =
+                        _atoi64(&hdb_info->
+                                idx_lbuf[hdb_info->hash_len + 1]);
+#else
+
+                    db_off =
+                        strtoull(&hdb_info->
+                                 idx_lbuf[hdb_info->hash_len + 1], NULL,
+                                 10);
+#endif
+                    if (hdb_info->
+                        getentry(hdb_info_base, hash, db_off, flags, action,
+                                 ptr)) {
+                        tsk_release_lock(&hdb_info_base->lock);
+                        return -1;
+                    }
+                    tmpoff -= hdb_info->idx_llen;
+                }
+
+                /* next entries */
+                tmpoff = offset + hdb_info->idx_llen;
+                while (tmpoff < up) {
+
+                    if (0 != fseeko(hdb_info->hIdx, tmpoff, SEEK_SET)) {
+                        tsk_release_lock(&hdb_info_base->lock);
+                        tsk_error_reset();
+                        tsk_error_set_errno(TSK_ERR_HDB_READIDX);
+                        tsk_error_set_errstr(
+                                 "hdb_lookup: Error seeking for next entries: %"
+                                 PRIuOFF, tmpoff);
+                        return -1;
+                    }
+
+                    if (NULL ==
+                        fgets(hdb_info->idx_lbuf,
+                              (int) hdb_info->idx_llen + 1,
+                              hdb_info->hIdx)) {
+                        if (feof(hdb_info->hIdx))
+                            break;
+                        tsk_release_lock(&hdb_info_base->lock);
+                        tsk_error_reset();
+                        tsk_error_set_errno(TSK_ERR_HDB_READIDX);
+                        tsk_error_set_errstr(
+                                 "Error reading index file (next): %lu",
+                                 (unsigned long) tmpoff);
+                        return -1;
+                    }
+                    else if (strlen(hdb_info->idx_lbuf) <
+                             hdb_info->idx_llen) {
+                        tsk_release_lock(&hdb_info_base->lock);
+                        tsk_error_reset();
+                        tsk_error_set_errno(TSK_ERR_HDB_CORRUPT);
+                        tsk_error_set_errstr(
+                                 "Invalid index file line (next): %lu",
+                                 (unsigned long) tmpoff);
+                        return -1;
+                    }
+
+                    hdb_info->idx_lbuf[hdb_info->hash_len] = '\0';
+                    if (strcasecmp(hdb_info->idx_lbuf, hash) != 0) {
+                        break;
+                    }
+#ifdef TSK_WIN32
+                    db_off =
+                        _atoi64(&hdb_info->
+                                idx_lbuf[hdb_info->hash_len + 1]);
+#else
+                    db_off =
+                        strtoull(&hdb_info->
+                                 idx_lbuf[hdb_info->hash_len + 1], NULL,
+                                 10);
+#endif
+                    if (hdb_info->
+                        getentry(hdb_info_base, hash, db_off, flags, action,
+                                 ptr)) {
+                        tsk_release_lock(&hdb_info_base->lock);
+                        return -1;
+                    }
+
+                    tmpoff += hdb_info->idx_llen;
+                }
+            }
+            break;
+        }
+        poffset = offset;
+    }
+    tsk_release_lock(&hdb_info_base->lock);
+
+    return wasFound;
+}
+
+/**
+ * \ingroup hashdblib
+ * Search the index for the given hash value given (in binary form).
+ *
+ * @param hdb_info Open hash database (with index)
+ * @param hash Array with binary hash value to search for
+ * @param len Number of bytes in binary hash value
+ * @param flags Flags to use in lookup
+ * @param action Callback function to call for each hash db entry 
+ * (not called if QUICK flag is given)
+ * @param ptr Pointer to data to pass to each callback
+ *
+ * @return -1 on error, 0 if hash value not found, and 1 if value was found.
+ */
+int8_t
+tsk_hdb_lookup_raw(TSK_HDB_INFO * hdb_info, uint8_t * hash, uint8_t len,
+                   TSK_HDB_FLAG_ENUM flags,
+                   TSK_HDB_LOOKUP_FN action, void *ptr)
+{
+    char hashbuf[TSK_HDB_HTYPE_SHA1_LEN + 1];
+    int i;
+    static const char hex[] = "0123456789abcdef";
+
+    if (2 * len > TSK_HDB_HTYPE_SHA1_LEN) {
+        tsk_error_reset();
+        tsk_error_set_errno(TSK_ERR_HDB_ARG);
+        tsk_error_set_errstr(
+                 "tsk_hdb_lookup_raw: hash value too long\n");
+        return -1;
+    }
+
+    for (i = 0; i < len; i++) {
+        hashbuf[2 * i] = hex[(hash[i] >> 4) & 0xf];
+        hashbuf[2 * i + 1] = hex[hash[i] & 0xf];
+    }
+    hashbuf[2 * len] = '\0';
+
+    return tsk_hdb_lookup_str(hdb_info, hashbuf, flags, action, ptr);
+}
+
 void
 text_db_close(TSK_HDB_INFO *hdb_info) 
 {
diff --git a/tsk/hashdb/tsk_hashdb.h b/tsk/hashdb/tsk_hashdb.h
index 2d58efd4affa9c44f111caa45aefd4bb48096f7e..05f82c6b5c169e5a3817cab4559645a329cea5a5 100644
--- a/tsk/hashdb/tsk_hashdb.h
+++ b/tsk/hashdb/tsk_hashdb.h
@@ -2,7 +2,7 @@
  * The Sleuth Kit
  *
  * Brian Carrier [carrier <at> sleuthkit [dot] org]
- * Copyright (c) 2003-2011 Brian Carrier.  All rights reserved
+ * Copyright (c) 2003-2014 Brian Carrier.  All rights reserved
  */
 
 /**
@@ -116,26 +116,26 @@ extern "C" {
         const char *name,
         void *);
 
-    typedef struct TSK_HDB_EXTERNAL_IDX_INFO {
-        char db_name[TSK_HDB_NAME_MAXLEN];          ///< Name of the database // RJCTODO: This is probably only needed for an indexed db
-        uint8_t(*open)(TSK_HDB_INFO *, uint8_t);
-        uint8_t(*initialize)(TSK_HDB_INFO *, TSK_TCHAR *);
-        uint8_t(*addentry)(TSK_HDB_INFO *, char *, TSK_OFF_T);
-        uint8_t(*addentry_bin)(TSK_HDB_INFO *, unsigned char *, int, TSK_OFF_T);
-        uint8_t(*finalize)(TSK_HDB_INFO *);
-        void(*close)(TSK_HDB_INFO *);
-    } TSK_HDB_EXTERNAL_IDX_INFO;
-
-    typedef struct TSK_HDB_BINSRCH_IDX_INFO {
-        TSK_HDB_EXTERNAL_IDX_INFO base;
-        FILE *hIdx;             ///< File handle to index (only open during lookups)
-        FILE *hIdxTmp;          ///< File handle to temp (unsorted) index file (only open during index creation)
-        TSK_TCHAR *uns_fname;   ///< Name of unsorted index file
-        TSK_OFF_T idx_size;     ///< Size of index file
-        uint16_t idx_off;       ///< Offset in index file to first index entry
-        size_t idx_llen;        ///< Length of each line in index
-        char *idx_lbuf;         ///< Buffer to hold a line from the index  (r/w shared - lock) 
-    } TSK_HDB_BINSRCH_IDX_INFO;    
+    //typedef struct TSK_HDB_EXTERNAL_IDX_INFO {
+    //    char db_name[TSK_HDB_NAME_MAXLEN];          ///< Name of the database // RJCTODO: This is probably only needed for an indexed db
+    //    uint8_t(*open)(TSK_HDB_INFO *, uint8_t);
+    //    uint8_t(*initialize)(TSK_HDB_INFO *, TSK_TCHAR *);
+    //    uint8_t(*addentry)(TSK_HDB_INFO *, char *, TSK_OFF_T);
+    //    uint8_t(*addentry_bin)(TSK_HDB_INFO *, unsigned char *, int, TSK_OFF_T);
+    //    uint8_t(*finalize)(TSK_HDB_INFO *);
+    //    void(*close)(TSK_HDB_INFO *);
+    //} TSK_HDB_EXTERNAL_IDX_INFO;
+
+    //typedef struct TSK_HDB_BINSRCH_IDX_INFO {
+    //    TSK_HDB_EXTERNAL_IDX_INFO base;
+    //    FILE *hIdx;             ///< File handle to index (only open during lookups)
+    //    FILE *hIdxTmp;          ///< File handle to temp (unsorted) index file (only open during index creation)
+    //    TSK_TCHAR *uns_fname;   ///< Name of unsorted index file
+    //    TSK_OFF_T idx_size;     ///< Size of index file
+    //    uint16_t idx_off;       ///< Offset in index file to first index entry
+    //    size_t idx_llen;        ///< Length of each line in index
+    //    char *idx_lbuf;         ///< Buffer to hold a line from the index  (r/w shared - lock) 
+    //} TSK_HDB_BINSRCH_IDX_INFO;    
 
     /**
      * Holds information about an open hash database. Created by 
@@ -143,13 +143,13 @@ extern "C" {
      */
     struct TSK_HDB_INFO {
         TSK_TCHAR *db_fname;          ///< Database file path, may be NULL for index only database
-        TSK_TCHAR *idx_fname;         ///< Name of index file, may be NULL for database without external index
         TSK_HDB_DBTYPE_ENUM db_type;  ///< Type of database
         uint8_t updateable;           ///< Allow new entries to be added? // RJCTODO: Could be done by dbtype, as is also true for 
-        uint8_t uses_external_index;           
-        TSK_HDB_HTYPE_ENUM hash_type; ///< Type of hash used in index // RJCTODO: Not needed for SQLITE?
-        uint16_t hash_len;            ///< Length of hash // RJCTODO: Not needed for SQLITE?
+        uint8_t uses_external_indexes;           
+        //TSK_HDB_HTYPE_ENUM hash_type; ///< Type of hash used in index // RJCTODO: Not needed for SQLITE?
+        //uint16_t hash_len;            ///< Length of hash // RJCTODO: Not needed for SQLITE?
         tsk_lock_t lock;              ///< Lock for lazy loading and idx_lbuf
+        uint8_t(*has_index)(TSK_HDB_INFO *, TSK_HDB_HTYPE_ENUM);
         uint8_t(*makeindex)(TSK_HDB_INFO *, TSK_TCHAR *);     ///< \internal Database-specific function to make index 
         uint8_t(*set_index_params)(TSK_HDB_INFO *hdb_info, TSK_HDB_DBTYPE_ENUM htype);
         int8_t(*lookup_str)(TSK_HDB_INFO *, const char *, TSK_HDB_FLAG_ENUM, TSK_HDB_LOOKUP_FN, void *);
@@ -161,9 +161,20 @@ extern "C" {
 
     typedef struct TSK_TEXT_HDB_INFO {
         TSK_HDB_INFO base;
+        char db_name[TSK_HDB_NAME_MAXLEN];          ///< Name of the database // RJCTODO: This is probably only needed for an indexed db
         FILE *hDb;              ///< File handle to database (always open)
         uint8_t(*getentry) (TSK_HDB_INFO *, const char *, TSK_OFF_T, TSK_HDB_FLAG_ENUM, TSK_HDB_LOOKUP_FN, void *);    ///< \internal Database-specific function to find entry at a given offset // RJCTODO: Text DB thing
-        TSK_HDB_EXTERNAL_IDX_INFO *idx;
+        //TSK_HDB_EXTERNAL_IDX_INFO *idx;
+        TSK_HDB_HTYPE_ENUM hash_type; ///< Type of hash used in index // RJCTODO: Not needed for SQLITE?
+        uint16_t hash_len;            ///< Length of hash // RJCTODO: Not needed for SQLITE?
+        TSK_TCHAR *idx_fname;         ///< Name of index file, may be NULL for database without external index
+        FILE *hIdx;             ///< File handle to index (only open during lookups)
+        FILE *hIdxTmp;          ///< File handle to temp (unsorted) index file (only open during index creation)
+        TSK_TCHAR *uns_fname;   ///< Name of unsorted index file
+        TSK_OFF_T idx_size;     ///< Size of index file
+        uint16_t idx_off;       ///< Offset in index file to first index entry
+        size_t idx_llen;        ///< Length of each line in index
+        char *idx_lbuf;         ///< Buffer to hold a line from the index  (r/w shared - lock) 
     } TSK_TEXT_HDB_INFO;    
 
     typedef struct TSK_SQLITE_HDB_INFO {
@@ -188,7 +199,8 @@ extern "C" {
 
     extern void tsk_hdb_close(TSK_HDB_INFO * hdb_info);
 
-    extern uint8_t tsk_hdb_hasindex(TSK_HDB_INFO *, uint8_t htype);
+    extern uint8_t tsk_hdb_hasindex(TSK_HDB_INFO *, uint8_t htype); // RJCTODO: to go away
+    extern uint8_t tsk_text_hdb_has_index(TSK_HDB_INFO * hdb_info, TSK_HDB_HTYPE_ENUM htype);
 
     extern uint8_t tsk_set_index_params(TSK_HDB_INFO *hdb_info, TSK_HDB_DBTYPE_ENUM htype);
     
@@ -200,7 +212,7 @@ extern "C" {
 
     extern uint8_t tsk_hdb_regenerate_index(TSK_HDB_INFO *, TSK_TCHAR *, uint8_t);
 
-    extern int8_t tsk_hdb_add_str(TSK_HDB_INFO * hdb_info, 
+    extern int8_t tsk_hdb_add_hash(TSK_HDB_INFO * hdb_info, 
                         const char * filename, 
                         const char * md5, 
                         const char * sha1, 
diff --git a/tsk/hashdb/tsk_hashdb_i.h b/tsk/hashdb/tsk_hashdb_i.h
index 895696c42e4a4e4e96ef484b897d06205d57aafb..1fd05d8d27dae2c702fafdd5b45c767f18091c5d 100644
--- a/tsk/hashdb/tsk_hashdb_i.h
+++ b/tsk/hashdb/tsk_hashdb_i.h
@@ -72,6 +72,9 @@ extern "C" {
 // Warning: changing the hash storage type changes the Db schema
 //#define IDX_SQLITE_STORE_TEXT 
 
+    // Utils RJCTODO
+    extern uint8_t hdb_file_exists(TSK_TCHAR *file_path);
+
     // "Generic" functions that apply to all types or delegate to hash database type-specific functions. 
     extern uint8_t hdb_setupindex(TSK_HDB_INFO * hdb_info, uint8_t htype); // RJCTODO: Where is the tsk_ ?
     extern void tsk_idx_close(TSK_HDB_INFO * hdb_info);
@@ -83,6 +86,11 @@ extern "C" {
     extern void tsk_hdb_name_from_path(TSK_HDB_INFO *);
 
     // Hash database functions common to all text hash databases.
+    extern TSK_TEXT_HDB_INFO *text_hdb_open(FILE *hDb, const TSK_TCHAR *db_path);
+    extern uint8_t text_hdb_idx_init(TSK_HDB_INFO *, TSK_TCHAR *);
+    extern uint8_t text_hdb_idx_add_entry(TSK_HDB_INFO *, char *, TSK_OFF_T);
+    extern uint8_t text_hdb_idx_finalize(TSK_HDB_INFO *);
+
     extern void text_db_close(TSK_HDB_INFO *hdb_info) ;
 
     // Hash database functions for NSRL hash databases. 
@@ -121,7 +129,7 @@ extern "C" {
                                TSK_HDB_FLAG_ENUM, TSK_HDB_LOOKUP_FN,
                                void *);
 
-    // Hash database functions for ASCII index files standing in for the original hash databases. 
+    // Hash database functions for text index files standing in for the original hash databases. 
     extern TSK_HDB_INFO *idxonly_open(const TSK_TCHAR *db_path);
     extern void idxonly_name(TSK_HDB_INFO *);
     extern uint8_t idxonly_makeindex(TSK_HDB_INFO *, TSK_TCHAR * htype);
@@ -132,7 +140,7 @@ extern "C" {
     // Hash database functions for SQLite hash databases.
     extern TSK_HDB_INFO *sqlite_hdb_open(TSK_TCHAR *db_path);
     extern uint8_t sqlite_hdb_set_index_params(TSK_HDB_INFO *hdb_info, TSK_HDB_DBTYPE_ENUM hash_type); 
-    extern uint8_t sqlite_hdb_make_index(TSK_HDB_INFO *hdb_info, TSK_HDB_DBTYPE_ENUM hash_type); // RJCTODO: Probably do not need type, set by above func
+    extern uint8_t sqlite_hdb_make_index(TSK_HDB_INFO *, TSK_TCHAR * htype);
 
     // Index functions for ASCII indexes for hash databases. 
     extern uint8_t binsrch_open(TSK_HDB_INFO * hdb_info, uint8_t htype);
@@ -151,21 +159,14 @@ extern "C" {
     extern int8_t binsrch_get_properties(TSK_HDB_INFO * hdb_info);
 
     // Hash database and index functions for SQLite hash databases.
-    extern uint8_t sqlite_hdb_make_index(TSK_HDB_INFO *, TSK_TCHAR * htype);
     extern uint8_t sqlite_hdb_get_entry(TSK_HDB_INFO *, const char *, TSK_OFF_T, TSK_HDB_FLAG_ENUM, TSK_HDB_LOOKUP_FN, void *);
 	extern uint8_t sqlite_hdb_create_db(TSK_TCHAR*);
     extern sqlite3 *sqlite_hdb_open_db(TSK_TCHAR*);
     extern void sqlite_hdb_close(TSK_HDB_INFO*);
-    extern uint8_t sqlite_v1_initialize(TSK_HDB_INFO *, TSK_TCHAR *);
-    extern uint8_t sqlite_v1_begin(TSK_HDB_INFO *);
-    extern uint8_t sqlite_v1_addentry(TSK_HDB_INFO *, char *, TSK_OFF_T);
-    extern uint8_t sqlite_v1_addentry_bin(TSK_HDB_INFO *, unsigned char *, int, TSK_OFF_T);
-    extern uint8_t sqlite_v1_finalize(TSK_HDB_INFO *);
     extern int8_t sqlite_v1_lookup_str(TSK_HDB_INFO *, const char *, TSK_HDB_FLAG_ENUM, TSK_HDB_LOOKUP_FN, void *);
     extern int8_t sqlite_v1_lookup_raw(TSK_HDB_INFO *, uint8_t *, uint8_t, TSK_HDB_FLAG_ENUM, TSK_HDB_LOOKUP_FN, void *);
     extern void * sqlite_v1_getAllData(TSK_HDB_INFO *, unsigned long hashId);
     extern int8_t sqlite_v1_get_properties(TSK_HDB_INFO * hdb_info);
-    extern uint8_t sqlite3_test(FILE *);
 
 #ifdef __cplusplus
 }
diff --git a/win32/libtsk/libtsk.vcxproj b/win32/libtsk/libtsk.vcxproj
index d42284f753bf4589d1a372e3d1c608ec8b5233de..0eec65eb9ca2ee49d408ef5032222bba390a1cf5 100755
--- a/win32/libtsk/libtsk.vcxproj
+++ b/win32/libtsk/libtsk.vcxproj
@@ -293,6 +293,7 @@ copy "$(LIBEWF_HOME)\msvscpp\x64\release\zlib.dll" "$(OutDir)"
     <ClCompile Include="..\..\tsk\img\raw.c" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="..\..\tsk\hashdb\sqlite_index.h" />
     <ClInclude Include="..\..\tsk\vs\tsk_bsd.h" />
     <ClInclude Include="..\..\tsk\vs\tsk_dos.h" />
     <ClInclude Include="..\..\tsk\vs\tsk_gpt.h" />
diff --git a/win32/libtsk/libtsk.vcxproj.filters b/win32/libtsk/libtsk.vcxproj.filters
index 2c6324ccdb8ca1c8d8bf6d15ccf1bd54a8835df2..a798dcd7956a6e97eeae795ea2d147dc1987eabb 100755
--- a/win32/libtsk/libtsk.vcxproj.filters
+++ b/win32/libtsk/libtsk.vcxproj.filters
@@ -379,5 +379,8 @@
       <Filter>img</Filter>
     </ClInclude>
     <ClInclude Include="..\..\tsk\fs\tsk_yaffs.h" />
+    <ClInclude Include="..\..\tsk\hashdb\sqlite_index.h">
+      <Filter>hash</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file