diff --git a/bindings/java/jni/auto_db_java.cpp b/bindings/java/jni/auto_db_java.cpp index 969d87ba117d3a9b4959ad27feb27c116d42b62f..eb009c7d3f80e656ef39259b29e6c02bffff095f 100644 --- a/bindings/java/jni/auto_db_java.cpp +++ b/bindings/java/jni/auto_db_java.cpp @@ -79,7 +79,7 @@ TskAutoDbJava::initializeJni(JNIEnv * jniEnv, jobject jobj) { } m_callbackClass = (jclass)m_jniEnv->NewGlobalRef(localCallbackClass); - m_addImageMethodID = m_jniEnv->GetMethodID(m_callbackClass, "addImageInfo", "(IJLjava/lang/String;JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J"); + m_addImageMethodID = m_jniEnv->GetMethodID(m_callbackClass, "addImageInfo", "(IJLjava/lang/String;JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)J"); if (m_addImageMethodID == NULL) { return TSK_ERR; } @@ -184,7 +184,8 @@ TskAutoDbJava::getObjectInfo(uint64_t objId, TSK_DB_OBJECT** obj_info) { */ TSK_RETVAL_ENUM TskAutoDbJava::addImageInfo(int type, TSK_OFF_T ssize, int64_t & objId, const string & timezone, TSK_OFF_T size, const string &md5, - const string& sha1, const string& sha256, const string& deviceId, const string& collectionDetails) { + const string& sha1, const string& sha256, const string& deviceId, const string& collectionDetails, + char** img_ptrs, int num_imgs) { const char *tz_cstr = timezone.c_str(); jstring tzj = m_jniEnv->NewStringUTF(tz_cstr); @@ -204,8 +205,18 @@ TskAutoDbJava::addImageInfo(int type, TSK_OFF_T ssize, int64_t & objId, const st const char *coll_cstr = collectionDetails.c_str(); jstring collj = m_jniEnv->NewStringUTF(coll_cstr); + jobjectArray imgNamesj = (jobjectArray)m_jniEnv->NewObjectArray( + num_imgs, + m_jniEnv->FindClass("java/lang/String"), + m_jniEnv->NewStringUTF("")); + + for (int i = 0; i < num_imgs; i++) { + m_jniEnv->SetObjectArrayElement( + imgNamesj, i, m_jniEnv->NewStringUTF(img_ptrs[i])); + } + jlong objIdj = m_jniEnv->CallLongMethod(m_javaDbObj, m_addImageMethodID, - type, ssize, tzj, size, md5j, sha1j, sha256j, devIdj, collj); + type, ssize, tzj, size, md5j, sha1j, sha256j, devIdj, collj, imgNamesj); objId = (int64_t)objIdj; if (objId < 0) { @@ -1003,13 +1014,6 @@ TskAutoDbJava::addImageDetails(const char* deviceId) } else { devId = ""; } - if (TSK_OK != addImageInfo(m_img_info->itype, m_img_info->sector_size, - m_curImgId, m_curImgTZone, m_img_info->size, md5, sha1, "", devId, collectionDetails)) { - registerError(); - return 1; - } - - char **img_ptrs; #ifdef TSK_WIN32 @@ -1043,14 +1047,12 @@ TskAutoDbJava::addImageDetails(const char* deviceId) img_ptrs = m_img_info->images; #endif - // Add the image names - for (int i = 0; i < m_img_info->num_img; i++) { - const char *img_ptr = img_ptrs[i]; - if (TSK_OK != addImageName(m_curImgId, img_ptr, i)) { - registerError(); - return 1; - } + if (TSK_OK != addImageInfo(m_img_info->itype, m_img_info->sector_size, + m_curImgId, m_curImgTZone, m_img_info->size, md5, sha1, "", devId, collectionDetails, + img_ptrs, m_img_info->num_img)) { + registerError(); + return 1; } #ifdef TSK_WIN32 diff --git a/bindings/java/jni/auto_db_java.h b/bindings/java/jni/auto_db_java.h index e6c5e68dd7217d784695749cf53c24df090db75d..a4a55e509cf2c9cbac9bb8db521e3095e19953d1 100644 --- a/bindings/java/jni/auto_db_java.h +++ b/bindings/java/jni/auto_db_java.h @@ -204,7 +204,7 @@ class TskAutoDbJava :public TskAuto { // JNI methods TSK_RETVAL_ENUM addImageInfo(int type, TSK_OFF_T ssize, int64_t & objId, const string & timezone, TSK_OFF_T size, const string &md5, - const string& sha1, const string& sha256, const string& deviceId, const string& collectionDetails); + const string& sha1, const string& sha256, const string& deviceId, const string& collectionDetails, char** img_ptrs, int num_imgs); TSK_RETVAL_ENUM addImageName(int64_t objId, char const* imgName, int sequence); TSK_RETVAL_ENUM addVsInfo(const TSK_VS_INFO* vs_info, int64_t parObjId, int64_t& objId); TSK_RETVAL_ENUM addPoolInfoAndVS(const TSK_POOL_INFO *pool_info, int64_t parObjId, int64_t& objId); diff --git a/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbacks.java b/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbacks.java index cac2fc8435543679410a72ba88f40fa568dc4388..cd0c5d447b5767173ef684d4554cfb511ea049c4 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbacks.java +++ b/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbacks.java @@ -24,9 +24,9 @@ * */ public interface AddDataSourceCallbacks { - void onDataSourceAdded(long dataSourceObjectId) throws AddDataSourceCallbackException; + void onDataSourceAdded(long dataSourceObjectId) throws AddDataSourceCallbacksException; - void onFilesAdded(List<Long> fileObjectIds) throws AddDataSourceCallbackException; + void onFilesAdded(List<Long> fileObjectIds) throws AddDataSourceCallbacksException; - void onCompleted() throws AddDataSourceCallbackException; + void onCompleted() throws AddDataSourceCallbacksException; } diff --git a/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbackException.java b/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbacksException.java similarity index 83% rename from bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbackException.java rename to bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbacksException.java index 3fa66664177850deea8ae7b258aa9531dfaaa3e5..108fd54bc2361c0f1093f57a22b92425c8fc2bf2 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbackException.java +++ b/bindings/java/src/org/sleuthkit/datamodel/AddDataSourceCallbacksException.java @@ -21,13 +21,13 @@ /** * */ -public class AddDataSourceCallbackException extends TskException { +public class AddDataSourceCallbacksException extends TskException { private static final long serialVersionUID = 123049876L; /** * Default constructor when error message is not available */ - public AddDataSourceCallbackException() { + public AddDataSourceCallbacksException() { super("No error message available."); } @@ -36,7 +36,7 @@ public AddDataSourceCallbackException() { * * @param msg the message */ - public AddDataSourceCallbackException(String msg) { + public AddDataSourceCallbacksException(String msg) { super(msg); } @@ -46,7 +46,7 @@ public AddDataSourceCallbackException(String msg) { * @param msg the message * @param ex cause exception */ - public AddDataSourceCallbackException(String msg, Exception ex) { + public AddDataSourceCallbacksException(String msg, Exception ex) { super(msg, ex); } } diff --git a/bindings/java/src/org/sleuthkit/datamodel/JniDbHelper.java b/bindings/java/src/org/sleuthkit/datamodel/JniDbHelper.java index b65ad77b136adda0578a7bce53ed9b2f56945902..0f15f6e72602fa3c30ecfe77a50b0bc09b830d23 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/JniDbHelper.java +++ b/bindings/java/src/org/sleuthkit/datamodel/JniDbHelper.java @@ -40,6 +40,7 @@ class JniDbHelper { private final SleuthkitCase caseDb; private CaseDbTransaction trans = null; + AddDataSourceCallbacks addDataSourceCallbacks; private final Map<Long, Long> fsIdToRootDir = new HashMap<>(); private final Map<Long, TskData.TSK_FS_TYPE_ENUM> fsIdToFsType = new HashMap<>(); @@ -51,6 +52,13 @@ class JniDbHelper { JniDbHelper(SleuthkitCase caseDb) { this.caseDb = caseDb; + trans = null; + addDataSourceCallbacks = null; + } + + JniDbHelper(SleuthkitCase caseDb, AddDataSourceCallbacks addDataSourceCallbacks) { + this.caseDb = caseDb; + this.addDataSourceCallbacks = addDataSourceCallbacks; trans = null; } @@ -114,18 +122,30 @@ void finish() { */ long addImageInfo(int type, long ssize, String timezone, long size, String md5, String sha1, String sha256, String deviceId, - String collectionDetails) { + String collectionDetails, String[] paths) { try { beginTransaction(); long objId = caseDb.addImageJNI(TskData.TSK_IMG_TYPE_ENUM.valueOf(type), ssize, size, timezone, md5, sha1, sha256, deviceId, collectionDetails, trans); + for (int i = 0;i < paths.length;i++) { + caseDb.addImageNameJNI(objId, paths[i], i, trans); + } commitTransaction(); + + if (addDataSourceCallbacks != null) { + try { + addDataSourceCallbacks.onDataSourceAdded(objId); + } catch (AddDataSourceCallbacksException ex) { + logger.log(Level.SEVERE, "Error adding data source to ingest stream"); + return -1; + } + } return objId; } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Error adding image to the database", ex); revertTransaction(); return -1; - } + } } /** @@ -339,6 +359,7 @@ long addFile(long parentObjId, * @return 0 if successful, -1 if not */ private long addBatchedFilesToDb() { + List<Long> newObjIds = new ArrayList<>(); try { beginTransaction(); for (FileInfo fileInfo : batchedFiles) { @@ -361,6 +382,7 @@ private long addBatchedFilesToDb() { null, TskData.FileKnown.UNKNOWN, fileInfo.escaped_path, fileInfo.extension, false, trans); + newObjIds.add(objId); // If we're adding the root directory for the file system, cache it if (fileInfo.parentObjId == fileInfo.fsObjId) { @@ -385,6 +407,15 @@ private long addBatchedFilesToDb() { } } commitTransaction(); + + if (addDataSourceCallbacks != null) { + try { + addDataSourceCallbacks.onFilesAdded(newObjIds); + } catch (AddDataSourceCallbacksException ex) { + logger.log(Level.SEVERE, "Error adding files to ingest stream"); + return -1; + } + } } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Error adding batched files to database", ex); revertTransaction(); diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java index 4fe44e69095ea9e9a78621ed570f2a5b3417896d..50b332524e61127e04675192acab56ec6c37c18b 100644 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitJNI.java @@ -470,7 +470,7 @@ public class AddImageProcess { private volatile long tskAutoDbPointer; private boolean isCanceled; private final SleuthkitCase skCase; - private final JniDbHelper dbHelper; + private JniDbHelper dbHelper; /** * Constructs an object that encapsulates a multi-step process to @@ -493,7 +493,7 @@ private AddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFa tskAutoDbPointer = 0; this.isCanceled = false; this.skCase = skCase; - this.dbHelper = new JniDbHelper(skCase); + } /** @@ -515,6 +515,7 @@ private AddImageProcess(String timeZone, boolean addUnallocSpace, boolean skipFa * the process) */ public void run(String deviceId, String[] imageFilePaths, int sectorSize) throws TskCoreException, TskDataException { + dbHelper = new JniDbHelper(skCase); getTSKReadLock(); try { long imageHandle = 0; @@ -537,6 +538,50 @@ public void run(String deviceId, String[] imageFilePaths, int sectorSize) throws releaseTSKReadLock(); } } + + /** + * Starts the process of adding an image to the case database. + * Either AddImageProcess.commit or AddImageProcess.revert MUST be + * called after calling AddImageProcess.run. + * + * @param deviceId An ASCII-printable identifier for the + * device associated with the image that + * should be unique across multiple cases + * (e.g., a UUID). + * @param imageFilePaths Full path(s) to the image file(s). + * @param sectorSize The sector size (use '0' for autodetect). + * + * @throws TskCoreException if a critical error occurs within the + * SleuthKit. + * @throws TskDataException if a non-critical error occurs within + * the SleuthKit (should be OK to continue + * the process) + */ + public void run(String deviceId, String[] imageFilePaths, int sectorSize, + AddDataSourceCallbacks addDataSourceCallbacks) throws TskCoreException, TskDataException { + dbHelper = new JniDbHelper(skCase, addDataSourceCallbacks); + getTSKReadLock(); + try { + long imageHandle = 0; + synchronized (this) { + if (0 != tskAutoDbPointer) { + throw new TskCoreException("Add image process already started"); + } + if (!isCanceled) { //with isCanceled being guarded by this it will have the same value everywhere in this synchronized block + imageHandle = openImage(imageFilePaths, sectorSize, false, caseDbIdentifier); + tskAutoDbPointer = initAddImgNat(dbHelper, timezoneLongToShort(timeZone), addUnallocSpace, skipFatFsOrphans); + } + if (0 == tskAutoDbPointer) { + throw new TskCoreException("initAddImgNat returned a NULL TskAutoDb pointer"); + } + } + if (imageHandle != 0) { + runAddImgNat(tskAutoDbPointer, deviceId, imageHandle, timeZone, imageWriterPath); + } + } finally { + releaseTSKReadLock(); + } + } /** * Stops the process of adding the image to the case database that @@ -597,7 +642,9 @@ public synchronized long commit() throws TskCoreException { throw new TskCoreException("AddImgProcess::commit: AutoDB pointer is NULL"); } - dbHelper.finish(); + if (dbHelper != null) { + dbHelper.finish(); + } // Get the image ID and delete the object in the native code long id = finishAddImgNat(tskAutoDbPointer);