mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 09:17:42 +00:00
Merge branch 'develop' into aut-1900
This commit is contained in:
commit
38cb717bd9
@ -6,10 +6,6 @@
|
||||
<description>Builds, tests, and runs the project org.sleuthkit.autopsy.core</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Verify that the TSK_HOME env variable is set -->
|
||||
<target name="findTSK">
|
||||
<property environment="env"/>
|
||||
@ -30,7 +26,6 @@
|
||||
<copy file="${env.TSK_HOME}/bindings/java/lib/sqlite-jdbc-3.8.11.jar" tofile="${basedir}/release/modules/ext/sqlite-jdbc-3.8.11.jar"/>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="init" depends="basic-init,files-init,build-init,-javac-init">
|
||||
<!-- get additional deps -->
|
||||
<antcall target="getTSKJars" />
|
||||
|
@ -19,15 +19,13 @@
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.Image;
|
||||
import org.sleuthkit.datamodel.SleuthkitJNI;
|
||||
@ -35,66 +33,220 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
|
||||
/*
|
||||
* A background task that adds the given image to database using the Sleuthkit
|
||||
* JNI interface.
|
||||
*
|
||||
* It updates the given ProgressMonitor as it works through adding the image,
|
||||
* and et the end, calls the specified Callback.
|
||||
* A runnable that adds an image data source to the case database.
|
||||
*/
|
||||
class AddImageTask implements Runnable {
|
||||
|
||||
private final Logger logger = Logger.getLogger(AddImageTask.class.getName());
|
||||
|
||||
private final Case currentCase;
|
||||
|
||||
// true if the process was requested to cancel
|
||||
private final Object lock = new Object(); // synchronization object for cancelRequested
|
||||
private volatile boolean cancelRequested = false;
|
||||
|
||||
//true if revert has been invoked.
|
||||
private boolean reverted = false;
|
||||
|
||||
// true if there was a critical error in adding the data source
|
||||
private boolean hasCritError = false;
|
||||
|
||||
private final List<String> errorList = new ArrayList<>();
|
||||
|
||||
private final DataSourceProcessorProgressMonitor progressMonitor;
|
||||
private final DataSourceProcessorCallback callbackObj;
|
||||
|
||||
private final List<Content> newContents = Collections.synchronizedList(new ArrayList<Content>());
|
||||
|
||||
private SleuthkitJNI.CaseDbHandle.AddImageProcess addImageProcess;
|
||||
private Thread dirFetcher;
|
||||
|
||||
private final String deviceId;
|
||||
private final String imagePath;
|
||||
String timeZone;
|
||||
boolean noFatOrphans;
|
||||
|
||||
private final String dataSourceId;
|
||||
private final String timeZone;
|
||||
private final boolean ignoreFatOrphanFiles;
|
||||
private final DataSourceProcessorProgressMonitor progressMonitor;
|
||||
private final DataSourceProcessorCallback callback;
|
||||
private boolean criticalErrorOccurred;
|
||||
|
||||
/*
|
||||
* A thread that updates the progressMonitor with the name of the directory
|
||||
* currently being processed by the AddImageTask
|
||||
* The cancellation requested flag and SleuthKit add image process are
|
||||
* guarded by a monitor (called a lock here to avoid confusion with the
|
||||
* progress monitor) to synchronize cancelling the process (setting the flag
|
||||
* and calling its stop method) and calling either its commit or revert
|
||||
* method. The built-in monitor of the add image process can't be used for
|
||||
* this because it is already used to synchronize its run (init part),
|
||||
* commit, revert, and currentDirectory methods.
|
||||
*
|
||||
* TODO (AUT-2021): Merge SleuthkitJNI.AddImageProcess and AddImageTask
|
||||
*/
|
||||
private class CurrentDirectoryFetcher implements Runnable {
|
||||
private final Object tskAddImageProcessLock;
|
||||
private boolean tskAddImageProcessStopped;
|
||||
private SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess;
|
||||
|
||||
DataSourceProcessorProgressMonitor progressMonitor;
|
||||
SleuthkitJNI.CaseDbHandle.AddImageProcess process;
|
||||
|
||||
CurrentDirectoryFetcher(DataSourceProcessorProgressMonitor aProgressMonitor, SleuthkitJNI.CaseDbHandle.AddImageProcess proc) {
|
||||
this.progressMonitor = aProgressMonitor;
|
||||
this.process = proc;
|
||||
/**
|
||||
* Constructs a runnable task that adds an image to the case database.
|
||||
*
|
||||
* @param deviceId An ASCII-printable identifier for the device
|
||||
* associated with the data source that is
|
||||
* intended to be unique across multiple cases
|
||||
* (e.g., a UUID).
|
||||
* @param imagePath Path to the image file.
|
||||
* @param timeZone The time zone to use when processing dates
|
||||
* and times for the image, obtained from
|
||||
* java.util.TimeZone.getID.
|
||||
* @param ignoreFatOrphanFiles Whether to parse orphans if the image has a
|
||||
* FAT filesystem.
|
||||
* @param progressMonitor Progress monitor to report progress during
|
||||
* processing.
|
||||
* @param callback Callback to call when processing is done.
|
||||
*/
|
||||
AddImageTask(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
this.deviceId = deviceId;
|
||||
this.imagePath = imagePath;
|
||||
this.timeZone = timeZone;
|
||||
this.ignoreFatOrphanFiles = ignoreFatOrphanFiles;
|
||||
this.callback = callback;
|
||||
this.progressMonitor = progressMonitor;
|
||||
tskAddImageProcessLock = new Object();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the currently processing directory
|
||||
* Adds the image to the case database.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
progressMonitor.setIndeterminate(true);
|
||||
progressMonitor.setProgress(0);
|
||||
Case currentCase = Case.getCurrentCase();
|
||||
List<String> errorMessages = new ArrayList<>();
|
||||
List<Content> newDataSources = new ArrayList<>();
|
||||
try {
|
||||
currentCase.getSleuthkitCase().acquireExclusiveLock();
|
||||
synchronized (tskAddImageProcessLock) {
|
||||
tskAddImageProcess = currentCase.makeAddImageProcess(timeZone, true, ignoreFatOrphanFiles);
|
||||
}
|
||||
Thread progressUpdateThread = new Thread(new ProgressUpdater(progressMonitor, tskAddImageProcess));
|
||||
progressUpdateThread.start();
|
||||
runAddImageProcess(errorMessages);
|
||||
if (null != progressUpdateThread) {
|
||||
progressUpdateThread.interrupt();
|
||||
}
|
||||
commitOrRevertAddImageProcess(currentCase, errorMessages, newDataSources);
|
||||
progressMonitor.setProgress(100);
|
||||
} finally {
|
||||
currentCase.getSleuthkitCase().releaseExclusiveLock();
|
||||
DataSourceProcessorCallback.DataSourceProcessorResult result;
|
||||
if (criticalErrorOccurred) {
|
||||
result = DataSourceProcessorResult.CRITICAL_ERRORS;
|
||||
} else if (!errorMessages.isEmpty()) {
|
||||
result = DataSourceProcessorResult.NONCRITICAL_ERRORS;
|
||||
} else {
|
||||
result = DataSourceProcessorResult.NO_ERRORS;
|
||||
}
|
||||
callback.done(result, errorMessages, newDataSources);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempts to cancel adding the image to the case database.
|
||||
*/
|
||||
public void cancelTask() {
|
||||
synchronized (tskAddImageProcessLock) {
|
||||
if (null != tskAddImageProcess) {
|
||||
try {
|
||||
/*
|
||||
* All this does is set a flag that will make the TSK add
|
||||
* image process exit when the flag is checked between
|
||||
* processing steps. The state of the flag is not
|
||||
* accessible, so record it here so that it is known that
|
||||
* the revert method of the process object needs to be
|
||||
* called.
|
||||
*/
|
||||
tskAddImageProcess.stop();
|
||||
tskAddImageProcessStopped = true;
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error cancelling adding image %s to the case database", imagePath), ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the TSK add image process.
|
||||
*
|
||||
* @param errorMessages Error messages, if any, are added to this list for
|
||||
* eventual return via the callback.
|
||||
*/
|
||||
private void runAddImageProcess(List<String> errorMessages) {
|
||||
try {
|
||||
tskAddImageProcess.run(deviceId, new String[]{imagePath});
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Critical error occurred adding image %s", imagePath), ex); //NON-NLS
|
||||
criticalErrorOccurred = true;
|
||||
errorMessages.add(ex.getMessage());
|
||||
} catch (TskDataException ex) {
|
||||
logger.log(Level.WARNING, String.format("Non-critical error occurred adding image %s", imagePath), ex); //NON-NLS
|
||||
errorMessages.add(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits or reverts the results of the TSK add image process. If the
|
||||
* process was stopped before it completed or there was a critical error the
|
||||
* results are reverted, otherwise they are committed.
|
||||
*
|
||||
* @param currentCase The current case.
|
||||
* @param errorMessages Error messages, if any, are added to this list for
|
||||
* eventual return via the callback.
|
||||
* @param newDataSources If the new image is successfully committed, it is
|
||||
* added to this list for eventual return via the
|
||||
* callback.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private void commitOrRevertAddImageProcess(Case currentCase, List<String> errorMessages, List<Content> newDataSources) {
|
||||
synchronized (tskAddImageProcessLock) {
|
||||
if (tskAddImageProcessStopped || criticalErrorOccurred) {
|
||||
try {
|
||||
tskAddImageProcess.revert();
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error reverting adding image %s to the case database", imagePath), ex); //NON-NLS
|
||||
errorMessages.add(ex.getMessage());
|
||||
criticalErrorOccurred = true;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
long imageId = tskAddImageProcess.commit();
|
||||
if (imageId != 0) {
|
||||
Image newImage = currentCase.getSleuthkitCase().getImageById(imageId);
|
||||
String verificationError = newImage.verifyImageSize();
|
||||
if (!verificationError.isEmpty()) {
|
||||
errorMessages.add(verificationError);
|
||||
}
|
||||
newDataSources.add(newImage);
|
||||
} else {
|
||||
String errorMessage = String.format("Error commiting adding image %s to the case database, no object id returned", imagePath); //NON-NLS
|
||||
logger.log(Level.SEVERE, errorMessage);
|
||||
errorMessages.add(errorMessage);
|
||||
criticalErrorOccurred = true;
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error committing adding image %s to the case database", imagePath), ex); //NON-NLS
|
||||
errorMessages.add(ex.getMessage());
|
||||
criticalErrorOccurred = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Runnable that updates the progress monitor with the name of the
|
||||
* directory currently being processed by the SleuthKit add image process.
|
||||
*/
|
||||
private class ProgressUpdater implements Runnable {
|
||||
|
||||
private final DataSourceProcessorProgressMonitor progressMonitor;
|
||||
private final SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess;
|
||||
|
||||
/**
|
||||
* Constructs a Runnable that updates the progress monitor with the name
|
||||
* of the directory currently being processed by the SleuthKit.
|
||||
*
|
||||
* @param progressMonitor
|
||||
* @param tskAddImageProcess
|
||||
*/
|
||||
ProgressUpdater(DataSourceProcessorProgressMonitor progressMonitor, SleuthkitJNI.CaseDbHandle.AddImageProcess tskAddImageProcess) {
|
||||
this.progressMonitor = progressMonitor;
|
||||
this.tskAddImageProcess = tskAddImageProcess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the progress monitor with the name of the directory currently
|
||||
* being processed by the SleuthKit add image process.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
String currDir = process.currentDirectory();
|
||||
String currDir = tskAddImageProcess.currentDirectory();
|
||||
if (currDir != null) {
|
||||
if (!currDir.isEmpty()) {
|
||||
progressMonitor.setProgressText(
|
||||
@ -102,227 +254,20 @@ class AddImageTask implements Runnable {
|
||||
currDir));
|
||||
}
|
||||
}
|
||||
// this sleep here prevents the UI from locking up
|
||||
// due to too frequent updates to the progressMonitor above
|
||||
/*
|
||||
* The sleep here throttles the UI updates and provides a
|
||||
* non-standard mechanism for completing this task by
|
||||
* interrupting the thread in which it is running.
|
||||
*
|
||||
* TODO (AUT-1870): Replace this with giving the task to a
|
||||
* java.util.concurrent.ScheduledThreadPoolExecutor that is
|
||||
* shut down when the main task completes.
|
||||
*/
|
||||
Thread.sleep(500);
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
// nothing to do, thread was interrupted externally
|
||||
// signaling the end of AddImageProcess
|
||||
} catch (InterruptedException expected) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a runnable task that adds an image to the case database.
|
||||
*
|
||||
* @param dataSourceId An ASCII-printable identifier for the data
|
||||
* source that is intended to be unique across
|
||||
* multiple cases (e.g., a UUID).
|
||||
* @param imagePath Path to the image file.
|
||||
* @param timeZone The time zone to use when processing dates
|
||||
* and times for the image, obtained from
|
||||
* java.util.TimeZone.getID.
|
||||
* @param ignoreFatOrphanFiles Whether to parse orphans if the image has a
|
||||
* FAT filesystem.
|
||||
* @param monitor Progress monitor to report progress during
|
||||
* processing.
|
||||
* @param cbObj Callback to call when processing is done.
|
||||
*/
|
||||
AddImageTask(String dataSourceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor monitor, DataSourceProcessorCallback cbObj) {
|
||||
currentCase = Case.getCurrentCase();
|
||||
this.dataSourceId = dataSourceId;
|
||||
this.imagePath = imagePath;
|
||||
this.timeZone = timeZone;
|
||||
this.noFatOrphans = ignoreFatOrphanFiles;
|
||||
this.callbackObj = cbObj;
|
||||
this.progressMonitor = monitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the addImage process, but does not commit the results.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
errorList.clear();
|
||||
try {
|
||||
currentCase.getSleuthkitCase().acquireExclusiveLock();
|
||||
addImageProcess = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans);
|
||||
dirFetcher = new Thread(new CurrentDirectoryFetcher(progressMonitor, addImageProcess));
|
||||
try {
|
||||
progressMonitor.setIndeterminate(true);
|
||||
progressMonitor.setProgress(0);
|
||||
dirFetcher.start();
|
||||
addImageProcess.run(dataSourceId, new String[]{imagePath});
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Core errors occurred while running add image on " + imagePath, ex); //NON-NLS
|
||||
hasCritError = true;
|
||||
errorList.add(ex.getMessage());
|
||||
} catch (TskDataException ex) {
|
||||
logger.log(Level.WARNING, "Data errors occurred while running add image " + imagePath, ex); //NON-NLS
|
||||
errorList.add(ex.getMessage());
|
||||
}
|
||||
postProcess();
|
||||
} finally {
|
||||
currentCase.getSleuthkitCase().releaseExclusiveLock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the newly added image to DB
|
||||
*
|
||||
*
|
||||
* @throws Exception if commit or adding the image to the case failed
|
||||
*/
|
||||
private void commitImage() throws Exception {
|
||||
|
||||
long imageId = 0;
|
||||
try {
|
||||
imageId = addImageProcess.commit();
|
||||
} catch (TskCoreException e) {
|
||||
logger.log(Level.WARNING, "Errors occurred while committing the image " + imagePath, e); //NON-NLS
|
||||
errorList.add(e.getMessage());
|
||||
} finally {
|
||||
if (imageId != 0) {
|
||||
// get the newly added Image so we can return to caller
|
||||
Image newImage = currentCase.getSleuthkitCase().getImageById(imageId);
|
||||
|
||||
//while we have the image, verify the size of its contents
|
||||
String verificationErrors = newImage.verifyImageSize();
|
||||
if (verificationErrors.equals("") == false) {
|
||||
//data error (non-critical)
|
||||
errorList.add(verificationErrors);
|
||||
}
|
||||
|
||||
// Add the image to the list of new content
|
||||
newContents.add(newImage);
|
||||
}
|
||||
|
||||
logger.log(Level.INFO, "Image committed, imageId: {0}", imageId); //NON-NLS
|
||||
logger.log(Level.INFO, PlatformUtil.getAllMemUsageInfo());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Post processing after the addImageProcess is done.
|
||||
*
|
||||
*/
|
||||
private void postProcess() {
|
||||
|
||||
// cancel the directory fetcher
|
||||
dirFetcher.interrupt();
|
||||
|
||||
if (cancelRequested() || hasCritError) {
|
||||
logger.log(Level.WARNING, "Critical errors or interruption in add image process on {0}. Image will not be committed.", imagePath); //NON-NLS
|
||||
revert();
|
||||
}
|
||||
|
||||
if (!errorList.isEmpty()) {
|
||||
logger.log(Level.INFO, "There were errors that occurred in add image process for {0}", imagePath); //NON-NLS
|
||||
}
|
||||
|
||||
// When everything happens without an error:
|
||||
if (!(cancelRequested() || hasCritError)) {
|
||||
try {
|
||||
if (addImageProcess != null) {
|
||||
// commit image
|
||||
try {
|
||||
commitImage();
|
||||
} catch (Exception ex) {
|
||||
errorList.add(ex.getMessage());
|
||||
// Log error/display warning
|
||||
logger.log(Level.SEVERE, "Error adding image " + imagePath + " to case.", ex); //NON-NLS
|
||||
}
|
||||
} else {
|
||||
logger.log(Level.SEVERE, "Missing image process object"); //NON-NLS
|
||||
}
|
||||
|
||||
// Tell the progress monitor we're done
|
||||
progressMonitor.setProgress(100);
|
||||
} catch (Exception ex) {
|
||||
//handle unchecked exceptions post image add
|
||||
errorList.add(ex.getMessage());
|
||||
|
||||
logger.log(Level.WARNING, "Unexpected errors occurred while running post add image cleanup for " + imagePath, ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Error adding image " + imagePath + " to case", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
// invoke the callBack, unless the caller cancelled
|
||||
if (!cancelRequested()) {
|
||||
doCallBack();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the callback with results, new content, and errors, if any
|
||||
*/
|
||||
private void doCallBack() {
|
||||
DataSourceProcessorCallback.DataSourceProcessorResult result;
|
||||
|
||||
if (hasCritError) {
|
||||
result = DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
|
||||
} else if (!errorList.isEmpty()) {
|
||||
result = DataSourceProcessorCallback.DataSourceProcessorResult.NONCRITICAL_ERRORS;
|
||||
} else {
|
||||
result = DataSourceProcessorCallback.DataSourceProcessorResult.NO_ERRORS;
|
||||
}
|
||||
|
||||
// invoke the callback, passing it the result, list of new contents, and list of errors
|
||||
callbackObj.done(result, errorList, newContents);
|
||||
}
|
||||
|
||||
/*
|
||||
* cancel the image addition, if possible
|
||||
*/
|
||||
public void cancelTask() {
|
||||
|
||||
synchronized (lock) {
|
||||
cancelRequested = true;
|
||||
try {
|
||||
interrupt();
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Failed to interrupt the add image task..."); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt the add image process if it is still running
|
||||
*/
|
||||
private void interrupt() throws Exception {
|
||||
|
||||
try {
|
||||
logger.log(Level.INFO, "interrupt() add image process"); //NON-NLS
|
||||
addImageProcess.stop(); //it might take time to truly stop processing and writing to db
|
||||
} catch (TskCoreException ex) {
|
||||
throw new Exception(NbBundle.getMessage(this.getClass(), "AddImageTask.interrupt.exception.msg"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Revert - if image has already been added but not committed yet
|
||||
*/
|
||||
private void revert() {
|
||||
|
||||
if (!reverted) {
|
||||
logger.log(Level.INFO, "Revert after add image process"); //NON-NLS
|
||||
try {
|
||||
addImageProcess.revert();
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error reverting add image process", ex); //NON-NLS
|
||||
}
|
||||
reverted = true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean cancelRequested() {
|
||||
synchronized (lock) {
|
||||
return cancelRequested;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,6 +146,7 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
*
|
||||
* @param panel instance of ImageTypePanel to change to
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void updateCurrentPanel(JPanel panel) {
|
||||
currentPanel = panel;
|
||||
typePanel.removeAll();
|
||||
|
@ -68,6 +68,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
private final AddImageWizardChooseDataSourcePanel dataSourcePanel;
|
||||
|
||||
private DataSourceProcessor dsProcessor;
|
||||
private boolean cancelled;
|
||||
|
||||
AddImageWizardIngestConfigPanel(AddImageWizardChooseDataSourcePanel dsPanel, AddImageAction action, AddImageWizardAddingProgressPanel proPanel) {
|
||||
this.addImageAction = action;
|
||||
@ -228,6 +229,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
@Override
|
||||
void cleanup() throws Exception {
|
||||
cancelDataSourceProcessing(dataSourceId);
|
||||
cancelled = true;
|
||||
}
|
||||
};
|
||||
|
||||
@ -244,7 +246,6 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
public void doneEDT(DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
|
||||
dataSourceProcessorDone(dataSourceId, result, errList, contents);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
progressPanel.setStateStarted();
|
||||
@ -258,9 +259,6 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
* Cancels the data source processing - in case the users presses 'Cancel'
|
||||
*/
|
||||
private void cancelDataSourceProcessing(UUID dataSourceId) {
|
||||
new Thread(() -> {
|
||||
Case.getCurrentCase().notifyFailedAddingDataSource(dataSourceId);
|
||||
}).start();
|
||||
dsProcessor.cancel();
|
||||
}
|
||||
|
||||
@ -303,21 +301,23 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
progressPanel.addErrors(err, critErr);
|
||||
}
|
||||
|
||||
newContents.clear();
|
||||
newContents.addAll(contents);
|
||||
|
||||
//notify the UI of the new content added to the case
|
||||
new Thread(() -> {
|
||||
if (!newContents.isEmpty()) {
|
||||
Case.getCurrentCase().notifyDataSourceAdded(newContents.get(0), dataSourceId);
|
||||
if (!contents.isEmpty()) {
|
||||
Case.getCurrentCase().notifyDataSourceAdded(contents.get(0), dataSourceId);
|
||||
} else {
|
||||
Case.getCurrentCase().notifyFailedAddingDataSource(dataSourceId);
|
||||
}
|
||||
}).start();
|
||||
|
||||
// Start ingest if we can
|
||||
if (!cancelled) {
|
||||
newContents.clear();
|
||||
newContents.addAll(contents);
|
||||
progressPanel.setStateStarted();
|
||||
startIngest();
|
||||
} else {
|
||||
cancelled = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -222,8 +222,8 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
"Case_caseType_multiUser=Multi-user case"})
|
||||
public enum CaseType {
|
||||
|
||||
SINGLE_USER_CASE(Bundle.Case_caseType_singleUser()),
|
||||
MULTI_USER_CASE(Bundle.Case_caseType_multiUser());
|
||||
SINGLE_USER_CASE("Single-user case"), //NON-NLS
|
||||
MULTI_USER_CASE("Multi-user case"); //NON-NLS
|
||||
|
||||
private final String caseType;
|
||||
|
||||
@ -250,6 +250,14 @@ public class Case implements SleuthkitCase.ErrorObserver {
|
||||
public String toString() {
|
||||
return caseType;
|
||||
}
|
||||
|
||||
String getLocalizedDisplayName() {
|
||||
if (fromString(caseType) == SINGLE_USER_CASE) {
|
||||
return Bundle.Case_caseType_singleUser();
|
||||
} else {
|
||||
return Bundle.Case_caseType_multiUser();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private String name;
|
||||
|
@ -92,7 +92,7 @@ class CasePropertiesForm extends javax.swing.JPanel {
|
||||
CaseMetadata caseMetadata = new CaseMetadata(Paths.get(currentCase.getConfigFilePath()));
|
||||
tbDbName.setText(caseMetadata.getCaseDatabaseName());
|
||||
Case.CaseType caseType = caseMetadata.getCaseType();
|
||||
tbDbType.setText(caseType.toString());
|
||||
tbDbType.setText(caseType.getLocalizedDisplayName());
|
||||
if (caseType == Case.CaseType.SINGLE_USER_CASE) {
|
||||
deleteCaseButton.setEnabled(true);
|
||||
} else {
|
||||
|
@ -466,7 +466,11 @@ final class CollaborationMonitor {
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
eventPublisher.publishRemotely(new CollaborationEvent(hostName, localTasksManager.getCurrentTasks()));
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Unexpected exception in HeartbeatTask", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -482,7 +486,11 @@ final class CollaborationMonitor {
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
remoteTasksManager.finishStaleTasks();
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Unexpected exception in StaleTaskDetectionTask", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
|
||||
/**
|
||||
* An image file data source processor that implements the DataSourceProcessor
|
||||
* A image file data source processor that implements the DataSourceProcessor
|
||||
* service provider interface to allow integration with the add data source
|
||||
* wizard. It also provides a run method overload to allow it to be used
|
||||
* independently of the wizard.
|
||||
@ -81,10 +81,10 @@ public class ImageDSProcessor implements DataSourceProcessor {
|
||||
|
||||
/**
|
||||
* Gets a string that describes the type of data sources this processor is
|
||||
* able to process.
|
||||
* able to add to the case database. The string is suitable for display in a
|
||||
* type selection UI component (e.g., a combo box).
|
||||
*
|
||||
* @return A string suitable for display in a data source processor
|
||||
* selection UI component (e.g., a combo box).
|
||||
* @return A data source type display string for this data source processor.
|
||||
*/
|
||||
public static String getType() {
|
||||
return DATA_SOURCE_TYPE;
|
||||
@ -92,21 +92,23 @@ public class ImageDSProcessor implements DataSourceProcessor {
|
||||
|
||||
/**
|
||||
* Gets a string that describes the type of data sources this processor is
|
||||
* able to process.
|
||||
* able to add to the case database. The string is suitable for display in a
|
||||
* type selection UI component (e.g., a combo box).
|
||||
*
|
||||
* @return A string suitable for display in a data source processor
|
||||
* selection UI component (e.g., a combo box).
|
||||
* @return A data source type display string for this data source processor.
|
||||
*/
|
||||
@Override
|
||||
public String getDataSourceType() {
|
||||
return DATA_SOURCE_TYPE;
|
||||
return getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the panel that allows a user to select a data source and do any
|
||||
* configuration the data source processor may require.
|
||||
* configuration required by the data source. The panel is less than 544
|
||||
* pixels wide and less than 173 pixels high.
|
||||
*
|
||||
* @return A JPanel less than 544 pixels wide and 173 pixels high.
|
||||
* @return A selection and configuration panel for this data source
|
||||
* processor.
|
||||
*/
|
||||
@Override
|
||||
public JPanel getPanel() {
|
||||
@ -116,10 +118,11 @@ public class ImageDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the settings in the panel are valid and complete.
|
||||
* Indicates whether the settings in the selection and configuration panel
|
||||
* are valid and complete.
|
||||
*
|
||||
* @return True if the settings are valid and complete and the processor is
|
||||
* ready to have its run method called; false otherwise.
|
||||
* ready to have its run method called, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean isPanelValid() {
|
||||
@ -127,16 +130,18 @@ public class ImageDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a separate thread and the
|
||||
* settings provided by the panel. Returns as soon as the background task is
|
||||
* started and uses the callback object to signal task completion and return
|
||||
* results.
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
* configuration panel. Returns as soon as the background task is started.
|
||||
* The background task uses a callback object to signal task completion and
|
||||
* return results.
|
||||
*
|
||||
* NOTE: This method should not be called unless isPanelValid returns true.
|
||||
* This method should not be called unless isPanelValid returns true.
|
||||
*
|
||||
* @param progressMonitor Progress monitor for reporting progress during
|
||||
* processing.
|
||||
* @param callback Callback to call when processing is done.
|
||||
* @param progressMonitor Progress monitor that will be used by the
|
||||
* background task to report progress.
|
||||
* @param callback Callback that will be used by the background task
|
||||
* to return results.
|
||||
*/
|
||||
@Override
|
||||
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
@ -151,10 +156,11 @@ public class ImageDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a separate thread and the
|
||||
* given settings instead of those provided by the panel. Returns as soon as
|
||||
* the background task is started and uses the callback object to signal
|
||||
* task completion and return results.
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the given settings instead of those provided by the
|
||||
* selection and configuration panel. Returns as soon as the background task
|
||||
* is started and uses the callback object to signal task completion and
|
||||
* return results.
|
||||
*
|
||||
* @param deviceId An ASCII-printable identifier for the device
|
||||
* associated with the data source that is
|
||||
@ -176,8 +182,11 @@ public class ImageDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests cancellation of the data source processing task after it is
|
||||
* started using the run method. Cancellation is not guaranteed.
|
||||
* Requests cancellation of the background task that adds a data source to
|
||||
* the case database, after the task is started using the run method. This
|
||||
* is a "best effort" cancellation, with no guarantees that the case
|
||||
* database will be unchanged. If cancellation succeeded, the list of new
|
||||
* data sources returned by the background task will be empty.
|
||||
*/
|
||||
@Override
|
||||
public void cancel() {
|
||||
@ -185,7 +194,8 @@ public class ImageDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the panel.
|
||||
* Resets the selection and configuration panel for this data source
|
||||
* processor.
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
@ -199,7 +209,7 @@ public class ImageDSProcessor implements DataSourceProcessor {
|
||||
|
||||
/**
|
||||
* Sets the configuration of the data source processor without using the
|
||||
* configuration panel.
|
||||
* selection and configuration panel.
|
||||
*
|
||||
* @param imagePath Path to the image file.
|
||||
* @param timeZone The time zone to use when processing dates
|
||||
|
@ -190,7 +190,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
|
||||
String oldText = pathTextField.getText();
|
||||
// set the current directory of the FileChooser if the ImagePath Field is valid
|
||||
|
@ -61,10 +61,10 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
|
||||
/**
|
||||
* Gets a string that describes the type of data sources this processor is
|
||||
* able to process.
|
||||
* able to add to the case database. The string is suitable for display in a
|
||||
* type selection UI component (e.g., a combo box).
|
||||
*
|
||||
* @return A string suitable for display in a data source processor
|
||||
* selection UI component (e.g., a combo box).
|
||||
* @return A data source type display string for this data source processor.
|
||||
*/
|
||||
public static String getType() {
|
||||
return DATA_SOURCE_TYPE;
|
||||
@ -72,10 +72,10 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
|
||||
/**
|
||||
* Gets a string that describes the type of data sources this processor is
|
||||
* able to process.
|
||||
* able to add to the case database. The string is suitable for display in a
|
||||
* type selection UI component (e.g., a combo box).
|
||||
*
|
||||
* @return A string suitable for display in a data source processor
|
||||
* selection UI component (e.g., a combo box).
|
||||
* @return A data source type display string for this data source processor.
|
||||
*/
|
||||
@Override
|
||||
public String getDataSourceType() {
|
||||
@ -83,10 +83,12 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the JPanel that allows a user to select a data source and do any
|
||||
* configuration the data source processor may require.
|
||||
* Gets the panel that allows a user to select a data source and do any
|
||||
* configuration required by the data source. The panel is less than 544
|
||||
* pixels wide and less than 173 pixels high.
|
||||
*
|
||||
* @return A JPanel less than 544 pixels wide and 173 pixels high.
|
||||
* @return A selection and configuration panel for this data source
|
||||
* processor.
|
||||
*/
|
||||
@Override
|
||||
public JPanel getPanel() {
|
||||
@ -95,10 +97,11 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the settings in the panel are valid and complete.
|
||||
* Indicates whether the settings in the selection and configuration panel
|
||||
* are valid and complete.
|
||||
*
|
||||
* @return True if the settings are valid and complete and the processor is
|
||||
* ready to have its run method called; false otherwise.
|
||||
* ready to have its run method called, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean isPanelValid() {
|
||||
@ -106,16 +109,18 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a separate thread and the
|
||||
* settings provided by the panel. Returns as soon as the background task is
|
||||
* started and uses the callback object to signal task completion and return
|
||||
* results.
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
* configuration panel. Returns as soon as the background task is started.
|
||||
* The background task uses a callback object to signal task completion and
|
||||
* return results.
|
||||
*
|
||||
* NOTE: This method should not be called unless isPanelValid returns true.
|
||||
* This method should not be called unless isPanelValid returns true.
|
||||
*
|
||||
* @param progressMonitor Progress monitor for reporting progress during
|
||||
* processing.
|
||||
* @param callback Callback to call when processing is done.
|
||||
* @param progressMonitor Progress monitor that will be used by the
|
||||
* background task to report progress.
|
||||
* @param callback Callback that will be used by the background task
|
||||
* to return results.
|
||||
*/
|
||||
@Override
|
||||
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
@ -130,10 +135,11 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a separate thread and the
|
||||
* given settings instead of those provided by the panel. Returns as soon as
|
||||
* the background task is started and uses the callback object to signal
|
||||
* task completion and return results.
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the given settings instead of those provided by the
|
||||
* selection and configuration panel. Returns as soon as the background task
|
||||
* is started and uses the callback object to signal task completion and
|
||||
* return results.
|
||||
*
|
||||
* @param deviceId An ASCII-printable identifier for the device
|
||||
* associated with the data source that is
|
||||
@ -155,8 +161,11 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests cancellation of the data source processing task after it is
|
||||
* started using the run method. Cancellation is not guaranteed.
|
||||
* Requests cancellation of the background task that adds a data source to
|
||||
* the case database, after the task is started using the run method. This
|
||||
* is a "best effort" cancellation, with no guarantees that the case
|
||||
* database will be unchanged. If cancellation succeeded, the list of new
|
||||
* data sources returned by the background task will be empty.
|
||||
*/
|
||||
@Override
|
||||
public void cancel() {
|
||||
@ -164,7 +173,8 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the panel.
|
||||
* Resets the selection and configuration panel for this data source
|
||||
* processor.
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
|
@ -59,10 +59,10 @@ public class LocalFilesDSProcessor implements DataSourceProcessor {
|
||||
|
||||
/**
|
||||
* Gets a string that describes the type of data sources this processor is
|
||||
* able to process.
|
||||
* able to add to the case database. The string is suitable for display in a
|
||||
* type selection UI component (e.g., a combo box).
|
||||
*
|
||||
* @return A string suitable for display in a data source processor
|
||||
* selection UI component (e.g., a combo box).
|
||||
* @return A data source type display string for this data source processor.
|
||||
*/
|
||||
public static String getType() {
|
||||
return DATA_SOURCE_TYPE;
|
||||
@ -70,10 +70,10 @@ public class LocalFilesDSProcessor implements DataSourceProcessor {
|
||||
|
||||
/**
|
||||
* Gets a string that describes the type of data sources this processor is
|
||||
* able to process.
|
||||
* able to add to the case database. The string is suitable for display in a
|
||||
* type selection UI component (e.g., a combo box).
|
||||
*
|
||||
* @return A string suitable for display in a data source processor
|
||||
* selection UI component (e.g., a combo box).
|
||||
* @return A data source type display string for this data source processor.
|
||||
*/
|
||||
@Override
|
||||
public String getDataSourceType() {
|
||||
@ -82,9 +82,11 @@ public class LocalFilesDSProcessor implements DataSourceProcessor {
|
||||
|
||||
/**
|
||||
* Gets the panel that allows a user to select a data source and do any
|
||||
* configuration the data source processor may require.
|
||||
* configuration required by the data source. The panel is less than 544
|
||||
* pixels wide and less than 173 pixels high.
|
||||
*
|
||||
* @return A JPanel less than 544 pixels wide and 173 pixels high.
|
||||
* @return A selection and configuration panel for this data source
|
||||
* processor.
|
||||
*/
|
||||
@Override
|
||||
public JPanel getPanel() {
|
||||
@ -93,10 +95,11 @@ public class LocalFilesDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the settings in the panel are valid and complete.
|
||||
* Indicates whether the settings in the selection and configuration panel
|
||||
* are valid and complete.
|
||||
*
|
||||
* @return True if the settings are valid and complete and the processor is
|
||||
* ready to have its run method called; false otherwise.
|
||||
* ready to have its run method called, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean isPanelValid() {
|
||||
@ -104,16 +107,18 @@ public class LocalFilesDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a separate thread and the
|
||||
* settings provided by the panel. Returns as soon as the background task is
|
||||
* started and uses the callback object to signal task completion and return
|
||||
* results.
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
* configuration panel. Returns as soon as the background task is started.
|
||||
* The background task uses a callback object to signal task completion and
|
||||
* return results.
|
||||
*
|
||||
* NOTE: This method should not be called unless isPanelValid returns true.
|
||||
* This method should not be called unless isPanelValid returns true.
|
||||
*
|
||||
* @param progressMonitor Progress monitor for reporting progress during
|
||||
* processing.
|
||||
* @param callback Callback to call when processing is done.
|
||||
* @param progressMonitor Progress monitor that will be used by the
|
||||
* background task to report progress.
|
||||
* @param callback Callback that will be used by the background task
|
||||
* to return results.
|
||||
*/
|
||||
@Override
|
||||
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
@ -125,10 +130,11 @@ public class LocalFilesDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a separate thread and the
|
||||
* given settings instead of those provided by the panel. Returns as soon as
|
||||
* the background task is started and uses the callback object to signal
|
||||
* task completion and return results.
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the given settings instead of those provided by the
|
||||
* selection and configuration panel. Returns as soon as the background task
|
||||
* is started and uses the callback object to signal task completion and
|
||||
* return results.
|
||||
*
|
||||
* @param deviceId An ASCII-printable identifier for the
|
||||
* device associated with the data source
|
||||
@ -151,18 +157,22 @@ public class LocalFilesDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests cancellation of the data source processing task after it is
|
||||
* started using the run method. Cancellation is not guaranteed.
|
||||
* Requests cancellation of the background task that adds a data source to
|
||||
* the case database, after the task is started using the run method. This
|
||||
* is a "best effort" cancellation, with no guarantees that the case
|
||||
* database will be unchanged. If cancellation succeeded, the list of new
|
||||
* data sources returned by the background task will be empty.
|
||||
*
|
||||
* TODO (AUT-1907): Implement cancellation by deleting rows added to the
|
||||
* case database.
|
||||
*/
|
||||
@Override
|
||||
public void cancel() {
|
||||
/*
|
||||
* Cancellation is not currently supported.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the panel.
|
||||
* Resets the selection and configuration panel for this data source
|
||||
* processor.
|
||||
*/
|
||||
@Override
|
||||
public void reset() {
|
||||
|
@ -239,7 +239,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
|
||||
Object res2 = DialogDisplayer.getDefault().notify(d2);
|
||||
if (res2 != null && res2 == DialogDescriptor.YES_OPTION) {
|
||||
// if user say yes
|
||||
// if user says yes
|
||||
try {
|
||||
createDirectory(caseDirPath, getComponent().getCaseType());
|
||||
} catch (Exception ex) {
|
||||
@ -251,7 +251,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
}
|
||||
}
|
||||
if (res2 != null && res2 == DialogDescriptor.NO_OPTION) {
|
||||
// if user say no
|
||||
// if user says no
|
||||
validationError(NbBundle.getMessage(this.getClass(),
|
||||
"NewCaseWizardPanel1.validate.errMsg.prevCreateBaseDir.msg",
|
||||
caseDirPath));
|
||||
|
@ -389,7 +389,11 @@ public class ServicesMonitor {
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
checkAllServices();
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Unexpected exception in CrashDetectionTask", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,18 +22,24 @@ import javax.swing.JPanel;
|
||||
|
||||
/**
|
||||
* Interface implemented by classes that add data sources of a particular type
|
||||
* (e.g., images, local disks, virtual directories of local/logical files, etc.)
|
||||
* to a case database. A data source processor is NOT responsible for analyzing
|
||||
* the data source (running ingest modules on the data source and its contents).
|
||||
* (e.g., images, local disks, virtual directories of local/logical files) to a
|
||||
* case database. A data source processor is NOT responsible for analyzing the
|
||||
* data source, i.e., running ingest modules on the data source and its
|
||||
* contents.
|
||||
*
|
||||
* Data source processors plug in to the add data source wizard and should
|
||||
* provide a JPanel to allow a user to select a data source and do any
|
||||
* configuration the data source processor may require. The panel should support
|
||||
* addition of the add data source wizard as a property change listener and
|
||||
* should fire DSP_PANEL_EVENT property changes to communicate with the wizard.
|
||||
* provide a UI panel to allow a user to select a data source and do any
|
||||
* configuration required by the data source processor. The selection and
|
||||
* configuration panel should support addition of the add data source wizard as
|
||||
* a property change listener and should fire DSP_PANEL_EVENT property change
|
||||
* events to communicate with the wizard.
|
||||
*
|
||||
* Data source processors should perform all processing on a separate thread,
|
||||
* reporting results using a callback object.
|
||||
* Data source processors should perform all processing in a background task in
|
||||
* a separate thread, reporting results using a callback object.
|
||||
*
|
||||
* It is recommended that implementers provide an overload of the run method
|
||||
* that allows the data source processor to be run independently of the
|
||||
* selection and configuration panel.
|
||||
*/
|
||||
public interface DataSourceProcessor {
|
||||
|
||||
@ -48,64 +54,76 @@ public interface DataSourceProcessor {
|
||||
enum DSP_PANEL_EVENT {
|
||||
|
||||
/**
|
||||
* Fire this event when the user changes something in the panel to
|
||||
* notify the add data source wizard that it should call isPanelValid.
|
||||
* This event is fired when the user changes something in the selection
|
||||
* and configuration panel. It notifies the add data source wizard that
|
||||
* it should call isPanelValid.
|
||||
*/
|
||||
UPDATE_UI,
|
||||
/**
|
||||
* Fire this event to make the add data source wizard move focus to the
|
||||
* next button.
|
||||
* This event is fired to make the add data source wizard move focus to
|
||||
* the wizard's next button.
|
||||
* @deprecated Use UPDATE_UI.
|
||||
*/
|
||||
@Deprecated
|
||||
FOCUS_NEXT
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a string that describes the type of data sources this processor is
|
||||
* able to process.
|
||||
* able to add to the case database. The string is suitable for display in a
|
||||
* type selection UI component (e.g., a combo box).
|
||||
*
|
||||
* @return A string suitable for display in a data source processor
|
||||
* selection UI component (e.g., a combo box).
|
||||
* @return A data source type display string for this data source processor.
|
||||
*/
|
||||
String getDataSourceType();
|
||||
|
||||
/**
|
||||
* Gets the panel that allows a user to select a data source and do any
|
||||
* configuration the data source processor may require.
|
||||
* configuration required by the data source. The panel is less than 544
|
||||
* pixels wide and less than 173 pixels high.
|
||||
*
|
||||
* @return A JPanel less than 544 pixels wide and 173 pixels high.
|
||||
* @return A selection and configuration panel for this data source
|
||||
* processor.
|
||||
*/
|
||||
JPanel getPanel();
|
||||
|
||||
/**
|
||||
* Indicates whether the settings in the panel are valid and complete.
|
||||
* Indicates whether the settings in the selection and configuration panel
|
||||
* are valid and complete.
|
||||
*
|
||||
* @return True if the settings are valid and complete and the processor is
|
||||
* ready to have its run method called; false otherwise.
|
||||
* ready to have its run method called, false otherwise.
|
||||
*/
|
||||
boolean isPanelValid();
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a separate thread and the
|
||||
* settings provided by the panel. Returns as soon as the background task is
|
||||
* started and uses the callback object to signal task completion and return
|
||||
* results.
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
* configuration panel. Returns as soon as the background task is started.
|
||||
* The background task uses a callback object to signal task completion and
|
||||
* return results.
|
||||
*
|
||||
* NOTE: This method should not be called unless isPanelValid returns true.
|
||||
* This method should not be called unless isPanelValid returns true.
|
||||
*
|
||||
* @param progressMonitor Progress monitor for reporting progress during
|
||||
* processing.
|
||||
* @param callback Callback to call when processing is done.
|
||||
* @param progressMonitor Progress monitor that will be used by the
|
||||
* background task to report progress.
|
||||
* @param callback Callback that will be used by the background task
|
||||
* to return results.
|
||||
*/
|
||||
void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback);
|
||||
|
||||
/**
|
||||
* Requests cancellation of the data source processing task after it is
|
||||
* started using the run method. Cancellation is not guaranteed.
|
||||
* Requests cancellation of the background task that adds a data source to
|
||||
* the case database, after the task is started using the run method. This
|
||||
* is a "best effort" cancellation, with no guarantees that the case
|
||||
* database will be unchanged. If cancellation succeeded, the list of new
|
||||
* data sources returned by the background task will be empty.
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* Resets the panel.
|
||||
* Resets the selection and configuration panel for this data source
|
||||
* processor.
|
||||
*/
|
||||
void reset();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2014 Basis Technology Corp.
|
||||
* Copyright 2013-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -23,56 +23,72 @@ import java.util.List;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
|
||||
/**
|
||||
* Abstract class for a callback for a DataSourceProcessor.
|
||||
*
|
||||
* Ensures that DSP invokes the caller overridden method, doneEDT(), in the EDT
|
||||
* thread.
|
||||
* An abstract base class for callback objects to be given to data source
|
||||
* processors for use by the background tasks that add data sources to a case
|
||||
* database. The callback objects are used to signal task completion and return
|
||||
* results.
|
||||
*
|
||||
* Concrete implementations of DataSourceProcessorCallback should override
|
||||
* either the done method or the doneEDT method, but not both.
|
||||
*/
|
||||
public abstract class DataSourceProcessorCallback {
|
||||
|
||||
public enum DataSourceProcessorResult {
|
||||
|
||||
NO_ERRORS, ///< No errors were encountered while ading the data source
|
||||
CRITICAL_ERRORS, ///< No data was added to the database. There were fundamental errors processing the data (such as no data or system failure).
|
||||
NONCRITICAL_ERRORS, ///< There was data added to the database, but there were errors from data corruption or a small number of minor issues.
|
||||
/**
|
||||
* No errors occurred while ading the data source to the case database.
|
||||
*/
|
||||
NO_ERRORS,
|
||||
/**
|
||||
* Critical errors occurred while ading the data source to the case
|
||||
* database. The data source was not added to the case database.
|
||||
*/
|
||||
CRITICAL_ERRORS,
|
||||
/**
|
||||
* Non-critical errors occurred while adding the data source to the case
|
||||
* database. The data source was added to the database, but the data
|
||||
* source may have been corrupted in some way.
|
||||
*/
|
||||
NONCRITICAL_ERRORS
|
||||
};
|
||||
|
||||
/**
|
||||
* Called by a DSP implementation when it is done adding a data source to
|
||||
* the database. Users of the DSP can override this method if they do not
|
||||
* want to be notified on the EDT. Otherwise, this method will call
|
||||
* doneEDT() with the same arguments.
|
||||
* Called by a data source processor when it is done adding a data source to
|
||||
* the case database, this method adds a task to call the doneEDT method to
|
||||
* the EDT task queue.
|
||||
*
|
||||
* @param result Code for status
|
||||
* @param errList List of error strings
|
||||
* @param newContents List of root Content objects that were added to
|
||||
* database. Typically only one is given.
|
||||
* IMPORTANT: Concrete implementations of DataSourceProcessorCallback should
|
||||
* override this method if the callback SHOULD NOT be done in the EDT.
|
||||
*
|
||||
* @param result Result code.
|
||||
* @param errList List of error messages, possibly empty.
|
||||
* @param newDataSources A list of the data sources added, empty if critical
|
||||
* errors occurred or processing was successfully
|
||||
* cancelled.
|
||||
*/
|
||||
public void done(DataSourceProcessorResult result, List<String> errList, List<Content> newContents) {
|
||||
|
||||
public void done(DataSourceProcessorResult result, List<String> errList, List<Content> newDataSources) {
|
||||
final DataSourceProcessorResult resultf = result;
|
||||
final List<String> errListf = errList;
|
||||
final List<Content> newContentsf = newContents;
|
||||
|
||||
// Invoke doneEDT() that runs on the EDT .
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final List<Content> newContentsf = newDataSources;
|
||||
EventQueue.invokeLater(() -> {
|
||||
doneEDT(resultf, errListf, newContentsf);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by done() if the default implementation is used. Users of DSPs
|
||||
* that have UI updates to do after the DSP is finished adding the DS can
|
||||
* implement this method to receive the updates on the EDT.
|
||||
* Called by a data source processor when it is done adding a data source to
|
||||
* the case database, if the default done method has not been overridden.
|
||||
*
|
||||
* @param result Code for status
|
||||
* @param errList List of error strings
|
||||
* @param newContents List of root Content objects that were added to
|
||||
* database. Typically only one is given.
|
||||
* IMPORTANT: Concrete implementations of DataSourceProcessorCallback should
|
||||
* override the done method and provide an implementation of this method
|
||||
* that throws an UnsupportedOperationException if the callback SHOULD NOT
|
||||
* be done in the EDT.
|
||||
*
|
||||
* @param result Result code.
|
||||
* @param errList List of error messages, possibly empty.
|
||||
* @param newDataSources A list of the data sources added, empty if critical
|
||||
* errors occurred or processing was successfully
|
||||
* cancelled.
|
||||
*/
|
||||
public abstract void doneEDT(DataSourceProcessorResult result, List<String> errList, List<Content> newContents);
|
||||
abstract public void doneEDT(DataSourceProcessorResult result, List<String> errList, List<Content> newDataSources);
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -47,16 +47,22 @@ import org.sleuthkit.datamodel.SleuthkitJNI;
|
||||
*/
|
||||
public final class AboutWindowPanel extends JPanel implements HyperlinkListener {
|
||||
|
||||
private static final Logger Logger = org.sleuthkit.autopsy.coreutils.Logger.getLogger(AboutWindowPanel.class.getName());
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private URL url = null;
|
||||
|
||||
private Icon about;
|
||||
|
||||
private final Icon about;
|
||||
private boolean verboseLogging;
|
||||
|
||||
public AboutWindowPanel() {
|
||||
about = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/splash.png"));
|
||||
init();
|
||||
}
|
||||
|
||||
public AboutWindowPanel(String pathToBrandingImage) {
|
||||
about = new ImageIcon(ImageUtilities.loadImage(pathToBrandingImage));
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
initComponents();
|
||||
logoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
description.setText(org.openide.util.NbBundle.getMessage(AboutWindowPanel.class,
|
||||
@ -68,7 +74,6 @@ public final class AboutWindowPanel extends JPanel implements HyperlinkListener
|
||||
if (verboseLoggingIsSet()) {
|
||||
disableVerboseLoggingButton();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
|
@ -148,7 +148,7 @@ FXVideoPanel.progress.bufferingCancelled=media buffering was canceled
|
||||
FXVideoPanel.progress.bufferingInterrupted=media buffering was interrupted
|
||||
FXVideoPanel.progress.errorWritingVideoToDisk=Error writing video to disk
|
||||
OptionsCategory_Name_Multi_User_Settings=Multi-user
|
||||
OptionsCategory_Keywords_Multi_User_Options=Multi-user Options
|
||||
OptionsCategory_Keywords_Multi_User_Options=Multi-user Settings
|
||||
MultiUserSettingsPanel.lbSolrSettings.text=Solr Settings
|
||||
MultiUserSettingsPanel.cbEnableMultiUser.text=Enable Multi-user cases
|
||||
MultiUserSettingsPanel.lbDatabaseSettings.text=Database Settings
|
||||
|
@ -488,7 +488,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
|
||||
// if the artifact has an ASSOCIATED ARTIFACT, then we display the associated artifact instead
|
||||
try {
|
||||
for (BlackboardAttribute attr : artifact.getAttributes()) {
|
||||
if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
|
||||
if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
|
||||
long assocArtifactId = attr.getValueLong();
|
||||
int assocArtifactIndex = -1;
|
||||
for (BlackboardArtifact art : artifacts) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -23,38 +23,67 @@ import org.openide.nodes.FilterNode;
|
||||
import org.openide.nodes.Node;
|
||||
|
||||
/**
|
||||
* Complementary class to TableFilterNode.
|
||||
* A children (child factory) implementation for a TableFilterNode. A
|
||||
* TableFilterNode creates at most one layer of child nodes for the node it
|
||||
* wraps. It is designed to be used for nodes displayed in Autopsy table views.
|
||||
*/
|
||||
class TableFilterChildren extends FilterNode.Children {
|
||||
|
||||
/**
|
||||
* the constructor
|
||||
* Constructs a children (child factory) implementation for a
|
||||
* TableFilterNode. A TableFilterNode creates at most one layer of child
|
||||
* nodes for the node it wraps. It is designed to be used for nodes
|
||||
* displayed in Autopsy table views.
|
||||
*
|
||||
* @param wrappedNode The node wrapped by the TableFilterNode.
|
||||
*/
|
||||
TableFilterChildren(Node arg) {
|
||||
super(arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node copyNode(Node arg0) {
|
||||
return new TableFilterNode(arg0, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node[] createNodes(Node arg0) {
|
||||
// filter out the children
|
||||
return new Node[]{this.copyNode(arg0)};
|
||||
TableFilterChildren(Node wrappedNode) {
|
||||
super(wrappedNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given FsContent into "Children".
|
||||
* Copies a TableFilterNode, with the create children (child factory) flag
|
||||
* set to false.
|
||||
*
|
||||
* @param fs
|
||||
* @param nodeToCopy The TableFilterNode to copy.
|
||||
*
|
||||
* @return children
|
||||
* @return A copy of a TableFilterNode.
|
||||
*/
|
||||
public static Children createInstance(Node arg, boolean createChild) {
|
||||
if (createChild) {
|
||||
return new TableFilterChildren(arg);
|
||||
@Override
|
||||
protected Node copyNode(Node nodeToCopy) {
|
||||
return new TableFilterNode(nodeToCopy, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the child nodes represented by this children (child factory)
|
||||
* object.
|
||||
*
|
||||
* @param key The key, i.e., the node, for which to create the child nodes.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected Node[] createNodes(Node key) {
|
||||
return new Node[]{this.copyNode(key)};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a children (child factory) object for a node wrapped in a
|
||||
* TableFilterNode. A TableFilterNode creates at most one layer of child
|
||||
* nodes for the node it wraps. It is designed to be used for nodes
|
||||
* displayed in Autopsy table views.
|
||||
*
|
||||
*
|
||||
* @param wrappedNode The node wrapped by the TableFilterNode.
|
||||
* @param createChildren True if a children (child factory) object should be
|
||||
* created for the wrapped node.
|
||||
*
|
||||
* @return A children (child factory) object for a node wrapped by a
|
||||
* TableFilterNode.
|
||||
*/
|
||||
public static Children createInstance(Node wrappedNode, boolean createChildren) {
|
||||
if (createChildren) {
|
||||
return new TableFilterChildren(wrappedNode);
|
||||
} else {
|
||||
return Children.LEAF;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -23,48 +23,40 @@ import org.openide.nodes.Node;
|
||||
import org.openide.util.NbBundle;
|
||||
|
||||
/**
|
||||
* This class is used to filter the nodes that we want to show on the
|
||||
* "TreeTableView". So basically we just want to show one layer of nodes from
|
||||
* it's parent.
|
||||
*
|
||||
* @author jantonius
|
||||
* A filter node that creates at most one layer of child nodes for the node it
|
||||
* wraps. It is designed to be used for nodes displayed in Autopsy table views.
|
||||
*/
|
||||
public class TableFilterNode extends FilterNode {
|
||||
|
||||
private boolean createChild;
|
||||
private String itemType;
|
||||
private final boolean createChildren;
|
||||
|
||||
/**
|
||||
* the constructor
|
||||
*/
|
||||
public TableFilterNode(Node arg, boolean crChild) {
|
||||
super(arg, TableFilterChildren.createInstance(arg, crChild));
|
||||
this.createChild = crChild;
|
||||
this.itemType = "";
|
||||
}
|
||||
|
||||
public TableFilterNode(Node arg, boolean crChild, String itemType) {
|
||||
super(arg, TableFilterChildren.createInstance(arg, crChild));
|
||||
this.createChild = crChild;
|
||||
this.itemType = itemType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the display name / header for the first (tree) column on the
|
||||
* "TreeTableView".
|
||||
* Constructs a filter node that creates at most one layer of child nodes
|
||||
* for the node it wraps. It is designed to be used for nodes displayed in
|
||||
* Autopsy table views.
|
||||
*
|
||||
* @return disName the display name for the first column
|
||||
* @param wrappedNode The node to wrap in the filter node.
|
||||
* @param createChildren True if a children (child factory) object should be
|
||||
* created for the wrapped node.
|
||||
*/
|
||||
public TableFilterNode(Node wrappedNode, boolean createChildren) {
|
||||
super(wrappedNode, TableFilterChildren.createInstance(wrappedNode, createChildren));
|
||||
this.createChildren = createChildren;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a display name for the wrapped node, for use in the first column
|
||||
* of an Autopsy table view.
|
||||
*
|
||||
* @return The display name.
|
||||
*/
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
if (createChild) {
|
||||
if (createChildren) {
|
||||
return NbBundle.getMessage(this.getClass(), "TableFilterNode.displayName.text");
|
||||
} else {
|
||||
return super.getDisplayName();
|
||||
}
|
||||
}
|
||||
|
||||
public String getItemType() {
|
||||
return itemType;
|
||||
}
|
||||
}
|
||||
|
@ -72,19 +72,19 @@ public class ArtifactStringContent implements StringContent {
|
||||
|
||||
// name column
|
||||
buffer.append("<tr><td>"); //NON-NLS
|
||||
buffer.append(attr.getAttributeTypeDisplayName());
|
||||
buffer.append(attr.getAttributeType().getDisplayName());
|
||||
buffer.append("</td>"); //NON-NLS
|
||||
|
||||
// value column
|
||||
buffer.append("<td>"); //NON-NLS
|
||||
if (attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()
|
||||
|| attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()
|
||||
|| attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID()
|
||||
|| attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED.getTypeID()
|
||||
|| attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_RCVD.getTypeID()
|
||||
|| attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID()
|
||||
|| attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID()
|
||||
|| attr.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID()) {
|
||||
if (attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID()
|
||||
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()
|
||||
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID()
|
||||
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED.getTypeID()
|
||||
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_RCVD.getTypeID()
|
||||
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID()
|
||||
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID()
|
||||
|| attr.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID()) {
|
||||
long epoch = attr.getValueLong();
|
||||
String time = "0000-00-00 00:00:00";
|
||||
if (epoch != 0) {
|
||||
@ -93,7 +93,7 @@ public class ArtifactStringContent implements StringContent {
|
||||
}
|
||||
buffer.append(time);
|
||||
} else {
|
||||
switch (attr.getValueType()) {
|
||||
switch (attr.getAttributeType().getValueType()) {
|
||||
case STRING:
|
||||
String str = attr.getValueString();
|
||||
str = str.replaceAll(" ", " "); //NON-NLS
|
||||
|
@ -117,7 +117,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
if (artifact != null && artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
|
||||
try {
|
||||
for (BlackboardAttribute attribute : artifact.getAttributes()) {
|
||||
if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
|
||||
if (attribute.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
|
||||
BlackboardArtifact associatedArtifact = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong());
|
||||
if (associatedArtifact != null) {
|
||||
displayName = associatedArtifact.getDisplayName() + " Artifact"; // NON-NLS
|
||||
@ -282,8 +282,8 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
/**
|
||||
* Fill map with Artifact properties
|
||||
*
|
||||
* @param map map with preserved ordering, where property names/values are
|
||||
* put
|
||||
* @param map map with preserved ordering, where property names/values
|
||||
* are put
|
||||
* @param artifact to extract properties from
|
||||
*/
|
||||
@SuppressWarnings("deprecation") // TODO: Remove this when TSK_TAGGED_ARTIFACT rows are removed in a database upgrade.
|
||||
@ -384,7 +384,7 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
|
||||
String keyword = null;
|
||||
String regexp = null;
|
||||
for (BlackboardAttribute att : attributes) {
|
||||
final int attributeTypeID = att.getAttributeTypeID();
|
||||
final int attributeTypeID = att.getAttributeType().getTypeID();
|
||||
if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
|
||||
keyword = att.getValueString();
|
||||
} else if (attributeTypeID == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID()) {
|
||||
|
@ -271,8 +271,8 @@ public class DataResultFilterNode extends FilterNode {
|
||||
Content c = null;
|
||||
try {
|
||||
for (BlackboardAttribute attr : art.getAttributes()) {
|
||||
if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) {
|
||||
switch (attr.getValueType()) {
|
||||
if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) {
|
||||
switch (attr.getAttributeType().getValueType()) {
|
||||
case INTEGER:
|
||||
int i = attr.getValueInt();
|
||||
if (i != -1) {
|
||||
|
@ -865,7 +865,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
String setName = null;
|
||||
List<BlackboardAttribute> attributes = art.getAttributes();
|
||||
for (BlackboardAttribute att : attributes) {
|
||||
int typeId = att.getAttributeTypeID();
|
||||
int typeId = att.getAttributeType().getTypeID();
|
||||
if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
|
||||
setName = att.getValueString();
|
||||
}
|
||||
@ -882,7 +882,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
String keywordName = null;
|
||||
List<BlackboardAttribute> attributes = art.getAttributes();
|
||||
for (BlackboardAttribute att : attributes) {
|
||||
int typeId = att.getAttributeTypeID();
|
||||
int typeId = att.getAttributeType().getTypeID();
|
||||
if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
|
||||
listName = att.getValueString();
|
||||
} else if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
|
||||
@ -909,7 +909,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
String setName = null;
|
||||
List<BlackboardAttribute> attributes = art.getAttributes();
|
||||
for (BlackboardAttribute att : attributes) {
|
||||
int typeId = att.getAttributeTypeID();
|
||||
int typeId = att.getAttributeType().getTypeID();
|
||||
if (typeId == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()) {
|
||||
setName = att.getValueString();
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public final class AutopsyEventPublisher {
|
||||
* Composed of thread-safe objects.
|
||||
*/
|
||||
private static final Logger logger = Logger.getLogger(AutopsyEventPublisher.class.getName());
|
||||
private static final int MAX_REMOTE_EVENT_PUBLISH_TRIES = 3;
|
||||
private static final int MAX_REMOTE_EVENT_PUBLISH_TRIES = 1;
|
||||
private final LocalEventPublisher localPublisher;
|
||||
private RemoteEventPublisher remotePublisher;
|
||||
private String currentChannelName;
|
||||
@ -86,15 +86,8 @@ public final class AutopsyEventPublisher {
|
||||
* events from other Autopsy nodes.
|
||||
*/
|
||||
public void closeRemoteEventChannel() {
|
||||
stopRemotePublisher();
|
||||
currentChannelName = null;
|
||||
if (null != remotePublisher) {
|
||||
try {
|
||||
remotePublisher.stop();
|
||||
} catch (JMSException ex) {
|
||||
logger.log(Level.SEVERE, "Error closing remote event channel", ex); //NON-NLS
|
||||
}
|
||||
remotePublisher = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -162,12 +155,10 @@ public final class AutopsyEventPublisher {
|
||||
* @param event The event to publish.
|
||||
*/
|
||||
public void publishRemotely(AutopsyEvent event) {
|
||||
/*
|
||||
* This is a no-op if a remote channel has not been opened.
|
||||
*/
|
||||
if (null != currentChannelName) {
|
||||
boolean published = false;
|
||||
int tryCount = 1;
|
||||
|
||||
while (false == published && tryCount <= MAX_REMOTE_EVENT_PUBLISH_TRIES) {
|
||||
try {
|
||||
if (null == remotePublisher) {
|
||||
@ -175,16 +166,28 @@ public final class AutopsyEventPublisher {
|
||||
}
|
||||
remotePublisher.publish(event);
|
||||
published = true;
|
||||
} catch (JMSException ex) {
|
||||
} catch (AutopsyEventException | JMSException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Failed to publish %s using channel %s (tryCount = %s)", event.getPropertyName(), currentChannelName, tryCount), ex); //NON-NLS
|
||||
closeRemoteEventChannel();
|
||||
++tryCount;
|
||||
} catch (AutopsyEventException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Failed to reopen channel %s to publish %s event (tryCount = %s)", currentChannelName, event.getPropertyName(), tryCount), ex); //NON-NLS
|
||||
stopRemotePublisher();
|
||||
++tryCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the remote event publisher, but does not reset the current channel
|
||||
* name.
|
||||
*/
|
||||
private void stopRemotePublisher() {
|
||||
if (null != remotePublisher) {
|
||||
try {
|
||||
remotePublisher.stop();
|
||||
} catch (JMSException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error closing remote event publisher for channel %s", currentChannelName), ex); //NON-NLS
|
||||
}
|
||||
remotePublisher = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -115,5 +115,5 @@ IngestJob.cancelReason.notCancelled.text=Not cancelled
|
||||
IngestJob.cancelReason.cancelledByUser.text=Cancelled by user
|
||||
IngestJob.cancelReason.ingestModStartFail.text=Ingest modules startup failed
|
||||
IngestJob.cancelReason.outOfDiskSpace.text=Out of disk space
|
||||
IngestJob.cancelReason.servicesDown.text=Not cancelled
|
||||
IngestJob.cancelReason.servicesDown.text=Services Down
|
||||
IngestJob.cancelReason.caseClosed.text=Case closed
|
||||
|
@ -1,116 +1,115 @@
|
||||
CTL_IngestMessageTopComponent=\u30E1\u30C3\u30BB\u30FC\u30B8
|
||||
HINT_IngestMessageTopComponent=\u30E1\u30C3\u30BB\u30FC\u30B8\u30A6\u30A3\u30F3\u30C9\u30A6
|
||||
IngestDialog.closeButton.title=\u9589\u3058\u308B
|
||||
IngestDialog.startButton.title=\u958B\u59CB
|
||||
IngestDialog.title.text=\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8
|
||||
IngestJob.progress.cancelling={0}\uFF08\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D\u2026\uFF09
|
||||
IngestJob.progress.dataSourceIngest.displayName={1}\u306E{0}
|
||||
IngestJob.progress.fileIngest.displayName={0}\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u89E3\u6790\u4E2D
|
||||
IngestManager.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC
|
||||
IngestManager.moduleErr.errListenToUpdates.msg=Ingest Manager\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u30ED\u30B0\u3092\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u4E0D\u5B8C\u5168\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002
|
||||
IngestManager.StartIngestJobsTask.run.cancelling={0}\uFF08\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D\u2026\uFF09
|
||||
IngestManager.StartIngestJobsTask.run.displayName=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u958B\u59CB\u4E2D
|
||||
IngestMessage.exception.srcSubjDetailsDataNotNull.msg=\u30BD\u30FC\u30B9\u3001\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\u3001\u8A73\u7D30\u304A\u3088\u3073\u30C7\u30FC\u30BF\u306F\u30CC\u30EB\u3067\u306F\u3044\u3051\u307E\u305B\u3093
|
||||
IngestMessage.exception.srcSubjNotNull.msg=\u30BD\u30FC\u30B9\u304A\u3088\u3073\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\u306F\u30CC\u30EB\u3067\u306F\u3044\u3051\u307E\u305B\u3093
|
||||
IngestMessage.exception.typeSrcSubjNotNull.msg=\u30E1\u30C3\u30BB\u30FC\u30B8\u30BF\u30A4\u30D7\u3001\u30BD\u30FC\u30B9\u304A\u3088\u3073\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\u306F\u30CC\u30EB\u3067\u306F\u3044\u3051\u307E\u305B\u3093
|
||||
IngestMessage.toString.data.text=\ \u30C7\u30FC\u30BF\uFF1A{0}
|
||||
IngestMessage.toString.date.text=\ \u65E5\u4ED8\uFF1A{0}
|
||||
IngestMessage.toString.details.text=\ \u8A73\u7D30\uFF1A{0}
|
||||
IngestMessage.toString.subject.text=\ \u30B5\u30D6\u30B8\u30A7\u30AF\u30C8\uFF1A{0}
|
||||
IngestMessage.toString.type.text=\u30BF\u30A4\u30D7\uFF1A{0}
|
||||
IngestMessageDetailsPanel.copyMenuItem.text=\u30B3\u30D4\u30FC
|
||||
IngestMessageDetailsPanel.messageDetailsPane.contentType=\u30C6\u30AD\u30B9\u30C8\uFF0Fhtml
|
||||
IngestMessageDetailsPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629E
|
||||
IngestMessageDetailsPanel.viewArtifactButton.text=\u7D50\u679C\u3078\u79FB\u52D5
|
||||
IngestMessageDetailsPanel.viewContentButton.text=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3078\u79FB\u52D5
|
||||
IngestMessagePanel.BooleanRenderer.exception.nonBoolVal.msg=\u30D6\u30FC\u30EB\u5024\u3067\u306F\u306A\u3044\u3082\u306E\u306BBooleanRenderer\u3092\u4F7F\u7528\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F\u3002
|
||||
IngestMessagePanel.DateRenderer.exception.nonDateVal.text=\u65E5\u4ED8\u3067\u306F\u306A\u3044\u3082\u306E\u306BDateRenderer\u3092\u4F7F\u7528\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F\u3002
|
||||
IngestMessagePanel.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC
|
||||
IngestMessagePanel.moduleErr.errListenUpdates.text=IngestMessagePanel\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u30ED\u30B0\u3092\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u4E0D\u5B8C\u5168\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002
|
||||
IngestMessagePanel.MsgTableMod.colNames.module=\u30E2\u30B8\u30E5\u30FC\u30EB
|
||||
IngestMessagePanel.MsgTableMod.colNames.new=\u65B0\u898F\uFF1F
|
||||
IngestMessagePanel.MsgTableMod.colNames.num=\u756A\u53F7
|
||||
IngestMessagePanel.MsgTableMod.colNames.subject=\u30B5\u30D6\u30B8\u30A7\u30AF\u30C8
|
||||
IngestMessagePanel.MsgTableMod.colNames.timestamp=\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7
|
||||
IngestMessagePanel.sortByComboBox.model.priority=\u512A\u5148\u5EA6
|
||||
CTL_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8
|
||||
HINT_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8\u30a6\u30a3\u30f3\u30c9\u30a6
|
||||
IngestDialog.closeButton.title=\u9589\u3058\u308b
|
||||
IngestDialog.startButton.title=\u958b\u59cb
|
||||
IngestDialog.title.text=\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8
|
||||
IngestJob.progress.cancelling={0}\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026\uff09
|
||||
IngestJob.progress.dataSourceIngest.displayName={1}\u306e{0}
|
||||
IngestJob.progress.fileIngest.displayName={0}\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u89e3\u6790\u4e2d
|
||||
IngestManager.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc
|
||||
IngestManager.moduleErr.errListenToUpdates.msg=Ingest Manager\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002
|
||||
IngestManager.StartIngestJobsTask.run.cancelling={0}\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026\uff09
|
||||
IngestManager.StartIngestJobsTask.run.displayName=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u958b\u59cb\u4e2d
|
||||
IngestMessage.exception.srcSubjDetailsDataNotNull.msg=\u30bd\u30fc\u30b9\u3001\u30b5\u30d6\u30b8\u30a7\u30af\u30c8\u3001\u8a73\u7d30\u304a\u3088\u3073\u30c7\u30fc\u30bf\u306f\u30cc\u30eb\u3067\u306f\u3044\u3051\u307e\u305b\u3093
|
||||
IngestMessage.exception.srcSubjNotNull.msg=\u30bd\u30fc\u30b9\u304a\u3088\u3073\u30b5\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u30cc\u30eb\u3067\u306f\u3044\u3051\u307e\u305b\u3093
|
||||
IngestMessage.exception.typeSrcSubjNotNull.msg=\u30e1\u30c3\u30bb\u30fc\u30b8\u30bf\u30a4\u30d7\u3001\u30bd\u30fc\u30b9\u304a\u3088\u3073\u30b5\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u30cc\u30eb\u3067\u306f\u3044\u3051\u307e\u305b\u3093
|
||||
IngestMessage.toString.data.text=\ \u30c7\u30fc\u30bf\uff1a{0}
|
||||
IngestMessage.toString.date.text=\ \u65e5\u4ed8\uff1a{0}
|
||||
IngestMessage.toString.details.text=\ \u8a73\u7d30\uff1a{0}
|
||||
IngestMessage.toString.subject.text=\ \u30b5\u30d6\u30b8\u30a7\u30af\u30c8\uff1a{0}
|
||||
IngestMessage.toString.type.text=\u30bf\u30a4\u30d7\uff1a{0}
|
||||
IngestMessageDetailsPanel.copyMenuItem.text=\u30b3\u30d4\u30fc
|
||||
IngestMessageDetailsPanel.messageDetailsPane.contentType=\u30c6\u30ad\u30b9\u30c8\uff0fhtml
|
||||
IngestMessageDetailsPanel.selectAllMenuItem.text=\u3059\u3079\u3066\u9078\u629e
|
||||
IngestMessageDetailsPanel.viewArtifactButton.text=\u7d50\u679c\u3078\u79fb\u52d5
|
||||
IngestMessageDetailsPanel.viewContentButton.text=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3078\u79fb\u52d5
|
||||
IngestMessagePanel.BooleanRenderer.exception.nonBoolVal.msg=\u30d6\u30fc\u30eb\u5024\u3067\u306f\u306a\u3044\u3082\u306e\u306bBooleanRenderer\u3092\u4f7f\u7528\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u3002
|
||||
IngestMessagePanel.DateRenderer.exception.nonDateVal.text=\u65e5\u4ed8\u3067\u306f\u306a\u3044\u3082\u306e\u306bDateRenderer\u3092\u4f7f\u7528\u3057\u3088\u3046\u3068\u3057\u307e\u3057\u305f\u3002
|
||||
IngestMessagePanel.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc
|
||||
IngestMessagePanel.moduleErr.errListenUpdates.text=IngestMessagePanel\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002
|
||||
IngestMessagePanel.MsgTableMod.colNames.module=\u30e2\u30b8\u30e5\u30fc\u30eb
|
||||
IngestMessagePanel.MsgTableMod.colNames.new=\u65b0\u898f\uff1f
|
||||
IngestMessagePanel.MsgTableMod.colNames.num=\u756a\u53f7
|
||||
IngestMessagePanel.MsgTableMod.colNames.subject=\u30b5\u30d6\u30b8\u30a7\u30af\u30c8
|
||||
IngestMessagePanel.MsgTableMod.colNames.timestamp=\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7
|
||||
IngestMessagePanel.sortByComboBox.model.priority=\u512a\u5148\u5ea6
|
||||
IngestMessagePanel.sortByComboBox.model.time=\u6642\u9593
|
||||
IngestMessagePanel.sortByComboBox.toolTipText=\u6642\u9593\u9806\uFF08\u6642\u7CFB\u5217\uFF09\u307E\u305F\u306F\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u512A\u5148\u5EA6\u3067\u30BD\u30FC\u30C8
|
||||
IngestMessagePanel.sortByLabel.text=\u6B21\u3067\u30BD\u30FC\u30C8\uFF1A
|
||||
IngestMessagePanel.totalMessagesNameLabel.text=\u5408\u8A08\uFF1A
|
||||
IngestMessagePanel.sortByComboBox.toolTipText=\u6642\u9593\u9806\uff08\u6642\u7cfb\u5217\uff09\u307e\u305f\u306f\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u512a\u5148\u5ea6\u3067\u30bd\u30fc\u30c8
|
||||
IngestMessagePanel.sortByLabel.text=\u6b21\u3067\u30bd\u30fc\u30c8\uff1a
|
||||
IngestMessagePanel.totalMessagesNameLabel.text=\u5408\u8a08\uff1a
|
||||
IngestMessagePanel.totalMessagesNameVal.text=-
|
||||
IngestMessagePanel.totalUniqueMessagesNameLabel.text=\u30E6\u30CB\u30FC\u30AF\uFF1A
|
||||
IngestMessagePanel.totalUniqueMessagesNameLabel.text=\u30e6\u30cb\u30fc\u30af\uff1a
|
||||
IngestMessagePanel.totalUniqueMessagesNameVal.text=-
|
||||
IngestMessagesToolbar.customizeButton.toolTipText=\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8
|
||||
IngestMessageTopComponent.displayName=\u30A4\u30F3\u30DC\u30C3\u30AF\u30B9\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8
|
||||
IngestMessageTopComponent.displayReport.option.GenRpt=\u30EC\u30DD\u30FC\u30C8\u3092\u751F\u6210
|
||||
IngestMessagesToolbar.customizeButton.toolTipText=\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8
|
||||
IngestMessageTopComponent.displayName=\u30a4\u30f3\u30dc\u30c3\u30af\u30b9\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8
|
||||
IngestMessageTopComponent.displayReport.option.GenRpt=\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210
|
||||
IngestMessageTopComponent.displayReport.option.OK=OK
|
||||
IngestMessageTopComponent.initComponents.name=\u30A4\u30F3\u30DC\u30C3\u30AF\u30B9\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8
|
||||
IngestMessageTopComponent.msgDlg.ingestRpt.text=\u30EC\u30DD\u30FC\u30C8\u3092\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8
|
||||
IngestMonitor.mgrErrMsg.lowDiskSpace.msg=\u30C7\u30A3\u30B9\u30AF{0}\u306E\u30C7\u30A3\u30B9\u30AF\u9818\u57DF\u4E0D\u8DB3\u306E\u305F\u3081\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u4E2D\u6B62\u3057\u307E\u3059\u3002\n\u30B1\u30FC\u30B9\u30C9\u30E9\u30A4\u30D6\u306B\u6700\u4F4E1GB\u306E\u7A7A\u304D\u9818\u57DF\u304C\u3042\u308B\u306E\u3092\u78BA\u8A8D\u3057\u3001\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u518D\u5B9F\u884C\u3057\u3066\u4E0B\u3055\u3044\u3002
|
||||
IngestMonitor.mgrErrMsg.lowDiskSpace.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u304C\u4E2D\u6B62\u3055\u308C\u307E\u3057\u305F\u30FC{0}\u306E\u30C7\u30A3\u30B9\u30AF\u9818\u57DF\u4E0D\u8DB3
|
||||
OpenIDE-Module-Name=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8
|
||||
IngestManager.StartIngestJobsTask.run.startupErr.dlgErrorList=\n\u30A8\u30E9\u30FC\uFF1A\n{0}
|
||||
IngestManager.StartIngestJobsTask.run.startupErr.dlgMsg=\u5358\u6570\u307E\u305F\u306F\u8907\u6570\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30B9\u30BF\u30FC\u30C8\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u306F\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\u3002
|
||||
IngestManager.StartIngestJobsTask.run.startupErr.dlgSolution=\u5931\u6557\u3057\u305F\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u7121\u52B9\u5316\u3059\u308B\u304B\u30A8\u30E9\u30FC\u3092\u89E3\u6C7A\u3057\u3001\u305D\u306E\u5F8C\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u3092\u53F3\u30AF\u30EA\u30C3\u30AF\u3057\u3001\n\u300C\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u5B9F\u884C\u300D\u3092\u9078\u629E\u3057\u3066\u3001\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u518D\u5B9F\u884C\u3057\u3066\u4E0B\u3055\u3044\u3002
|
||||
IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u5931\u6557
|
||||
IngestJobSettings.createModuleSettingsFolder.warning=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u8A2D\u5B9A\u30D5\u30A9\u30EB\u30C0\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3002
|
||||
IngestJob.progress.dataSourceIngest.initialDisplayName={0}\u3092\u89E3\u6790\u4E2D
|
||||
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.dataSource=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9
|
||||
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.elapsedTime=\u7D4C\u904E\u6642\u9593\uFF08\u6642\uFF1A\u5206\uFF1A\u79D2\uFF09
|
||||
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.file=\u30D5\u30A1\u30A4\u30EB
|
||||
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.startTime=\u958B\u59CB\u6642\u9593
|
||||
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.threadID=\u30B9\u30EC\u30C3\u30C9ID
|
||||
IngestManager.IngestMessage.ErrorMessageLimitReached.msg=\u6700\u5927\u6570({0})\u306E\u30A8\u30E9\u30FC\u304A\u3088\u3073\u307E\u305F\u306F\u8B66\u544A\u30E1\u30C3\u30BB\u30FC\u30B8\u304C\u63B2\u8F09\u3055\u308C\u307E\u3057\u305F\u3002\u3055\u3089\u306A\u308B\u30A8\u30E9\u30FC\uFF0F\u8B66\u544A\u306F\u30ED\u30B0\u3092\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\uFF08\u30D8\u30EB\u30D7->\u30ED\u30B0\u30D5\u30A9\u30EB\u30C0\u30FC\u3092\u958B\u304F\uFF09
|
||||
IngestManager.IngestMessage.ErrorMessageLimitReached.subject=\u6700\u5927\u6570\u306E\u30A8\u30E9\u30FC\u304C\u63B2\u8F09\u3055\u308C\u307E\u3057\u305F
|
||||
IngestManager.IngestMessage.ErrorMessageLimitReached.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30DE\u30CD\u30B8\u30E3\u30FC
|
||||
IngestManager.IngestThreadActivitySnapshot.idleThread=\u30A2\u30A4\u30C9\u30EB
|
||||
IngestProgressSnapshotDialog.title.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30D7\u30ED\u30B0\u30EC\u30B9\u30FB\u30B9\u30CA\u30C3\u30D7\u30B7\u30E7\u30C3\u30C8
|
||||
IngestProgressSnapshotPanel.closeButton.text=\u9589\u3058\u308B
|
||||
IngestProgressSnapshotPanel.refreshButton.text=\u30EA\u30D5\u30EC\u30C3\u30B7\u30E5
|
||||
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.activity=\u30A2\u30AF\u30C6\u30A3\u30D3\u30C6\u30A3
|
||||
IngestJobSettingsPanel.advancedButton.actionCommand=\u30A2\u30C9\u30D0\u30F3\u30B9
|
||||
IngestJobSettingsPanel.advancedButton.text=\u30A2\u30C9\u30D0\u30F3\u30B9
|
||||
IngestMessageTopComponent.initComponents.name=\u30a4\u30f3\u30dc\u30c3\u30af\u30b9\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8
|
||||
IngestMessageTopComponent.msgDlg.ingestRpt.text=\u30ec\u30dd\u30fc\u30c8\u3092\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8
|
||||
IngestMonitor.mgrErrMsg.lowDiskSpace.msg=\u30c7\u30a3\u30b9\u30af{0}\u306e\u30c7\u30a3\u30b9\u30af\u9818\u57df\u4e0d\u8db3\u306e\u305f\u3081\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u4e2d\u6b62\u3057\u307e\u3059\u3002\n\u30b1\u30fc\u30b9\u30c9\u30e9\u30a4\u30d6\u306b\u6700\u4f4e1GB\u306e\u7a7a\u304d\u9818\u57df\u304c\u3042\u308b\u306e\u3092\u78ba\u8a8d\u3057\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u518d\u5b9f\u884c\u3057\u3066\u4e0b\u3055\u3044\u3002
|
||||
IngestMonitor.mgrErrMsg.lowDiskSpace.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u4e2d\u6b62\u3055\u308c\u307e\u3057\u305f\u30fc{0}\u306e\u30c7\u30a3\u30b9\u30af\u9818\u57df\u4e0d\u8db3
|
||||
OpenIDE-Module-Name=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8
|
||||
IngestManager.StartIngestJobsTask.run.startupErr.dlgErrorList=\n\u30a8\u30e9\u30fc\uff1a\n{0}
|
||||
IngestManager.StartIngestJobsTask.run.startupErr.dlgMsg=\u5358\u6570\u307e\u305f\u306f\u8907\u6570\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u30b9\u30bf\u30fc\u30c8\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u306f\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u307e\u3057\u305f\u3002
|
||||
IngestManager.StartIngestJobsTask.run.startupErr.dlgSolution=\u5931\u6557\u3057\u305f\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u7121\u52b9\u5316\u3059\u308b\u304b\u30a8\u30e9\u30fc\u3092\u89e3\u6c7a\u3057\u3001\u305d\u306e\u5f8c\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u3092\u53f3\u30af\u30ea\u30c3\u30af\u3057\u3001\n\u300c\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u5b9f\u884c\u300d\u3092\u9078\u629e\u3057\u3066\u3001\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u518d\u5b9f\u884c\u3057\u3066\u4e0b\u3055\u3044\u3002
|
||||
IngestManager.StartIngestJobsTask.run.startupErr.dlgTitle=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u5931\u6557
|
||||
IngestJobSettings.createModuleSettingsFolder.warning=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u8a2d\u5b9a\u30d5\u30a9\u30eb\u30c0\u306e\u4f5c\u6210\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u8a2d\u5b9a\u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3002
|
||||
IngestJob.progress.dataSourceIngest.initialDisplayName={0}\u3092\u89e3\u6790\u4e2d
|
||||
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.dataSource=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9
|
||||
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.elapsedTime=\u7d4c\u904e\u6642\u9593\uff08\u6642\uff1a\u5206\uff1a\u79d2\uff09
|
||||
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.file=\u30d5\u30a1\u30a4\u30eb
|
||||
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.startTime=\u958b\u59cb\u6642\u9593
|
||||
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.threadID=\u30b9\u30ec\u30c3\u30c9ID
|
||||
IngestManager.IngestMessage.ErrorMessageLimitReached.msg=\u6700\u5927\u6570({0})\u306e\u30a8\u30e9\u30fc\u304a\u3088\u3073\u307e\u305f\u306f\u8b66\u544a\u30e1\u30c3\u30bb\u30fc\u30b8\u304c\u63b2\u8f09\u3055\u308c\u307e\u3057\u305f\u3002\u3055\u3089\u306a\u308b\u30a8\u30e9\u30fc\uff0f\u8b66\u544a\u306f\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\uff08\u30d8\u30eb\u30d7->\u30ed\u30b0\u30d5\u30a9\u30eb\u30c0\u30fc\u3092\u958b\u304f\uff09
|
||||
IngestManager.IngestMessage.ErrorMessageLimitReached.subject=\u6700\u5927\u6570\u306e\u30a8\u30e9\u30fc\u304c\u63b2\u8f09\u3055\u308c\u307e\u3057\u305f
|
||||
IngestManager.IngestMessage.ErrorMessageLimitReached.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30de\u30cd\u30b8\u30e3\u30fc
|
||||
IngestManager.IngestThreadActivitySnapshot.idleThread=\u30a2\u30a4\u30c9\u30eb
|
||||
IngestProgressSnapshotDialog.title.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30d7\u30ed\u30b0\u30ec\u30b9\u30fb\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8
|
||||
IngestProgressSnapshotPanel.closeButton.text=\u9589\u3058\u308b
|
||||
IngestProgressSnapshotPanel.refreshButton.text=\u30ea\u30d5\u30ec\u30c3\u30b7\u30e5
|
||||
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.activity=\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3
|
||||
IngestJobSettingsPanel.advancedButton.actionCommand=\u30a2\u30c9\u30d0\u30f3\u30b9
|
||||
IngestJobSettingsPanel.advancedButton.text=\u30a2\u30c9\u30d0\u30f3\u30b9
|
||||
ModuleTableModel.colName.duration=\u6240\u8981\u6642\u9593
|
||||
IngestJob.cancellationDialog.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u30AD\u30E3\u30F3\u30BB\u30EB
|
||||
IngestJobSettings.missingModule.warning=\u4EE5\u524D\u306B\u8AAD\u307F\u8FBC\u3093\u3060{0}\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002
|
||||
DataSourceIngestCancellationPanel.cancelAllModulesRadioButton.text=\u5168\u3066\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30AD\u30E3\u30F3\u30BB\u30EB
|
||||
DataSourceIngestCancellationPanel.cancelCurrentModuleRadioButton.text=\u73FE\u5728\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u307F\u30AD\u30E3\u30F3\u30BB\u30EB
|
||||
FileIngestCancellationPanel.cancelFileIngestRadioButton.text=\u30D5\u30A1\u30A4\u30EB\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u306E\u307F\u30AD\u30E3\u30F3\u30BB\u30EB
|
||||
FileIngestCancellationPanel.cancelIngestJobRadioButton.text=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u304A\u3088\u3073\u30D5\u30A1\u30A4\u30EB\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u30AD\u30E3\u30F3\u30BB\u30EB
|
||||
IngestJobSettings.moduleSettingsLoad.warning={1}\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u306E{0}\u30E2\u30B8\u30E5\u30FC\u30EB\u7528\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u8A2D\u5B9A\u3092\u8AAD\u307F\u8FBC\u307F\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u8A2D\u5B9A\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002
|
||||
IngestJobSettings.save.warning={0}\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002
|
||||
IngestJobTableModel.colName.dataSource=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9
|
||||
IngestJobTableModel.colName.dirQueued=\u30AD\u30E5\u30FC\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA
|
||||
IngestJobTableModel.colName.filesPerSec=\u30D5\u30A1\u30A4\u30EB\uFF0F\u79D2
|
||||
IngestJobTableModel.colName.filesQueued=\u30AD\u30E5\u30FC\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB
|
||||
IngestJobTableModel.colName.inProgress=\u51E6\u7406\u4E2D
|
||||
IngestJobTableModel.colName.jobID=\u30B8\u30E7\u30D6ID
|
||||
IngestJobTableModel.colName.numProcessed=\u51E6\u7406\u3055\u308C\u305F\u6570
|
||||
IngestJobTableModel.colName.rootQueued=\u30AD\u30E5\u30FC\u3055\u308C\u305F\u30EB\u30FC\u30C8
|
||||
IngestJobTableModel.colName.start=\u30B9\u30BF\u30FC\u30C8
|
||||
IngestModuleFactoryLoader.errorMessages.duplicateDisplayName=\u5225\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u540D\u524D\u3092\u91CD\u8907\u3059\u308B\u3001{0}\u306E\u540D\u524D\u3092\u6301\u3064\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F\u3002\u30E2\u30B8\u30E5\u30FC\u30EB\u306F\u4F7F\u7528\u3057\u307E\u305B\u3093\u3002
|
||||
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.jobID=\u30B8\u30E7\u30D6ID
|
||||
ModuleTableModel.colName.module=\u30E2\u30B8\u30E5\u30FC\u30EB
|
||||
IngestJobSettingsPanel.processUnallocCheckbox.toolTipText=\u524A\u9664\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u7B49\u306E\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u3092\u51E6\u7406\u3002\u3088\u308A\u5B8C\u5168\u306A\u7D50\u679C\u304C\u51FA\u307E\u3059\u304C\u3001\u5927\u304D\u3044\u30A4\u30E1\u30FC\u30B8\u3067\u306F\u51E6\u7406\u6642\u9593\u304C\u9577\u304F\u306A\u308B\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002
|
||||
IngestJob.cancellationDialog.title=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u30ad\u30e3\u30f3\u30bb\u30eb
|
||||
IngestJobSettings.missingModule.warning=\u4ee5\u524d\u306b\u8aad\u307f\u8fbc\u3093\u3060{0}\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002
|
||||
DataSourceIngestCancellationPanel.cancelAllModulesRadioButton.text=\u5168\u3066\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u30ad\u30e3\u30f3\u30bb\u30eb
|
||||
DataSourceIngestCancellationPanel.cancelCurrentModuleRadioButton.text=\u73fe\u5728\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u307f\u30ad\u30e3\u30f3\u30bb\u30eb
|
||||
FileIngestCancellationPanel.cancelFileIngestRadioButton.text=\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306e\u307f\u30ad\u30e3\u30f3\u30bb\u30eb
|
||||
FileIngestCancellationPanel.cancelIngestJobRadioButton.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304a\u3088\u3073\u30d5\u30a1\u30a4\u30eb\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u30ad\u30e3\u30f3\u30bb\u30eb
|
||||
IngestJobSettings.moduleSettingsLoad.warning={1}\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u306e{0}\u30e2\u30b8\u30e5\u30fc\u30eb\u7528\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a\u3092\u8aad\u307f\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u8a2d\u5b9a\u3092\u4f7f\u7528\u3057\u3066\u3044\u307e\u3059\u3002
|
||||
IngestJobSettings.save.warning={0}\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a\u3092\u4fdd\u5b58\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
|
||||
IngestJobTableModel.colName.dataSource=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9
|
||||
IngestJobTableModel.colName.dirQueued=\u30ad\u30e5\u30fc\u3055\u308c\u305f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea
|
||||
IngestJobTableModel.colName.filesPerSec=\u30d5\u30a1\u30a4\u30eb\uff0f\u79d2
|
||||
IngestJobTableModel.colName.filesQueued=\u30ad\u30e5\u30fc\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb
|
||||
IngestJobTableModel.colName.inProgress=\u51e6\u7406\u4e2d
|
||||
IngestJobTableModel.colName.jobID=\u30b8\u30e7\u30d6ID
|
||||
IngestJobTableModel.colName.numProcessed=\u51e6\u7406\u3055\u308c\u305f\u6570
|
||||
IngestJobTableModel.colName.rootQueued=\u30ad\u30e5\u30fc\u3055\u308c\u305f\u30eb\u30fc\u30c8
|
||||
IngestJobTableModel.colName.start=\u30b9\u30bf\u30fc\u30c8
|
||||
IngestModuleFactoryLoader.errorMessages.duplicateDisplayName=\u5225\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u540d\u524d\u3092\u91cd\u8907\u3059\u308b\u3001{0}\u306e\u540d\u524d\u3092\u6301\u3064\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u3057\u305f\u3002\u30e2\u30b8\u30e5\u30fc\u30eb\u306f\u4f7f\u7528\u3057\u307e\u305b\u3093\u3002
|
||||
IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.jobID=\u30b8\u30e7\u30d6ID
|
||||
ModuleTableModel.colName.module=\u30e2\u30b8\u30e5\u30fc\u30eb
|
||||
IngestJobSettingsPanel.processUnallocCheckbox.toolTipText=\u524a\u9664\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u7b49\u306e\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u3092\u51e6\u7406\u3002\u3088\u308a\u5b8c\u5168\u306a\u7d50\u679c\u304c\u51fa\u307e\u3059\u304c\u3001\u5927\u304d\u3044\u30a4\u30e1\u30fc\u30b8\u3067\u306f\u51e6\u7406\u6642\u9593\u304c\u9577\u304f\u306a\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002
|
||||
|
||||
IngestJobSettingsPanel.processUnallocCheckbox.text=\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u306E\u51E6\u7406
|
||||
Menu/Tools/RunIngestModules=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u5B9F\u884C
|
||||
IngestJob.progress.fileIngest.cancelMessage={1}\u306E{0}\u3092\u5F85\u3063\u3066\u3044\u307E\u3059
|
||||
IngestManager.OpenEventChannel.Fail.ErrMsg=\u3053\u306E\u30B1\u30FC\u30B9\u3067\u4F7F\u308F\u308C\u3066\u3044\u308B\u304B\u3082\u3057\u308C\u306A\u3044\u4ED6\u306E\u30CE\u30FC\u30C9\u306B\u89E3\u6790\u30D7\u30ED\u30BB\u30B9\u304C\u63A5\u7D9A\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002
|
||||
IngestManager.OpenEventChannel.Fail.Title=\u63A5\u7D9A\u5931\u6557
|
||||
IngestJobSettings.moduleSettingsSave.warning={1}\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u306E{0}\u30E2\u30B8\u30E5\u30FC\u30EB\u7528\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u8A2D\u5B9A\u3092\u8AAD\u307F\u8FBC\u307F\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002
|
||||
IngestJobTableModel.colName.dsQueued=\u30AD\u30E5\u30FC\u3055\u308C\u305FDS
|
||||
IngestJobSettingsPanel.jButtonSelectAll.text=\u5168\u3066\u9078\u629E
|
||||
IngestJobSettingsPanel.jButtonDeselectAll.text=\u5168\u3066\u9078\u629E\u89E3\u9664
|
||||
IngestManager.cancellingIngest.msgDlg.text=\u73FE\u5728\u5B9F\u884C\u4E2D\u306E\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30B8\u30E7\u30D6\u3092\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D
|
||||
IngestManager.serviceIsDown.msgDlg.text={0}\u304C\u30C0\u30A6\u30F3\u3057\u3066\u3044\u307E\u3059
|
||||
RunIngestSubMenu.menuItem.empty=\u30FC\u7A7A\u767D\u30FC
|
||||
RunIngestModulesMenu.getName.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u5B9F\u884C
|
||||
DataSourceIngestPipeline.moduleError.title.text={0}\u30A8\u30E9\u30FC
|
||||
FileIngestPipeline.moduleError.title.text={0}\u30A8\u30E9\u30FC
|
||||
IngestJob.cancelReason.notCancelled.text=\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u3066\u3044\u307E\u305B\u3093
|
||||
IngestJob.cancelReason.cancelledByUser.text=\u30E6\u30FC\u30B6\u30FC\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3057\u305F
|
||||
IngestJob.cancelReason.ingestModStartFail.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u8D77\u52D5\u306B\u5931\u6557
|
||||
IngestJob.cancelReason.outOfDiskSpace.text=\u30C7\u30A3\u30B9\u30AF\u30B9\u30DA\u30FC\u30B9\u304C\u8DB3\u308A\u307E\u305B\u3093
|
||||
IngestJob.cancelReason.servicesDown.text=\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F
|
||||
IngestJob.cancelReason.caseClosed.text=\u30B1\u30FC\u30B9\u3092\u9589\u3058\u307E\u3057\u305F
|
||||
IngestJobSettingsPanel.processUnallocCheckbox.text=\u672a\u5272\u308a\u5f53\u3066\u9818\u57df\u306e\u51e6\u7406
|
||||
Menu/Tools/RunIngestModules=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c
|
||||
IngestJob.progress.fileIngest.cancelMessage={1}\u306e{0}\u3092\u5f85\u3063\u3066\u3044\u307e\u3059
|
||||
IngestManager.OpenEventChannel.Fail.ErrMsg=\u3053\u306e\u30b1\u30fc\u30b9\u3067\u4f7f\u308f\u308c\u3066\u3044\u308b\u304b\u3082\u3057\u308c\u306a\u3044\u4ed6\u306e\u30ce\u30fc\u30c9\u306b\u89e3\u6790\u30d7\u30ed\u30bb\u30b9\u304c\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
|
||||
IngestManager.OpenEventChannel.Fail.Title=\u63a5\u7d9a\u5931\u6557
|
||||
IngestJobSettings.moduleSettingsSave.warning={1}\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u306e{0}\u30e2\u30b8\u30e5\u30fc\u30eb\u7528\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a\u3092\u8aad\u307f\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
|
||||
IngestJobTableModel.colName.dsQueued=\u30ad\u30e5\u30fc\u3055\u308c\u305fDS
|
||||
IngestJobSettingsPanel.jButtonSelectAll.text=\u5168\u3066\u9078\u629e
|
||||
IngestJobSettingsPanel.jButtonDeselectAll.text=\u5168\u3066\u9078\u629e\u89e3\u9664
|
||||
IngestManager.cancellingIngest.msgDlg.text=\u73fe\u5728\u5b9f\u884c\u4e2d\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u3092\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d
|
||||
IngestManager.serviceIsDown.msgDlg.text={0}\u304c\u30c0\u30a6\u30f3\u3057\u3066\u3044\u307e\u3059
|
||||
RunIngestSubMenu.menuItem.empty=\u30fc\u7a7a\u767d\u30fc
|
||||
RunIngestModulesMenu.getName.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c
|
||||
DataSourceIngestPipeline.moduleError.title.text={0}\u30a8\u30e9\u30fc
|
||||
FileIngestPipeline.moduleError.title.text={0}\u30a8\u30e9\u30fc
|
||||
IngestJob.cancelReason.notCancelled.text=\u30ad\u30e3\u30f3\u30bb\u30eb\u3055\u308c\u3066\u3044\u307e\u305b\u3093
|
||||
IngestJob.cancelReason.cancelledByUser.text=\u30e6\u30fc\u30b6\u30fc\u304c\u30ad\u30e3\u30f3\u30bb\u30eb\u3057\u307e\u3057\u305f
|
||||
IngestJob.cancelReason.ingestModStartFail.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u8d77\u52d5\u306b\u5931\u6557
|
||||
IngestJob.cancelReason.outOfDiskSpace.text=\u30c7\u30a3\u30b9\u30af\u30b9\u30da\u30fc\u30b9\u304c\u8db3\u308a\u307e\u305b\u3093
|
||||
IngestJob.cancelReason.caseClosed.text=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u307e\u3057\u305f
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -39,8 +39,10 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.python.util.PythonObjectInputStream;
|
||||
|
||||
/**
|
||||
* Encapsulates the ingest job settings for a particular context such as the Add
|
||||
* Data Source wizard or the Run Ingest Modules dialog.
|
||||
* Encapsulates the ingest job settings for a particular execution context.
|
||||
* Examples of execution contexts include the add data source wizard and the run
|
||||
* ingest modules dialog. Different execution conterxts may have different
|
||||
* ingest job settings.
|
||||
*/
|
||||
public class IngestJobSettings {
|
||||
|
||||
@ -60,19 +62,30 @@ public class IngestJobSettings {
|
||||
private boolean processUnallocatedSpace;
|
||||
private final List<String> warnings;
|
||||
|
||||
// Determines which modeules to run
|
||||
/**
|
||||
* The type of ingest modules to run.
|
||||
*/
|
||||
public enum IngestType {
|
||||
|
||||
// Run all modules
|
||||
/**
|
||||
* Run both data source level and file-level ingest modules.
|
||||
*/
|
||||
ALL_MODULES,
|
||||
// Run only data source modules
|
||||
/**
|
||||
* Run only data source level ingest modules.
|
||||
*/
|
||||
DATA_SOURCE_ONLY,
|
||||
// Run only files modules
|
||||
/**
|
||||
* Run only file level ingest modules.
|
||||
*/
|
||||
FILES_ONLY
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an ingest job settings object for a given context.
|
||||
* Constructs an ingest job settings object for a given execution context.
|
||||
* Examples of execution contexts include the add data source wizard and the
|
||||
* run ingest modules dialog. Different execution conterxts may have
|
||||
* different ingest job settings.
|
||||
*
|
||||
* @param executionContext The ingest execution context identifier.
|
||||
*/
|
||||
@ -87,7 +100,10 @@ public class IngestJobSettings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an ingest job settings object for a given context.
|
||||
* Constructs an ingest job settings object for a given context. Examples of
|
||||
* execution contexts include the add data source wizard and the run ingest
|
||||
* modules dialog. Different execution conterxts may have different ingest
|
||||
* job settings.
|
||||
*
|
||||
* @param context The context identifier string.
|
||||
* @param ingestType The type of modules ingest is running.
|
||||
@ -116,9 +132,12 @@ public class IngestJobSettings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ingest execution context identifier.
|
||||
* Gets the ingest execution context identifier. Examples of execution
|
||||
* contexts include the add data source wizard and the run ingest modules
|
||||
* dialog. Different execution conterxts may have different ingest job
|
||||
* settings.
|
||||
*
|
||||
* @return The context string.
|
||||
* @return The execution context identifier.
|
||||
*/
|
||||
String getExecutionContext() {
|
||||
return this.executionContext;
|
||||
|
@ -71,28 +71,27 @@ public class IngestManager {
|
||||
private static IngestManager instance;
|
||||
private final Object ingestMessageBoxLock = new Object();
|
||||
|
||||
/**
|
||||
* The ingest manager maintains a mapping of ingest job IDs to running
|
||||
/*
|
||||
* The ingest manager maintains a mapping of ingest job ids to running
|
||||
* ingest jobs.
|
||||
*/
|
||||
private final ConcurrentHashMap<Long, IngestJob> jobsById;
|
||||
private final Map<Long, IngestJob> jobsById;
|
||||
|
||||
/**
|
||||
/*
|
||||
* Each runnable/callable task the ingest manager submits to its thread
|
||||
* pools is given a unique thread/task ID.
|
||||
*/
|
||||
private final AtomicLong nextThreadId;
|
||||
|
||||
/**
|
||||
* Ingest jobs may be queued to be started on a pool thread by ingest job
|
||||
* starters. A mapping of thread/task IDs to the result objects associated
|
||||
* with each ingest job starter is maintained to provide handles that can be
|
||||
* used to cancel the ingest job starter.
|
||||
/*
|
||||
* Ingest jobs may be queued to be started on a pool thread by start ingest
|
||||
* job tasks. A mapping of task ids to the Future objects for each task is
|
||||
* maintained to allow for task cancellation.
|
||||
*/
|
||||
private final ConcurrentHashMap<Long, Future<Void>> ingestJobStarters;
|
||||
private final Map<Long, Future<Void>> startIngestJobTasks;
|
||||
private final ExecutorService startIngestJobsThreadPool;
|
||||
|
||||
/**
|
||||
/*
|
||||
* Ingest jobs use an ingest task scheduler to break themselves down into
|
||||
* data source level and file level tasks. The ingest scheduler puts these
|
||||
* ingest tasks into queues for execution on ingest manager pool threads by
|
||||
@ -118,14 +117,14 @@ public class IngestManager {
|
||||
private AutopsyEventPublisher moduleEventPublisher;
|
||||
private final ExecutorService eventPublishingExecutor;
|
||||
|
||||
/**
|
||||
/*
|
||||
* The ingest manager uses an ingest monitor to determine when system
|
||||
* resources are under pressure. If the monitor detects such a situation, it
|
||||
* calls back to the ingest manager to cancel all ingest jobs in progress.
|
||||
*/
|
||||
private final IngestMonitor ingestMonitor;
|
||||
|
||||
/**
|
||||
/*
|
||||
* The ingest manager provides access to a top component that is used by
|
||||
* ingest module to post messages for the user. A count of the posts is used
|
||||
* as a cap to avoid bogging down the application.
|
||||
@ -134,7 +133,7 @@ public class IngestManager {
|
||||
private volatile IngestMessageTopComponent ingestMessageBox;
|
||||
private final AtomicLong ingestErrorMessagePosts;
|
||||
|
||||
/**
|
||||
/*
|
||||
* The ingest manager supports reporting of ingest processing progress by
|
||||
* collecting snapshots of the activities of the ingest threads, ingest job
|
||||
* progress, and ingest module run times.
|
||||
@ -142,13 +141,13 @@ public class IngestManager {
|
||||
private final ConcurrentHashMap<Long, IngestThreadActivitySnapshot> ingestThreadActivitySnapshots;
|
||||
private final ConcurrentHashMap<String, Long> ingestModuleRunTimes;
|
||||
|
||||
/**
|
||||
/*
|
||||
* The ingest job creation capability of the ingest manager can be turned on
|
||||
* and off to support an orderly shut down of the application.
|
||||
*/
|
||||
private volatile boolean jobCreationIsEnabled;
|
||||
|
||||
/**
|
||||
/*
|
||||
* Ingest manager subscribes to service outage notifications. If key
|
||||
* services are down, ingest manager cancels all ingest jobs in progress.
|
||||
*/
|
||||
@ -264,8 +263,8 @@ public class IngestManager {
|
||||
this.dataSourceIngestThreadPool = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("IM-data-source-ingest-%d").build()); //NON-NLS
|
||||
this.startIngestJobsThreadPool = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("IM-start-ingest-jobs-%d").build()); //NON-NLS
|
||||
this.nextThreadId = new AtomicLong(0L);
|
||||
this.jobsById = new ConcurrentHashMap<>();
|
||||
this.ingestJobStarters = new ConcurrentHashMap<>();
|
||||
this.jobsById = new HashMap<>();
|
||||
this.startIngestJobTasks = new ConcurrentHashMap<>();
|
||||
|
||||
this.servicesMonitor = ServicesMonitor.getInstance();
|
||||
subscribeToServiceMonitorEvents();
|
||||
@ -329,7 +328,7 @@ public class IngestManager {
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (evt.getNewValue().equals(ServicesMonitor.ServiceStatus.DOWN.toString())) {
|
||||
|
||||
// check whether a milti-user case is currently being processed
|
||||
// check whether a multi-user case is currently being processed
|
||||
try {
|
||||
if (!Case.isCaseOpen() || Case.getCurrentCase().getCaseType() != Case.CaseType.MULTI_USER_CASE) {
|
||||
return;
|
||||
@ -474,13 +473,13 @@ public class IngestManager {
|
||||
* @param dataSources The data sources to process.
|
||||
* @param settings The settings for the ingest job.
|
||||
*/
|
||||
public synchronized void queueIngestJob(Collection<Content> dataSources, IngestJobSettings settings) {
|
||||
if (this.jobCreationIsEnabled) {
|
||||
public void queueIngestJob(Collection<Content> dataSources, IngestJobSettings settings) {
|
||||
if (jobCreationIsEnabled) {
|
||||
IngestJob job = new IngestJob(dataSources, settings, RuntimeProperties.coreComponentsAreActive());
|
||||
if (job.hasIngestPipeline()) {
|
||||
long taskId = nextThreadId.incrementAndGet();
|
||||
Future<Void> task = startIngestJobsThreadPool.submit(new StartIngestJobTask(taskId, job));
|
||||
ingestJobStarters.put(taskId, task);
|
||||
startIngestJobTasks.put(taskId, task);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -544,20 +543,18 @@ public class IngestManager {
|
||||
ingestMonitor.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the job to the jobs map now so that isIngestRunning() will
|
||||
* return true while the modules read global settings during start
|
||||
* up. This works because the core global settings panels restrict
|
||||
* changes while analysis is in progress.
|
||||
*/
|
||||
this.jobsById.put(job.getId(), job);
|
||||
synchronized (jobsById) {
|
||||
jobsById.put(job.getId(), job);
|
||||
}
|
||||
List<IngestModuleError> errors = job.start();
|
||||
if (errors.isEmpty()) {
|
||||
this.fireIngestJobStarted(job.getId());
|
||||
IngestManager.logger.log(Level.INFO, "Ingest job {0} started", job.getId()); //NON-NLS
|
||||
success = true;
|
||||
} else {
|
||||
synchronized (jobsById) {
|
||||
this.jobsById.remove(job.getId());
|
||||
}
|
||||
for (IngestModuleError error : errors) {
|
||||
logger.log(Level.SEVERE, String.format("Error starting %s ingest module", error.getModuleDisplayName()), error.getModuleError()); //NON-NLS
|
||||
}
|
||||
@ -599,13 +596,15 @@ public class IngestManager {
|
||||
|
||||
synchronized void finishIngestJob(IngestJob job) {
|
||||
long jobId = job.getId();
|
||||
this.jobsById.remove(jobId);
|
||||
synchronized (jobsById) {
|
||||
jobsById.remove(jobId);
|
||||
}
|
||||
if (!job.isCancelled()) {
|
||||
IngestManager.logger.log(Level.INFO, "Ingest job {0} completed", jobId); //NON-NLS
|
||||
this.fireIngestJobCompleted(jobId);
|
||||
fireIngestJobCompleted(jobId);
|
||||
} else {
|
||||
IngestManager.logger.log(Level.INFO, "Ingest job {0} cancelled", jobId); //NON-NLS
|
||||
this.fireIngestJobCancelled(jobId);
|
||||
fireIngestJobCancelled(jobId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -615,7 +614,9 @@ public class IngestManager {
|
||||
* @return True or false.
|
||||
*/
|
||||
public boolean isIngestRunning() {
|
||||
return !this.jobsById.isEmpty();
|
||||
synchronized (jobsById) {
|
||||
return !jobsById.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -625,7 +626,7 @@ public class IngestManager {
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public synchronized void cancelAllIngestJobs() {
|
||||
public void cancelAllIngestJobs() {
|
||||
cancelAllIngestJobs(IngestJob.CancellationReason.USER_CANCELLED);
|
||||
}
|
||||
|
||||
@ -634,17 +635,23 @@ public class IngestManager {
|
||||
*
|
||||
* @param reason The cancellation reason.
|
||||
*/
|
||||
public synchronized void cancelAllIngestJobs(IngestJob.CancellationReason reason) {
|
||||
// Stop creating new ingest jobs.
|
||||
for (Future<Void> handle : ingestJobStarters.values()) {
|
||||
public void cancelAllIngestJobs(IngestJob.CancellationReason reason) {
|
||||
/*
|
||||
* Cancel the start job tasks.
|
||||
*/
|
||||
for (Future<Void> handle : startIngestJobTasks.values()) {
|
||||
handle.cancel(true);
|
||||
}
|
||||
|
||||
// Cancel all the jobs already created.
|
||||
/*
|
||||
* Cancel the jobs in progress.
|
||||
*/
|
||||
synchronized (jobsById) {
|
||||
for (IngestJob job : this.jobsById.values()) {
|
||||
job.cancel(reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an ingest job event property change listener.
|
||||
@ -903,9 +910,11 @@ public class IngestManager {
|
||||
*/
|
||||
List<DataSourceIngestJob.Snapshot> getIngestJobSnapshots() {
|
||||
List<DataSourceIngestJob.Snapshot> snapShots = new ArrayList<>();
|
||||
for (IngestJob job : this.jobsById.values()) {
|
||||
synchronized (jobsById) {
|
||||
for (IngestJob job : jobsById.values()) {
|
||||
snapShots.addAll(job.getDataSourceIngestJobSnapshots());
|
||||
}
|
||||
}
|
||||
return snapShots;
|
||||
}
|
||||
|
||||
@ -941,7 +950,9 @@ public class IngestManager {
|
||||
public Void call() {
|
||||
try {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
synchronized (jobsById) {
|
||||
jobsById.remove(job.getId());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -953,7 +964,7 @@ public class IngestManager {
|
||||
if (progress != null) {
|
||||
progress.setDisplayName(NbBundle.getMessage(this.getClass(), "IngestManager.StartIngestJobsTask.run.cancelling", displayName));
|
||||
}
|
||||
Future<?> handle = ingestJobStarters.remove(threadId);
|
||||
Future<?> handle = startIngestJobTasks.remove(threadId);
|
||||
handle.cancel(true);
|
||||
return true;
|
||||
}
|
||||
@ -968,7 +979,7 @@ public class IngestManager {
|
||||
if (null != progress) {
|
||||
progress.finish();
|
||||
}
|
||||
ingestJobStarters.remove(threadId);
|
||||
startIngestJobTasks.remove(threadId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -39,11 +39,14 @@ import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.Directory;
|
||||
|
||||
/**
|
||||
* Dialog box that allows a user to configure and run an ingest job on one or
|
||||
* more data sources.
|
||||
*
|
||||
* A dialog box that allows a user to configure and execute analysis of one or
|
||||
* more data sources with ingest modules or analysis of the contents of a
|
||||
* directory with file-level ingest modules.
|
||||
*/
|
||||
public final class RunIngestModulesDialog extends JDialog {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String TITLE = NbBundle.getMessage(RunIngestModulesDialog.class, "IngestDialog.title.text");
|
||||
private final IngestType ingestType;
|
||||
private static Dimension DIMENSIONS = new Dimension(500, 300);
|
||||
@ -51,13 +54,13 @@ public final class RunIngestModulesDialog extends JDialog {
|
||||
private IngestJobSettingsPanel ingestJobSettingsPanel;
|
||||
|
||||
/**
|
||||
* Construct a dialog box that allows a user to configure and run an ingest
|
||||
* job on one or more data sources.
|
||||
* Constructs a dialog box that allows a user to configure and execute
|
||||
* analysis of one or more data sources with ingest modules.
|
||||
*
|
||||
* @param frame The dialog parent window.
|
||||
* @param title The title for the dialog.
|
||||
* @param modal True if the dialog should be modal, false otherwise.
|
||||
* @param dataSources The data sources to be processed.
|
||||
* @param dataSources The data sources to be analyzed.
|
||||
*/
|
||||
public RunIngestModulesDialog(JFrame frame, String title, boolean modal, List<Content> dataSources) {
|
||||
super(frame, title, modal);
|
||||
@ -66,8 +69,8 @@ public final class RunIngestModulesDialog extends JDialog {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a dialog box that allows a user to configure and run an ingest
|
||||
* job on one or more data sources.
|
||||
* Constructs a dialog box that allows a user to configure and execute
|
||||
* analysis of one or more data sources with ingest modules.
|
||||
*
|
||||
* @param dataSources The data sources to be processed.
|
||||
*/
|
||||
@ -75,51 +78,17 @@ public final class RunIngestModulesDialog extends JDialog {
|
||||
this(new JFrame(TITLE), TITLE, true, dataSources);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a dialog box that allows a user to configure and execute
|
||||
* analysis of the contents of a directory with file-level ingest modules.
|
||||
*
|
||||
* @param dir
|
||||
*/
|
||||
public RunIngestModulesDialog(Directory dir) {
|
||||
this.dataSources.add(dir);
|
||||
this.ingestType = IngestType.FILES_ONLY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a dialog box that allows a user to configure and run an ingest
|
||||
* job on one or more data sources.
|
||||
*
|
||||
* @param frame The dialog parent window.
|
||||
* @param title The title for the dialog.
|
||||
* @param modal True if the dialog should be modal, false otherwise.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public RunIngestModulesDialog(JFrame frame, String title, boolean modal) {
|
||||
super(frame, title, modal);
|
||||
this.ingestType = IngestType.ALL_MODULES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a dialog box that allows a user to configure and run an ingest
|
||||
* job on one or more data sources.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public RunIngestModulesDialog() {
|
||||
this(new JFrame(TITLE), TITLE, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the data sources to be processed.
|
||||
*
|
||||
* @param dataSources The data sources.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public void setDataSources(List<Content> dataSources) {
|
||||
this.dataSources.clear();
|
||||
this.dataSources.addAll(dataSources);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays this dialog.
|
||||
*/
|
||||
@ -227,4 +196,45 @@ public final class RunIngestModulesDialog extends JDialog {
|
||||
JOptionPane.showMessageDialog(null, warningMessage.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a dialog box that allows a user to configure and execute
|
||||
* analysis of one or more data sources with ingest modules.
|
||||
*
|
||||
* @param frame The dialog parent window.
|
||||
* @param title The title for the dialog.
|
||||
* @param modal True if the dialog should be modal, false otherwise.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public RunIngestModulesDialog(JFrame frame, String title, boolean modal) {
|
||||
super(frame, title, modal);
|
||||
this.ingestType = IngestType.ALL_MODULES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a dialog box that allows a user to configure and run an ingest
|
||||
* job on one or more data sources.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public RunIngestModulesDialog() {
|
||||
this(new JFrame(TITLE), TITLE, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data sources to be processed.
|
||||
*
|
||||
* @param dataSources The data sources.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public void setDataSources(List<Content> dataSources) {
|
||||
this.dataSources.clear();
|
||||
this.dataSources.addAll(dataSources);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -49,26 +49,77 @@ public class UserArtifactIngestModule implements DataSourceIngestModule {
|
||||
FileManager manager = Case.getCurrentCase().getServices().getFileManager();
|
||||
List<AbstractFile> file1 = manager.findFiles("Sunset.jpg"); //NON-NLS
|
||||
List<AbstractFile> file2 = manager.findFiles("Winter.jpg"); //NON-NLS
|
||||
BlackboardArtifact art1;
|
||||
List<BlackboardArtifact> currArtifacts = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF);
|
||||
BlackboardArtifact art1 = currArtifacts.size() == 0 ? null : currArtifacts.get(0);
|
||||
BlackboardArtifact art2;
|
||||
if (art1 == null) {
|
||||
if (!file1.isEmpty()) {
|
||||
art1 = file1.get(0).newArtifact(type1.getTypeID());
|
||||
} else {
|
||||
art1 = dataSource.newArtifact(type1.getTypeID());
|
||||
}
|
||||
}
|
||||
if (!file2.isEmpty()) {
|
||||
art2 = file2.get(0).newArtifact(type2.getTypeID());
|
||||
} else {
|
||||
art2 = dataSource.newArtifact(type2.getTypeID());
|
||||
}
|
||||
BlackboardAttribute.Type attributeType = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("Test", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG, "2"); //NON-NLS
|
||||
BlackboardAttribute.Type attributeType2 = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("Test2", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE, "3"); //NON-NLS
|
||||
BlackboardAttribute.Type attributeType = Case.getCurrentCase().getSleuthkitCase().getAttributeType("Test8");
|
||||
if (attributeType == null) {
|
||||
attributeType = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("Test8", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG, "Header6");
|
||||
}
|
||||
BlackboardAttribute.Type attributeType2 = Case.getCurrentCase().getSleuthkitCase().getAttributeType("Test9");
|
||||
if (attributeType2 == null) {
|
||||
attributeType2 = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("Test9", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME, "Header7");
|
||||
|
||||
}
|
||||
BlackboardAttribute.Type attributeType3 = Case.getCurrentCase().getSleuthkitCase().getAttributeType("Test0");
|
||||
if (attributeType3 == null) {
|
||||
attributeType3 = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("Test0", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Header8");
|
||||
|
||||
}
|
||||
BlackboardAttribute.Type attributeType4 = Case.getCurrentCase().getSleuthkitCase().getAttributeType("TestA");
|
||||
if (attributeType4 == null) {
|
||||
attributeType4 = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("TestA", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.INTEGER, "Header9");
|
||||
|
||||
}
|
||||
BlackboardAttribute.Type attributeType5 = Case.getCurrentCase().getSleuthkitCase().getAttributeType("TestB");
|
||||
if (attributeType5 == null) {
|
||||
attributeType5 = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("TestB", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DOUBLE, "Header0");
|
||||
|
||||
}
|
||||
BlackboardAttribute.Type attributeType6 = Case.getCurrentCase().getSleuthkitCase().getAttributeType("TestC");
|
||||
if (attributeType6 == null) {
|
||||
attributeType6 = Case.getCurrentCase().getServices().getBlackboard().addAttributeType("TestC", TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE, "HeaderA");
|
||||
|
||||
}
|
||||
art1.addAttribute(new BlackboardAttribute(attributeType,
|
||||
UserArtifactIngestModuleFactory.getModuleName(), -1L));
|
||||
progressBar.progress(1);
|
||||
UserArtifactIngestModuleFactory.getModuleName(), 12345678L));
|
||||
art1.addAttribute(new BlackboardAttribute(attributeType2,
|
||||
UserArtifactIngestModuleFactory.getModuleName(), 1457105587962L));
|
||||
art1.addAttribute(new BlackboardAttribute(attributeType3,
|
||||
UserArtifactIngestModuleFactory.getModuleName(), "STRING VALUE TEST"));
|
||||
art1.addAttribute(new BlackboardAttribute(attributeType4,
|
||||
UserArtifactIngestModuleFactory.getModuleName(), 1234));
|
||||
art1.addAttribute(new BlackboardAttribute(attributeType5,
|
||||
UserArtifactIngestModuleFactory.getModuleName(), 1234.5678D));
|
||||
byte[] bytes = new byte[2];
|
||||
bytes[0] = 12;
|
||||
bytes[1] = 100;
|
||||
art1.addAttribute(new BlackboardAttribute(attributeType6,
|
||||
UserArtifactIngestModuleFactory.getModuleName(), bytes));
|
||||
art2.addAttribute(new BlackboardAttribute(attributeType2,
|
||||
UserArtifactIngestModuleFactory.getModuleName(), new byte[7]));
|
||||
progressBar.progress(1);
|
||||
UserArtifactIngestModuleFactory.getModuleName(), 1457105587962L));
|
||||
art2.addAttribute(new BlackboardAttribute(attributeType,
|
||||
UserArtifactIngestModuleFactory.getModuleName(), 12345678L));
|
||||
art2.addAttribute(new BlackboardAttribute(attributeType3,
|
||||
UserArtifactIngestModuleFactory.getModuleName(), "STRING VALUE TEST"));
|
||||
art2.addAttribute(new BlackboardAttribute(attributeType4,
|
||||
UserArtifactIngestModuleFactory.getModuleName(), 1234));
|
||||
art2.addAttribute(new BlackboardAttribute(attributeType5,
|
||||
UserArtifactIngestModuleFactory.getModuleName(), 1234.5678D));
|
||||
art2.addAttribute(new BlackboardAttribute(attributeType6,
|
||||
UserArtifactIngestModuleFactory.getModuleName(), bytes));
|
||||
IngestServices.getInstance().postMessage(IngestMessage.createDataMessage(
|
||||
"name", // NON-NLS
|
||||
UserArtifactIngestModuleFactory.getModuleName(),
|
||||
@ -84,9 +135,15 @@ public class UserArtifactIngestModule implements DataSourceIngestModule {
|
||||
@Override
|
||||
public void startUp(IngestJobContext context) throws IngestModuleException {
|
||||
try {
|
||||
type1 = Case.getCurrentCase().getServices().getBlackboard().addArtifactType("This is", "a test"); //NON-NLS
|
||||
type2 = Case.getCurrentCase().getServices().getBlackboard().addArtifactType("Another", "kinda test"); //NON-NLS
|
||||
} catch (BlackboardException ex) {
|
||||
type1 = Case.getCurrentCase().getSleuthkitCase().getArtifactType("FINAL TEST a");
|
||||
type2 = Case.getCurrentCase().getSleuthkitCase().getArtifactType("FINAL TEST b");
|
||||
if (type1 == null) {
|
||||
type1 = Case.getCurrentCase().getServices().getBlackboard().addArtifactType("FINAL TEST a", "FINAL TEST a"); //NON-NLS
|
||||
}
|
||||
if (type2 == null) {
|
||||
type2 = Case.getCurrentCase().getServices().getBlackboard().addArtifactType("FINAL TEST b", "FINAL TEST b"); //NON-NLS
|
||||
}
|
||||
} catch (BlackboardException | TskCoreException ex) {
|
||||
Logger.logMsg(Logger.ERROR, "Startup failed"); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
@ -19,15 +19,17 @@
|
||||
package org.sleuthkit.autopsy.modules.UserArtifacts;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.python.apache.xmlcommons.Version;
|
||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleFactory;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
|
||||
|
||||
/**
|
||||
* Factory for test module that creates new artifact and attribute types.
|
||||
*/
|
||||
//@ServiceProvider(service = IngestModuleFactory.class)
|
||||
@ServiceProvider(service = IngestModuleFactory.class)
|
||||
public class UserArtifactIngestModuleFactory extends IngestModuleFactoryAdapter {
|
||||
|
||||
static String getModuleName() {
|
||||
|
@ -79,7 +79,7 @@ public final class EmbeddedFileExtractorIngestModule implements FileIngestModule
|
||||
} catch (SecurityException ex) {
|
||||
logger.log(Level.SEVERE, "Error initializing output dir: " + moduleDirAbsolute, ex); //NON-NLS
|
||||
services.postMessage(IngestMessage.createErrorMessage(EmbeddedFileExtractorModuleFactory.getModuleName(), "Error initializing", "Error initializing output dir: " + moduleDirAbsolute)); //NON-NLS
|
||||
throw new IngestModuleException(ex.getMessage());
|
||||
throw new IngestModuleException(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,7 +87,7 @@ public final class EmbeddedFileExtractorIngestModule implements FileIngestModule
|
||||
try {
|
||||
fileTypeDetector = new FileTypeDetector();
|
||||
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
|
||||
throw new IngestModuleException(ex.getMessage());
|
||||
throw new IngestModuleException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
// initialize the extraction modules.
|
||||
|
@ -133,7 +133,7 @@ class SevenZipExtractor {
|
||||
String details = NbBundle.getMessage(SevenZipExtractor.class, "EmbeddedFileExtractorIngestModule.ArchiveExtractor.init.errCantInitLib",
|
||||
e.getMessage());
|
||||
services.postMessage(IngestMessage.createErrorMessage(EmbeddedFileExtractorModuleFactory.getModuleName(), msg, details));
|
||||
throw new IngestModuleException(e.getMessage());
|
||||
throw new IngestModuleException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
this.context = context;
|
||||
|
@ -91,7 +91,7 @@ public final class ExifParserFileIngestModule implements FileIngestModule {
|
||||
try {
|
||||
fileTypeDetector = new FileTypeDetector();
|
||||
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
|
||||
throw new IngestModuleException(NbBundle.getMessage(this.getClass(), "ExifParserFileIngestModule.startUp.fileTypeDetectorInitializationException.msg"));
|
||||
throw new IngestModuleException(NbBundle.getMessage(this.getClass(), "ExifParserFileIngestModule.startUp.fileTypeDetectorInitializationException.msg"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,13 +18,11 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.modules.fileextmismatch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
|
||||
@ -40,7 +38,6 @@ import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.TskException;
|
||||
@ -58,6 +55,7 @@ public class FileExtMismatchIngestModule implements FileIngestModule {
|
||||
private static final HashMap<Long, IngestJobTotals> totalsForIngestJobs = new HashMap<>();
|
||||
private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter();
|
||||
private static Blackboard blackboard;
|
||||
private FileTypeDetector detector;
|
||||
|
||||
private static class IngestJobTotals {
|
||||
|
||||
@ -94,6 +92,11 @@ public class FileExtMismatchIngestModule implements FileIngestModule {
|
||||
|
||||
FileExtMismatchXML xmlLoader = FileExtMismatchXML.getDefault();
|
||||
SigTypeToExtMap = xmlLoader.load();
|
||||
try {
|
||||
this.detector = new FileTypeDetector();
|
||||
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
|
||||
throw new IngestModuleException("Could not create file type detector.", ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -157,7 +160,7 @@ public class FileExtMismatchIngestModule implements FileIngestModule {
|
||||
if (settings.skipFilesWithNoExtension() && currActualExt.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
String currActualSigType = abstractFile.getMIMEType();
|
||||
String currActualSigType = detector.getFileType(abstractFile);
|
||||
if (currActualSigType == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -35,10 +35,10 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.datamodel.TskData;
|
||||
import org.sleuthkit.datamodel.TskDataException;
|
||||
|
||||
/**
|
||||
* Detects the type of a file by an inspection of its contents.
|
||||
* Detects the MIME type of a file by an inspection of its contents, using both
|
||||
* user-defined type definitions and Tika.
|
||||
*/
|
||||
public class FileTypeDetector {
|
||||
|
||||
@ -49,11 +49,14 @@ public class FileTypeDetector {
|
||||
private static final Logger logger = Logger.getLogger(FileTypeDetector.class.getName());
|
||||
|
||||
/**
|
||||
* Constructs an object that detects the type of a file by an inspection of
|
||||
* its contents.
|
||||
* Constructs an object that detects the MIME type of a file by an
|
||||
* inspection of its contents, using both user-defined type definitions and
|
||||
* Tika.
|
||||
*
|
||||
* @throws FileTypeDetector.FileTypeDetectorInitException if an
|
||||
* initialization error occurs.
|
||||
* @throws FileTypeDetectorInitException if an initialization error occurs,
|
||||
* e.g., user-defined file type
|
||||
* definitions exist but cannot be
|
||||
* loaded.
|
||||
*/
|
||||
public FileTypeDetector() throws FileTypeDetectorInitException {
|
||||
try {
|
||||
@ -64,12 +67,26 @@ public class FileTypeDetector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not a given MIME type is detectable by this
|
||||
* detector.
|
||||
* Gets the names of the user-defined MIME types.
|
||||
*
|
||||
* @param mimeType The MIME type name, e.g. "text/html", to look up.
|
||||
* @return A list of the user-defined MIME types.
|
||||
*/
|
||||
public List<String> getUserDefinedTypes() {
|
||||
List<String> list = new ArrayList<>();
|
||||
if (userDefinedFileTypes != null) {
|
||||
for (FileType fileType : userDefinedFileTypes) {
|
||||
list.add(fileType.getMimeType());
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not a given MIME type is detectable.
|
||||
*
|
||||
* @return True if MIME type is detectable.
|
||||
* @param mimeType The MIME type name (e.g., "text/html").
|
||||
*
|
||||
* @return True if the given MIME type is detectable.
|
||||
*/
|
||||
public boolean isDetectable(String mimeType) {
|
||||
return isDetectableAsUserDefinedType(mimeType) || isDetectableByTika(mimeType);
|
||||
@ -77,11 +94,11 @@ public class FileTypeDetector {
|
||||
|
||||
/**
|
||||
* Determines whether or not a given MIME type is detectable as a
|
||||
* user-defined file type.
|
||||
* user-defined MIME type.
|
||||
*
|
||||
* @param mimeType The MIME type name, e.g. "text/html", to look up.
|
||||
* @param mimeType The MIME type name (e.g., "text/html").
|
||||
*
|
||||
* @return True if MIME type is detectable.
|
||||
* @return True if the given MIME type is detectable.
|
||||
*/
|
||||
private boolean isDetectableAsUserDefinedType(String mimeType) {
|
||||
for (FileType fileType : userDefinedFileTypes) {
|
||||
@ -95,9 +112,9 @@ public class FileTypeDetector {
|
||||
/**
|
||||
* Determines whether or not a given MIME type is detectable by Tika.
|
||||
*
|
||||
* @param mimeType The MIME type name, e.g. "text/html", to look up.
|
||||
* @param mimeType The MIME type name (e.g., "text/html").
|
||||
*
|
||||
* @return True if MIME type is detectable.
|
||||
* @return True if the given MIME type is detectable.
|
||||
*/
|
||||
private boolean isDetectableByTika(String mimeType) {
|
||||
String[] split = mimeType.split("/");
|
||||
@ -112,59 +129,42 @@ public class FileTypeDetector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the MIME type of a file using the blackboard. If it is not
|
||||
* already posted, detect the type of the file, posting it to the blackboard
|
||||
* if detection succeeds.
|
||||
* Gets the MIME type of a file, detecting it if it is not already known. If
|
||||
* detection is necessary, the result is added to the case database.
|
||||
*
|
||||
* @param file The file to test.
|
||||
* @param file The file.
|
||||
*
|
||||
* @return The MIME type name if detection was successful, null otherwise.
|
||||
* @return A MIME type name.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
public String getFileType(AbstractFile file) throws TskCoreException {
|
||||
String fileType = file.getMIMEType();
|
||||
if (null != fileType) {
|
||||
return fileType;
|
||||
}
|
||||
return detectAndPostToBlackboard(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the MIME type of a file, posting it to the blackboard if detection
|
||||
* succeeds. Note that this method should currently be called at most once
|
||||
* per file.
|
||||
*
|
||||
* @param file The file to test.
|
||||
*
|
||||
* @return The MIME type name id detection was successful, null otherwise.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
* @throws TskCoreException if detection is required and there is a problem
|
||||
* writing the result to the case database.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public String detectAndPostToBlackboard(AbstractFile file) throws TskCoreException {
|
||||
String mimeType = detect(file);
|
||||
public String getFileType(AbstractFile file) throws TskCoreException {
|
||||
String mimeType = file.getMIMEType();
|
||||
if (null != mimeType) {
|
||||
/**
|
||||
* Add the file type attribute to the general info artifact. Note
|
||||
* that no property change is fired for this blackboard posting
|
||||
* because general info artifacts are different from other
|
||||
* artifacts, e.g., they are not displayed in the results tree.
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
mimeType = detect(file);
|
||||
Case.getCurrentCase().getSleuthkitCase().setFileMIMEType(file, mimeType);
|
||||
|
||||
/*
|
||||
* Add the file type attribute to the general info artifact. Note that
|
||||
* no property change is fired for this blackboard posting because
|
||||
* general info artifacts are different from other artifacts, e.g., they
|
||||
* are not displayed in the results tree.
|
||||
*/
|
||||
try {
|
||||
file.setMIMEType(mimeType);
|
||||
BlackboardArtifact getInfoArt = file.getGenInfoArtifact();
|
||||
BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType);
|
||||
getInfoArt.addAttribute(batt);
|
||||
} catch (TskDataException ex) {
|
||||
//Swallowing exception so that the logs aren't clogged in the case that ingest is run multiple times.
|
||||
}
|
||||
}
|
||||
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the MIME type of a file.
|
||||
* Detects the MIME type of a file. The result is not added to the case
|
||||
* database.
|
||||
*
|
||||
* @param file The file to test.
|
||||
*
|
||||
@ -173,9 +173,12 @@ public class FileTypeDetector {
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
public String detect(AbstractFile file) throws TskCoreException {
|
||||
// consistently mark non-regular files (refer TskData.TSK_FS_META_TYPE_ENUM),
|
||||
// 0 sized files, unallocated, and unused blocks (refer TskData.TSK_DB_FILES_TYPE_ENUM)
|
||||
// as octet-stream.
|
||||
/*
|
||||
* Consistently mark non-regular files (refer to
|
||||
* TskData.TSK_FS_META_TYPE_ENUM), zero-sized files, unallocated space,
|
||||
* and unused blocks (refer to TskData.TSK_DB_FILES_TYPE_ENUM) as
|
||||
* octet-stream.
|
||||
*/
|
||||
if (!file.isFile() || file.getSize() <= 0
|
||||
|| (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
|
||||
|| (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS)
|
||||
@ -183,8 +186,8 @@ public class FileTypeDetector {
|
||||
return MimeTypes.OCTET_STREAM;
|
||||
}
|
||||
|
||||
String fileType = detectUserDefinedType(file);
|
||||
if (null == fileType) {
|
||||
String mimeType = detectUserDefinedType(file);
|
||||
if (null == mimeType) {
|
||||
try {
|
||||
byte buf[];
|
||||
int len = file.read(buffer, 0, BUFFER_SIZE);
|
||||
@ -195,23 +198,25 @@ public class FileTypeDetector {
|
||||
buf = buffer;
|
||||
}
|
||||
|
||||
String mimetype = tika.detect(buf, file.getName());
|
||||
String tikaType = tika.detect(buf, file.getName());
|
||||
|
||||
/**
|
||||
* Strip out any Tika enhancements to the MIME type name.
|
||||
*/
|
||||
return mimetype.replace("tika-", ""); //NON-NLS
|
||||
mimeType = tikaType.replace("tika-", ""); //NON-NLS
|
||||
|
||||
} catch (Exception ignored) {
|
||||
/**
|
||||
* This exception is swallowed rather than propagated because
|
||||
* files in images are not always consistent with their file
|
||||
* system meta data making for read errors, and Tika can be a
|
||||
* bit flaky at times, making this a best effort endeavor.
|
||||
/*
|
||||
* This exception is swallowed and not logged rather than
|
||||
* propagated because files in data sources are not always
|
||||
* consistent with their file system metadata, making for read
|
||||
* errors, and Tika can be a bit flaky at times, making this a
|
||||
* best effort endeavor. Default to octet-stream.
|
||||
*/
|
||||
mimeType = MimeTypes.OCTET_STREAM;
|
||||
}
|
||||
}
|
||||
return fileType;
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -235,7 +240,7 @@ public class FileTypeDetector {
|
||||
BlackboardAttribute setNameAttribute = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, FileTypeIdModuleFactory.getModuleName(), fileType.getFilesSetName());
|
||||
artifact.addAttribute(setNameAttribute);
|
||||
|
||||
/**
|
||||
/*
|
||||
* Use the MIME type as the category, i.e., the rule that
|
||||
* determined this file belongs to the interesting files
|
||||
* set.
|
||||
@ -259,6 +264,7 @@ public class FileTypeDetector {
|
||||
}
|
||||
|
||||
public static class FileTypeDetectorInitException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
FileTypeDetectorInitException(String message) {
|
||||
@ -271,17 +277,22 @@ public class FileTypeDetector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of user defined file types (MIME types)
|
||||
* Gets the MIME type of a file, detecting it if it is not already known. If
|
||||
* detection is necessary, the result is added to the case database.
|
||||
*
|
||||
* @return the List<String> of user defined file types
|
||||
* @param file The file.
|
||||
*
|
||||
* @return A MIME type name.
|
||||
*
|
||||
* @throws TskCoreException if detection is required and there is a problem
|
||||
* writing the result to the case database.
|
||||
* @deprecated Use getFileType instead and use AbstractFile.getMIMEType
|
||||
* instead of querying the blackboard.
|
||||
*/
|
||||
public List<String> getUserDefinedTypes() {
|
||||
List<String> list = new ArrayList<>();
|
||||
if (userDefinedFileTypes != null) {
|
||||
for (FileType fileType : userDefinedFileTypes) {
|
||||
list.add(fileType.getMimeType());
|
||||
}
|
||||
}
|
||||
return list;
|
||||
@Deprecated
|
||||
@SuppressWarnings("deprecation")
|
||||
public String detectAndPostToBlackboard(AbstractFile file) throws TskCoreException {
|
||||
return getFileType(file);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,52 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="skipKnownCheckBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="46" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="-2" pref="11" max="-2" attributes="0"/>
|
||||
<Component id="skipKnownCheckBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="86" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JCheckBox" name="skipKnownCheckBox">
|
||||
<Properties>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties" key="FileTypeIdIngestJobSettingsPanel.skipKnownCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/modules/filetypeid/Bundle.properties" key="FileTypeIdIngestJobSettingsPanel.skipKnownCheckBox.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="skipKnownCheckBoxActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 - 2014 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.modules.filetypeid;
|
||||
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
|
||||
|
||||
/**
|
||||
* UI component used to set ingest job options for file type identifier ingest
|
||||
* modules.
|
||||
*/
|
||||
class FileTypeIdIngestJobSettingsPanel extends IngestModuleIngestJobSettingsPanel {
|
||||
|
||||
private final FileTypeIdModuleSettings settings;
|
||||
|
||||
FileTypeIdIngestJobSettingsPanel(FileTypeIdModuleSettings settings) {
|
||||
this.settings = settings;
|
||||
initComponents();
|
||||
customizeComponents();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public IngestModuleIngestJobSettings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does child component initialization in addition to that done by the
|
||||
* Matisse generated code.
|
||||
*/
|
||||
private void customizeComponents() {
|
||||
skipKnownCheckBox.setSelected(settings.skipKnownFiles());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
skipKnownCheckBox = new javax.swing.JCheckBox();
|
||||
|
||||
skipKnownCheckBox.setSelected(true);
|
||||
skipKnownCheckBox.setText(org.openide.util.NbBundle.getMessage(FileTypeIdIngestJobSettingsPanel.class, "FileTypeIdIngestJobSettingsPanel.skipKnownCheckBox.text")); // NOI18N
|
||||
skipKnownCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(FileTypeIdIngestJobSettingsPanel.class, "FileTypeIdIngestJobSettingsPanel.skipKnownCheckBox.toolTipText")); // NOI18N
|
||||
skipKnownCheckBox.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
skipKnownCheckBoxActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(skipKnownCheckBox)
|
||||
.addContainerGap(46, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(11, 11, 11)
|
||||
.addComponent(skipKnownCheckBox)
|
||||
.addContainerGap(86, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void skipKnownCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_skipKnownCheckBoxActionPerformed
|
||||
settings.setSkipKnownFiles(skipKnownCheckBox.isSelected());
|
||||
}//GEN-LAST:event_skipKnownCheckBoxActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JCheckBox skipKnownCheckBox;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
@ -27,7 +27,6 @@ import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||
import org.sleuthkit.autopsy.ingest.IngestMessage;
|
||||
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.TskData.FileKnown;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModule.ProcessResult;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
|
||||
|
||||
@ -38,7 +37,6 @@ import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
|
||||
public class FileTypeIdIngestModule implements FileIngestModule {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(FileTypeIdIngestModule.class.getName());
|
||||
private final FileTypeIdModuleSettings settings;
|
||||
private long jobId;
|
||||
private static final HashMap<Long, IngestJobTotals> totalsForIngestJobs = new HashMap<>();
|
||||
private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter();
|
||||
@ -66,11 +64,8 @@ public class FileTypeIdIngestModule implements FileIngestModule {
|
||||
/**
|
||||
* Creates an ingest module that detects the type of a file based on
|
||||
* signature (magic) values. Posts results to the blackboard.
|
||||
*
|
||||
* @param settings The ingest module settings.
|
||||
*/
|
||||
FileTypeIdIngestModule(FileTypeIdModuleSettings settings) {
|
||||
this.settings = settings;
|
||||
FileTypeIdIngestModule() {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,7 +78,7 @@ public class FileTypeIdIngestModule implements FileIngestModule {
|
||||
try {
|
||||
fileTypeDetector = new FileTypeDetector();
|
||||
} catch (FileTypeDetector.FileTypeDetectorInitException ex) {
|
||||
throw new IngestModuleException(NbBundle.getMessage(this.getClass(), "FileTypeIdIngestModule.startUp.fileTypeDetectorInitializationException.msg"));
|
||||
throw new IngestModuleException(NbBundle.getMessage(this.getClass(), "FileTypeIdIngestModule.startUp.fileTypeDetectorInitializationException.msg"), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,13 +88,6 @@ public class FileTypeIdIngestModule implements FileIngestModule {
|
||||
@Override
|
||||
public ProcessResult process(AbstractFile file) {
|
||||
|
||||
/**
|
||||
* Skip known files if configured to do so.
|
||||
*/
|
||||
if (settings.skipKnownFiles() && (file.getKnown() == FileKnown.KNOWN)) {
|
||||
return ProcessResult.OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to detect the file type. Do it within an exception firewall,
|
||||
* so that any issues with reading file content or complaints from tika
|
||||
|
@ -26,7 +26,6 @@ import org.sleuthkit.autopsy.ingest.IngestModuleFactory;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
|
||||
|
||||
/**
|
||||
* A factory that creates file ingest modules that determine the types of files.
|
||||
@ -92,35 +91,6 @@ public class FileTypeIdModuleFactory extends IngestModuleFactoryAdapter {
|
||||
return globalSettingsPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public IngestModuleIngestJobSettings getDefaultIngestJobSettings() {
|
||||
return new FileTypeIdModuleSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean hasIngestJobSettingsPanel() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings settings) {
|
||||
assert settings instanceof FileTypeIdModuleSettings;
|
||||
if (!(settings instanceof FileTypeIdModuleSettings)) {
|
||||
throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(),
|
||||
"FileTypeIdModuleFactory.getIngestJobSettingsPanel.exception.msg"));
|
||||
}
|
||||
return new FileTypeIdIngestJobSettingsPanel((FileTypeIdModuleSettings) settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@ -134,11 +104,6 @@ public class FileTypeIdModuleFactory extends IngestModuleFactoryAdapter {
|
||||
*/
|
||||
@Override
|
||||
public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings settings) {
|
||||
assert settings instanceof FileTypeIdModuleSettings;
|
||||
if (!(settings instanceof FileTypeIdModuleSettings)) {
|
||||
throw new IllegalArgumentException(
|
||||
NbBundle.getMessage(this.getClass(), "FileTypeIdModuleFactory.createFileIngestModule.exception.msg"));
|
||||
}
|
||||
return new FileTypeIdIngestModule((FileTypeIdModuleSettings) settings);
|
||||
return new FileTypeIdIngestModule();
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.modules.filetypeid;
|
||||
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
|
||||
|
||||
/**
|
||||
* Ingest job options for the file type identifier ingest module instances.
|
||||
*/
|
||||
// TODO: This class does not need to be public.
|
||||
public class FileTypeIdModuleSettings implements IngestModuleIngestJobSettings {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private boolean skipKnownFiles = true;
|
||||
private boolean skipSmallFiles = false; // No longer used.
|
||||
|
||||
FileTypeIdModuleSettings() {
|
||||
}
|
||||
|
||||
FileTypeIdModuleSettings(boolean skipKnownFiles) {
|
||||
this.skipKnownFiles = skipKnownFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public long getVersionNumber() {
|
||||
return serialVersionUID;
|
||||
}
|
||||
|
||||
void setSkipKnownFiles(boolean enabled) {
|
||||
skipKnownFiles = enabled;
|
||||
}
|
||||
|
||||
boolean skipKnownFiles() {
|
||||
return skipKnownFiles;
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -59,7 +59,6 @@ import org.xml.sax.SAXException;
|
||||
final class UserDefinedFileTypesManager {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(UserDefinedFileTypesManager.class.getName());
|
||||
private static final String FILE_TYPE_DEFINITIONS_SCHEMA_FILE = "FileTypes.xsd"; //NON-NLS
|
||||
private static final String USER_DEFINED_TYPE_DEFINITIONS_FILE = "UserFileTypeDefinitions.xml"; //NON-NLS
|
||||
private static final String FILE_TYPES_TAG_NAME = "FileTypes"; //NON-NLS
|
||||
private static final String FILE_TYPE_TAG_NAME = "FileType"; //NON-NLS
|
||||
@ -72,7 +71,6 @@ final class UserDefinedFileTypesManager {
|
||||
private static final String INTERESTING_FILES_SET_TAG_NAME = "InterestingFileSset"; //NON-NLS
|
||||
private static final String ALERT_ATTRIBUTE = "alert"; //NON-NLS
|
||||
private static final String ENCODING_FOR_XML_FILE = "UTF-8"; //NON-NLS
|
||||
private static final String ASCII_ENCODING = "US-ASCII"; //NON-NLS
|
||||
private static UserDefinedFileTypesManager instance;
|
||||
|
||||
/**
|
||||
@ -233,8 +231,7 @@ final class UserDefinedFileTypesManager {
|
||||
byteArray = DatatypeConverter.parseHexBinary("54525545564953494F4E2D5846494C452E00"); //NON-NLS
|
||||
fileType = new FileType("image/x-tga", new Signature(byteArray, 17, false), "", false); //NON-NLS
|
||||
fileTypes.add(fileType);
|
||||
}
|
||||
// parseHexBinary() throws this if the argument passed in is not Hex
|
||||
} // parseHexBinary() throws this if the argument passed in is not Hex
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new UserDefinedFileTypesException("Error creating predefined file types", e); //
|
||||
}
|
||||
@ -415,6 +412,13 @@ final class UserDefinedFileTypesManager {
|
||||
fileTypeElem.setAttribute(ALERT_ATTRIBUTE, Boolean.toString(fileType.alertOnMatch()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor suppresses creation of instanmces of this utility
|
||||
* class.
|
||||
*/
|
||||
private XmlWriter() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -432,7 +436,17 @@ final class UserDefinedFileTypesManager {
|
||||
*/
|
||||
private static List<FileType> readFileTypes(String filePath) throws IOException, ParserConfigurationException, SAXException {
|
||||
List<FileType> fileTypes = new ArrayList<>();
|
||||
Document doc = XMLUtil.loadDocument(filePath, UserDefinedFileTypesManager.class, FILE_TYPE_DEFINITIONS_SCHEMA_FILE);
|
||||
/*
|
||||
* RC: Commenting out the loadDocument overload that validates
|
||||
* against the XSD is a temp fix for a failure to provide an upgrade
|
||||
* path when the RelativeToStart attribute was added to the
|
||||
* Signature element. The upgrade path can be supplied, but the plan
|
||||
* is to replace the use of XML with object serialization for the
|
||||
* settings, so it may not be worth the effort.
|
||||
*/
|
||||
// private static final String FILE_TYPE_DEFINITIONS_SCHEMA_FILE = "FileTypes.xsd"; //NON-NLS
|
||||
// Document doc = XMLUtil.loadDocument(filePath, UserDefinedFileTypesManager.class, FILE_TYPE_DEFINITIONS_SCHEMA_FILE);
|
||||
Document doc = XMLUtil.loadDocument(filePath);
|
||||
if (doc != null) {
|
||||
Element fileTypesElem = doc.getDocumentElement();
|
||||
if (fileTypesElem != null && fileTypesElem.getNodeName().equals(FILE_TYPES_TAG_NAME)) {
|
||||
@ -497,13 +511,15 @@ final class UserDefinedFileTypesManager {
|
||||
String offsetString = offsetElem.getTextContent();
|
||||
long offset = DatatypeConverter.parseLong(offsetString);
|
||||
|
||||
boolean isRelativeToStart;
|
||||
String relativeString = offsetElem.getAttribute(RELATIVE_ATTRIBUTE);
|
||||
if(relativeString == null || relativeString.equals(""))
|
||||
return new Signature(signatureBytes, offset, signatureType);
|
||||
if (null == relativeString || relativeString.equals("")) {
|
||||
isRelativeToStart = true;
|
||||
} else {
|
||||
isRelativeToStart = DatatypeConverter.parseBoolean(relativeString);
|
||||
}
|
||||
|
||||
boolean isRelative = DatatypeConverter.parseBoolean(relativeString);
|
||||
|
||||
return new Signature(signatureBytes, offset, signatureType, isRelative);
|
||||
return new Signature(signatureBytes, offset, signatureType, isRelativeToStart);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -546,12 +562,20 @@ final class UserDefinedFileTypesManager {
|
||||
private static String getChildElementTextContent(Element elem, String tagName) {
|
||||
NodeList childElems = elem.getElementsByTagName(tagName);
|
||||
Node childNode = childElems.item(0);
|
||||
if(childNode == null)
|
||||
if (childNode == null) {
|
||||
return null;
|
||||
}
|
||||
Element childElem = (Element) childNode;
|
||||
return childElem.getTextContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor suppresses creation of instanmces of this utility
|
||||
* class.
|
||||
*/
|
||||
private XmlReader() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -578,6 +602,8 @@ final class UserDefinedFileTypesManager {
|
||||
*/
|
||||
static class UserDefinedFileTypesException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
UserDefinedFileTypesException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
|
||||
// Initialize job totals
|
||||
initTotalsForIngestJob(jobId);
|
||||
} catch (SecurityException | IOException | UnsupportedOperationException ex) {
|
||||
throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage()));
|
||||
throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage()), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -396,7 +396,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
|
||||
} catch (FileAlreadyExistsException ex) {
|
||||
// No worries.
|
||||
} catch (IOException | SecurityException | UnsupportedOperationException ex) {
|
||||
throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage()));
|
||||
throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage()), ex);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
@ -115,15 +115,15 @@ class EvalAccountObj extends EvaluatableObject {
|
||||
boolean foundSIDMatch = false;
|
||||
|
||||
for (BlackboardAttribute attr : art.getAttributes()) {
|
||||
if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID())
|
||||
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID())
|
||||
&& (haveHomeDir)) {
|
||||
foundHomeDirMatch = compareStringObject(userAccountObj.getHomeDirectory(), attr.getValueString());
|
||||
}
|
||||
if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID())
|
||||
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID())
|
||||
&& (haveUsername)) {
|
||||
foundUsernameMatch = compareStringObject(userAccountObj.getUsername(), attr.getValueString());
|
||||
}
|
||||
if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_ID.getTypeID())
|
||||
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_ID.getTypeID())
|
||||
&& (haveSID) && (winUserObj != null)) {
|
||||
foundSIDMatch = compareStringObject(winUserObj.getSecurityID(), attr.getValueString());
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ class EvalAddressObj extends EvaluatableObject {
|
||||
for (BlackboardArtifact art : artList) {
|
||||
|
||||
for (BlackboardAttribute attr : art.getAttributes()) {
|
||||
if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
|
||||
if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
|
||||
if (compareStringObject(addressStr, obj.getAddressValue().getCondition(),
|
||||
obj.getAddressValue().getApplyCondition(), attr.getValueString())) {
|
||||
finalHits.add(art);
|
||||
|
@ -80,7 +80,7 @@ class EvalDomainObj extends EvaluatableObject {
|
||||
for (BlackboardArtifact art : artList) {
|
||||
|
||||
for (BlackboardAttribute attr : art.getAttributes()) {
|
||||
if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
|
||||
if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
|
||||
String url = attr.getValueString();
|
||||
|
||||
// Check whether the domain name is a substring of the URL (regardless
|
||||
|
@ -98,11 +98,11 @@ class EvalNetworkShareObj extends EvaluatableObject {
|
||||
boolean foundLocalPathMatch = false;
|
||||
|
||||
for (BlackboardAttribute attr : art.getAttributes()) {
|
||||
if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REMOTE_PATH.getTypeID())
|
||||
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REMOTE_PATH.getTypeID())
|
||||
&& (obj.getNetname() != null)) {
|
||||
foundRemotePathMatch = compareStringObject(obj.getNetname(), attr.getValueString());
|
||||
}
|
||||
if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCAL_PATH.getTypeID())
|
||||
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCAL_PATH.getTypeID())
|
||||
&& (obj.getLocalPath() != null)) {
|
||||
foundLocalPathMatch = compareStringObject(obj.getLocalPath(), attr.getValueString());
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ class EvalURIObj extends EvaluatableObject {
|
||||
for (BlackboardArtifact art : artList) {
|
||||
|
||||
for (BlackboardAttribute attr : art.getAttributes()) {
|
||||
if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
|
||||
if (attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID()) {
|
||||
|
||||
String modifiedAttrString = attr.getValueString();
|
||||
if (modifiedAttrString != null) {
|
||||
|
@ -152,7 +152,7 @@ class EvalURLHistoryObj extends EvaluatableObject {
|
||||
boolean foundBrowserNameMatch = false;
|
||||
|
||||
for (BlackboardAttribute attr : art.getAttributes()) {
|
||||
if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID())
|
||||
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID())
|
||||
&& (haveURL)) {
|
||||
if (entry.getURL().getValue() instanceof AnyURIObjectPropertyType) {
|
||||
foundURLMatch = compareStringObject(entry.getURL().getValue().getValue().toString(),
|
||||
@ -163,12 +163,12 @@ class EvalURLHistoryObj extends EvaluatableObject {
|
||||
addWarning("Non-AnyURIObjectPropertyType found in URL value field"); //NON-NLS
|
||||
}
|
||||
}
|
||||
if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID())
|
||||
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID())
|
||||
&& (haveHostname)) {
|
||||
foundHostnameMatch = compareStringObject(entry.getHostname().getHostnameValue(),
|
||||
attr.getValueString());
|
||||
}
|
||||
if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID())
|
||||
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID())
|
||||
&& (haveReferrer)) {
|
||||
if (entry.getReferrerURL().getValue() instanceof AnyURIObjectPropertyType) {
|
||||
foundReferrerMatch = compareStringObject(entry.getReferrerURL().getValue().getValue().toString(),
|
||||
@ -179,17 +179,17 @@ class EvalURLHistoryObj extends EvaluatableObject {
|
||||
addWarning("Non-AnyURIObjectPropertyType found in URL value field"); //NON-NLS
|
||||
}
|
||||
}
|
||||
if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID())
|
||||
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE.getTypeID())
|
||||
&& (havePageTitle)) {
|
||||
foundPageTitleMatch = compareStringObject(entry.getPageTitle(),
|
||||
attr.getValueString());
|
||||
}
|
||||
if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID())
|
||||
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME.getTypeID())
|
||||
&& (haveUserProfile)) {
|
||||
foundUserProfileMatch = compareStringObject(entry.getUserProfileName(),
|
||||
attr.getValueString());
|
||||
}
|
||||
if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())
|
||||
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())
|
||||
&& (haveBrowserName)) {
|
||||
foundBrowserNameMatch = compareStringObject(obj.getBrowserInformation().getName(),
|
||||
null, null, attr.getValueString());
|
||||
@ -240,7 +240,7 @@ class EvalURLHistoryObj extends EvaluatableObject {
|
||||
boolean foundBrowserNameMatch = false;
|
||||
|
||||
for (BlackboardAttribute attr : art.getAttributes()) {
|
||||
if ((attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())
|
||||
if ((attr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID())
|
||||
&& (haveBrowserName)) {
|
||||
foundBrowserNameMatch = compareStringObject(obj.getBrowserInformation().getName(),
|
||||
null, null, attr.getValueString());
|
||||
|
@ -87,7 +87,7 @@
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new javax.swing.JList<>()"/>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<ARTIFACT_TYPE>"/>
|
||||
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<BlackboardArtifact.Type>"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
|
@ -27,6 +27,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
@ -40,15 +41,14 @@ import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
public class ArtifactSelectionDialog extends javax.swing.JDialog {
|
||||
|
||||
private ArtifactModel model;
|
||||
private ArtifactRenderer renderer;
|
||||
private Map<BlackboardArtifact.ARTIFACT_TYPE, Boolean> artifactStates;
|
||||
private List<BlackboardArtifact.ARTIFACT_TYPE> artifacts;
|
||||
private Map<BlackboardArtifact.Type, Boolean> artifactTypeSelections;
|
||||
private List<BlackboardArtifact.Type> artifactTypes;
|
||||
|
||||
/**
|
||||
* Creates new form ArtifactSelectionDialog
|
||||
@ -61,27 +61,31 @@ public class ArtifactSelectionDialog extends javax.swing.JDialog {
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the list of artifacts with all important artifacts.
|
||||
* Populate the list of artifact types with all important artifact types.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void populateList() {
|
||||
try {
|
||||
ArrayList<BlackboardArtifact.ARTIFACT_TYPE> doNotReport = new ArrayList<>();
|
||||
doNotReport.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO);
|
||||
doNotReport.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_TOOL_OUTPUT); // output is too unstructured for table review.
|
||||
ArrayList<BlackboardArtifact.Type> doNotReport = new ArrayList<>();
|
||||
doNotReport.add(new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getTypeID(),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getLabel(),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getDisplayName()));
|
||||
doNotReport.add(new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID(),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getLabel(),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getDisplayName())); // output is too unstructured for table review
|
||||
|
||||
artifacts = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifactTypesInUse();
|
||||
artifacts.removeAll(doNotReport);
|
||||
Collections.sort(artifacts, new Comparator<BlackboardArtifact.ARTIFACT_TYPE>() {
|
||||
artifactTypes = Case.getCurrentCase().getSleuthkitCase().getArtifactTypesInUse();
|
||||
artifactTypes.removeAll(doNotReport);
|
||||
Collections.sort(artifactTypes, new Comparator<BlackboardArtifact.Type>() {
|
||||
@Override
|
||||
public int compare(ARTIFACT_TYPE o1, ARTIFACT_TYPE o2) {
|
||||
public int compare(BlackboardArtifact.Type o1, BlackboardArtifact.Type o2) {
|
||||
return o1.getDisplayName().compareTo(o2.getDisplayName());
|
||||
}
|
||||
});
|
||||
|
||||
artifactStates = new EnumMap<>(BlackboardArtifact.ARTIFACT_TYPE.class);
|
||||
for (BlackboardArtifact.ARTIFACT_TYPE type : artifacts) {
|
||||
artifactStates.put(type, Boolean.TRUE);
|
||||
artifactTypeSelections = new HashMap<>();
|
||||
for (BlackboardArtifact.Type type : artifactTypes) {
|
||||
artifactTypeSelections.put(type, Boolean.TRUE);
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
Logger.getLogger(ArtifactSelectionDialog.class.getName()).log(Level.SEVERE, "Error getting list of artifacts in use: " + ex.getLocalizedMessage()); //NON-NLS
|
||||
@ -99,17 +103,19 @@ public class ArtifactSelectionDialog extends javax.swing.JDialog {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent evt) {
|
||||
int index = artifactList.locationToIndex(evt.getPoint());
|
||||
BlackboardArtifact.ARTIFACT_TYPE type = model.getElementAt(index);
|
||||
artifactStates.put(type, !artifactStates.get(type));
|
||||
BlackboardArtifact.Type type = model.getElementAt(index);
|
||||
artifactTypeSelections.put(type, !artifactTypeSelections.get(type));
|
||||
artifactList.repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Display this dialog, and return the selected artifacts.
|
||||
* Display this dialog, and return the selected artifactTypes.
|
||||
*
|
||||
* @return The state of artifact types displayed
|
||||
*/
|
||||
Map<BlackboardArtifact.ARTIFACT_TYPE, Boolean> display() {
|
||||
Map<BlackboardArtifact.Type, Boolean> display() {
|
||||
this.setTitle(NbBundle.getMessage(this.getClass(), "ArtifactSelectionDialog.dlgTitle.text"));
|
||||
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
// set the popUp window / JFrame
|
||||
@ -120,7 +126,7 @@ public class ArtifactSelectionDialog extends javax.swing.JDialog {
|
||||
setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
|
||||
|
||||
this.setVisible(true);
|
||||
return artifactStates;
|
||||
return artifactTypeSelections;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -215,20 +221,20 @@ public class ArtifactSelectionDialog extends javax.swing.JDialog {
|
||||
}//GEN-LAST:event_okButtonActionPerformed
|
||||
|
||||
private void selectAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectAllButtonActionPerformed
|
||||
for (ARTIFACT_TYPE type : artifacts) {
|
||||
artifactStates.put(type, Boolean.TRUE);
|
||||
for (BlackboardArtifact.Type type : artifactTypes) {
|
||||
artifactTypeSelections.put(type, Boolean.TRUE);
|
||||
}
|
||||
artifactList.repaint();
|
||||
}//GEN-LAST:event_selectAllButtonActionPerformed
|
||||
|
||||
private void deselectAllButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deselectAllButtonActionPerformed
|
||||
for (ARTIFACT_TYPE type : artifacts) {
|
||||
artifactStates.put(type, Boolean.FALSE);
|
||||
for (BlackboardArtifact.Type type : artifactTypes) {
|
||||
artifactTypeSelections.put(type, Boolean.FALSE);
|
||||
}
|
||||
artifactList.repaint();
|
||||
}//GEN-LAST:event_deselectAllButtonActionPerformed
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JList<ARTIFACT_TYPE> artifactList;
|
||||
private javax.swing.JList<BlackboardArtifact.Type> artifactList;
|
||||
private javax.swing.JScrollPane artifactScrollPane;
|
||||
private javax.swing.JButton deselectAllButton;
|
||||
private javax.swing.JButton okButton;
|
||||
@ -236,16 +242,16 @@ public class ArtifactSelectionDialog extends javax.swing.JDialog {
|
||||
private javax.swing.JLabel titleLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
private class ArtifactModel implements ListModel<ARTIFACT_TYPE> {
|
||||
private class ArtifactModel implements ListModel<BlackboardArtifact.Type> {
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return artifacts.size();
|
||||
return artifactTypes.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ARTIFACT_TYPE getElementAt(int index) {
|
||||
return artifacts.get(index);
|
||||
public BlackboardArtifact.Type getElementAt(int index) {
|
||||
return artifactTypes.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -257,13 +263,13 @@ public class ArtifactSelectionDialog extends javax.swing.JDialog {
|
||||
}
|
||||
}
|
||||
|
||||
private class ArtifactRenderer extends JCheckBox implements ListCellRenderer<BlackboardArtifact.ARTIFACT_TYPE> {
|
||||
private class ArtifactRenderer extends JCheckBox implements ListCellRenderer<BlackboardArtifact.Type> {
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList<? extends ARTIFACT_TYPE> list, ARTIFACT_TYPE value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
public Component getListCellRendererComponent(JList<? extends BlackboardArtifact.Type> list, BlackboardArtifact.Type value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
if (value != null) {
|
||||
setEnabled(list.isEnabled());
|
||||
setSelected(artifactStates.get(value));
|
||||
setSelected(artifactTypeSelections.get(value));
|
||||
setFont(list.getFont());
|
||||
setBackground(list.getBackground());
|
||||
setForeground(list.getForeground());
|
||||
|
@ -71,8 +71,6 @@ ReportGenerator.artifactTable.taggedResults.text=Contains results that were tagg
|
||||
ReportGenerator.progress.processing=Now processing {0}...
|
||||
ReportGenerator.msgShow.skippingArtType.title=Skipping artifact type {0} in reports
|
||||
ReportGenerator.msgShow.skippingArtType.msg=Unknown columns to report on
|
||||
ReportGenerator.msgShow.skippingArtRow.title=Skipping artifact rows for type {0} in reports
|
||||
ReportGenerator.msgShow.skippingArtRow.msg=Unknown columns to report on
|
||||
ReportGenerator.makeContTagTab.taggedFiles.msg=Contains files that were tagged with one of the following\:
|
||||
ReportGenerator.makeBbArtTagTab.taggedRes.msg=This report only includes results tagged with\:
|
||||
ReportGenerator.tagTable.header.resultType=Result Type
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -262,7 +262,6 @@ class ReportHTML implements TableReportModule {
|
||||
break;
|
||||
}
|
||||
} else { // no defined artifact found for this dataType
|
||||
logger.log(Level.WARNING, "useDataTypeIcon: no artifact found for data type = " + dataType); //NON-NLS
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/star.png"); //NON-NLS
|
||||
iconFileName = "star.png"; //NON-NLS
|
||||
iconFilePath = path + File.separator + iconFileName;
|
||||
@ -984,8 +983,8 @@ class ReportHTML implements TableReportModule {
|
||||
StringBuilder head = new StringBuilder();
|
||||
head.append("<html>\n<head>\n<title>").append( //NON-NLS
|
||||
NbBundle.getMessage(this.getClass(), "ReportHTML.writeSum.title")).append("</title>\n"); //NON-NLS
|
||||
head.append("<style type=\"text/css\">\n"); //NON-NLS
|
||||
head.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"); //NON-NLS
|
||||
head.append("<style type=\"text/css\">\n"); //NON-NLS
|
||||
head.append("body { padding: 0px; margin: 0px; font: 13px/20px Arial, Helvetica, sans-serif; color: #535353; }\n"); //NON-NLS
|
||||
head.append("#wrapper { width: 90%; margin: 0px auto; margin-top: 35px; }\n"); //NON-NLS
|
||||
head.append("h1 { color: #07A; font-size: 36px; line-height: 42px; font-weight: normal; margin: 0px; border-bottom: 1px solid #81B9DB; }\n"); //NON-NLS
|
||||
|
@ -113,12 +113,12 @@ class ReportKML implements GeneralReportModule {
|
||||
geoPath = "";
|
||||
String extractedToPath;
|
||||
for (BlackboardAttribute attribute : artifact.getAttributes()) {
|
||||
if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()) //latitude
|
||||
if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()) //latitude
|
||||
{
|
||||
|
||||
lat = attribute.getValueDouble();
|
||||
}
|
||||
if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()) //longitude
|
||||
if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()) //longitude
|
||||
{
|
||||
lon = attribute.getValueDouble();
|
||||
}
|
||||
@ -150,11 +150,11 @@ class ReportKML implements GeneralReportModule {
|
||||
lat = 0;
|
||||
lon = 0;
|
||||
for (BlackboardAttribute attribute : artifact.getAttributes()) {
|
||||
if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()) //latitude
|
||||
if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()) //latitude
|
||||
{
|
||||
lat = attribute.getValueDouble();
|
||||
}
|
||||
if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()) //longitude
|
||||
if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()) //longitude
|
||||
{
|
||||
lon = attribute.getValueDouble();
|
||||
}
|
||||
@ -172,22 +172,22 @@ class ReportKML implements GeneralReportModule {
|
||||
String name = "";
|
||||
String location = "";
|
||||
for (BlackboardAttribute attribute : artifact.getAttributes()) {
|
||||
if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID()) //latitude
|
||||
if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID()) //latitude
|
||||
{
|
||||
lat = attribute.getValueDouble();
|
||||
} else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END.getTypeID()) //longitude
|
||||
} else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END.getTypeID()) //longitude
|
||||
{
|
||||
destlat = attribute.getValueDouble();
|
||||
} else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START.getTypeID()) //longitude
|
||||
} else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START.getTypeID()) //longitude
|
||||
{
|
||||
lon = attribute.getValueDouble();
|
||||
} else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END.getTypeID()) //longitude
|
||||
} else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END.getTypeID()) //longitude
|
||||
{
|
||||
destlon = attribute.getValueDouble();
|
||||
} else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID()) //longitude
|
||||
} else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID()) //longitude
|
||||
{
|
||||
name = attribute.getValueString();
|
||||
} else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID()) //longitude
|
||||
} else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID()) //longitude
|
||||
{
|
||||
location = attribute.getValueString();
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -50,8 +51,8 @@ final class ReportVisualPanel2 extends JPanel {
|
||||
private Map<String, Boolean> tagStates = new LinkedHashMap<>();
|
||||
private List<String> tags = new ArrayList<>();
|
||||
ArtifactSelectionDialog dialog = new ArtifactSelectionDialog(new JFrame(), true);
|
||||
private Map<ARTIFACT_TYPE, Boolean> artifactStates = new EnumMap<>(ARTIFACT_TYPE.class);
|
||||
private List<ARTIFACT_TYPE> artifacts = new ArrayList<>();
|
||||
private Map<BlackboardArtifact.Type, Boolean> artifactStates = new HashMap<>();
|
||||
private List<BlackboardArtifact.Type> artifacts = new ArrayList<>();
|
||||
private TagsListModel tagsModel;
|
||||
private TagsListRenderer tagsRenderer;
|
||||
|
||||
@ -111,16 +112,20 @@ final class ReportVisualPanel2 extends JPanel {
|
||||
private void initArtifactTypes() {
|
||||
|
||||
try {
|
||||
ArrayList<BlackboardArtifact.ARTIFACT_TYPE> doNotReport = new ArrayList<>();
|
||||
doNotReport.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO);
|
||||
doNotReport.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_TOOL_OUTPUT); // output is too unstructured for table review
|
||||
ArrayList<BlackboardArtifact.Type> doNotReport = new ArrayList<>();
|
||||
doNotReport.add(new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getTypeID(),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getLabel(),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getDisplayName()));
|
||||
doNotReport.add(new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID(),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getLabel(),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getDisplayName())); // output is too unstructured for table review
|
||||
|
||||
artifacts = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifactTypesInUse();
|
||||
artifacts = Case.getCurrentCase().getSleuthkitCase().getArtifactTypesInUse();
|
||||
|
||||
artifacts.removeAll(doNotReport);
|
||||
|
||||
artifactStates = new EnumMap<>(ARTIFACT_TYPE.class);
|
||||
for (ARTIFACT_TYPE type : artifacts) {
|
||||
artifactStates = new HashMap<>();
|
||||
for (BlackboardArtifact.Type type : artifacts) {
|
||||
artifactStates.put(type, Boolean.TRUE);
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
@ -134,9 +139,11 @@ final class ReportVisualPanel2 extends JPanel {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the enabled/disabled state of all artifacts
|
||||
*
|
||||
* @return the enabled/disabled state of all Artifacts
|
||||
*/
|
||||
Map<ARTIFACT_TYPE, Boolean> getArtifactStates() {
|
||||
Map<BlackboardArtifact.Type, Boolean> getArtifactStates() {
|
||||
return artifactStates;
|
||||
}
|
||||
|
||||
@ -159,7 +166,7 @@ final class ReportVisualPanel2 extends JPanel {
|
||||
|
||||
private boolean areArtifactsSelected() {
|
||||
boolean result = false;
|
||||
for (Entry<ARTIFACT_TYPE, Boolean> entry : artifactStates.entrySet()) {
|
||||
for (Entry<BlackboardArtifact.Type, Boolean> entry : artifactStates.entrySet()) {
|
||||
if (entry.getValue()) {
|
||||
result = true;
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ import org.openide.util.actions.CallableSystemAction;
|
||||
import org.openide.util.actions.Presenter;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.core.RuntimeProperties;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
|
||||
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.report.ReportWizardAction")
|
||||
@ActionRegistration(displayName = "#CTL_ReportWizardAction", lazy = false)
|
||||
@ -68,7 +68,7 @@ public final class ReportWizardAction extends CallableSystemAction implements Pr
|
||||
ReportGenerator generator = new ReportGenerator((Map<TableReportModule, Boolean>) wiz.getProperty("tableModuleStates"), //NON-NLS
|
||||
(Map<GeneralReportModule, Boolean>) wiz.getProperty("generalModuleStates"), //NON-NLS
|
||||
(Map<FileReportModule, Boolean>) wiz.getProperty("fileModuleStates")); //NON-NLS
|
||||
generator.generateTableReports((Map<ARTIFACT_TYPE, Boolean>) wiz.getProperty("artifactStates"), (Map<String, Boolean>) wiz.getProperty("tagStates")); //NON-NLS
|
||||
generator.generateTableReports((Map<BlackboardArtifact.Type, Boolean>) wiz.getProperty("artifactStates"), (Map<String, Boolean>) wiz.getProperty("tagStates")); //NON-NLS
|
||||
generator.generateFileListReports((Map<FileReportDataTypes, Boolean>) wiz.getProperty("fileReportOptions")); //NON-NLS
|
||||
generator.generateGeneralReports();
|
||||
generator.displayProgressPanels();
|
||||
|
@ -440,6 +440,7 @@ public class TimeLineController {
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // TODO (EUR-733): Do not use SleuthkitCase.getLastObjectId
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.ANY)
|
||||
@NbBundle.Messages({"TimeLineController.errorTitle=Timeline error.",
|
||||
"TimeLineController.outOfDate.errorMessage=Error determing if the timeline is out of date. We will assume it should be updated. See the logs for more details.",
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 Basis Technology Corp.
|
||||
* Copyright 2014-16 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,10 +18,9 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.timeline.datamodel.eventtype;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
@ -34,56 +33,56 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
*/
|
||||
public interface ArtifactEventType extends EventType {
|
||||
|
||||
public static final Logger LOGGER = Logger.getLogger(ArtifactEventType.class.getName());
|
||||
static final EmptyExtractor EMPTY_EXTRACTOR = new EmptyExtractor();
|
||||
|
||||
/**
|
||||
* @return the Artifact type this event type is derived form, or null if
|
||||
* there is no artifact type (eg file system events)
|
||||
* @return the Artifact type this event type is derived from
|
||||
*/
|
||||
public BlackboardArtifact.ARTIFACT_TYPE getArtifactType();
|
||||
public BlackboardArtifact.Type getArtifactType();
|
||||
|
||||
public BlackboardAttribute.ATTRIBUTE_TYPE getDateTimeAttrubuteType();
|
||||
public BlackboardAttribute.Type getDateTimeAttrubuteType();
|
||||
|
||||
/**
|
||||
* given an artifact, and a map from attribute types to attributes, pull out
|
||||
* the time stamp, and compose the descriptions. Each implementation of
|
||||
* {@link ArtifactEventType} needs to implement parseAttributesHelper() as
|
||||
* hook for {@link buildEventDescription(org.sleuthkit.datamodel.BlackboardArtifact)
|
||||
* given an artifact, pull out the time stamp, and compose the descriptions.
|
||||
* Each implementation of {@link ArtifactEventType} needs to implement
|
||||
* parseAttributesHelper() as hook for {@link buildEventDescription(org.sleuthkit.datamodel.BlackboardArtifact)
|
||||
* to invoke. Most subtypes can use this default implementation.
|
||||
*
|
||||
* @param artf
|
||||
* @param attrMap
|
||||
*
|
||||
* @return an {@link AttributeEventDescription} containing the timestamp
|
||||
* and description information
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
default AttributeEventDescription parseAttributesHelper(BlackboardArtifact artf, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attrMap) throws TskCoreException {
|
||||
final BlackboardAttribute dateTimeAttr = attrMap.get(getDateTimeAttrubuteType());
|
||||
default AttributeEventDescription parseAttributesHelper(BlackboardArtifact artf) throws TskCoreException {
|
||||
final BlackboardAttribute dateTimeAttr = artf.getAttribute(getDateTimeAttrubuteType());
|
||||
|
||||
long time = dateTimeAttr.getValueLong();
|
||||
String shortDescription = getShortExtractor().apply(artf, attrMap);
|
||||
String medDescription = shortDescription + " : " + getMedExtractor().apply(artf, attrMap);
|
||||
String fullDescription = medDescription + " : " + getFullExtractor().apply(artf, attrMap);
|
||||
String shortDescription = getShortExtractor().apply(artf);
|
||||
String medDescription = shortDescription + " : " + getMedExtractor().apply(artf);
|
||||
String fullDescription = medDescription + " : " + getFullExtractor().apply(artf);
|
||||
return new AttributeEventDescription(time, shortDescription, medDescription, fullDescription);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a function from an artifact and a map of its attributes, to a
|
||||
* String to use as part of the full event description
|
||||
* @return a function from an artifact to a String to use as part of the
|
||||
* full event description
|
||||
*/
|
||||
BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> getFullExtractor();
|
||||
Function<BlackboardArtifact, String> getFullExtractor();
|
||||
|
||||
/**
|
||||
* @return a function from an artifact and a map of its attributes, to a
|
||||
* String to use as part of the medium event description
|
||||
* @return a function from an artifact to a String to use as part of the
|
||||
* medium event description
|
||||
*/
|
||||
BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> getMedExtractor();
|
||||
Function<BlackboardArtifact, String> getMedExtractor();
|
||||
|
||||
/**
|
||||
* @return a function from an artifact and a map of its attributes, to a
|
||||
* String to use as part of the short event description
|
||||
* @return a function from an artifact to a String to use as part of the
|
||||
* short event description
|
||||
*/
|
||||
BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> getShortExtractor();
|
||||
Function<BlackboardArtifact, String> getShortExtractor();
|
||||
|
||||
/**
|
||||
* bundles the per event information derived from a BlackBoard Artifact into
|
||||
@ -124,14 +123,13 @@ public interface ArtifactEventType extends EventType {
|
||||
this.medDescription = medDescription;
|
||||
this.fullDescription = fullDescription;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link AttributeEventDescription} derived from a
|
||||
* {@link BlackboardArtifact}. This is a template method that relies on each
|
||||
* {@link SubType}'s implementation of
|
||||
* {@link SubType#parseAttributesHelper()} to know how to go from
|
||||
* {@link ArtifactEventType}'s implementation of
|
||||
* {@link ArtifactEventType#parseAttributesHelper()} to know how to go from
|
||||
* {@link BlackboardAttribute}s to the event description.
|
||||
*
|
||||
* @param artf the {@link BlackboardArtifact} to derive the event
|
||||
@ -149,48 +147,45 @@ public interface ArtifactEventType extends EventType {
|
||||
if (type.getArtifactType().getTypeID() != artf.getArtifactTypeID()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
/*
|
||||
* build a map from attribute type to attribute, this makes implementing
|
||||
* the parseAttributeHelper easier but could be ineffecient if we don't
|
||||
* need most of the attributes. This would be unnessecary if there was
|
||||
* an api on Blackboard artifacts to get specific attributes by type
|
||||
*/
|
||||
List<BlackboardAttribute> attributes = artf.getAttributes();
|
||||
Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attrMap = new HashMap<>();
|
||||
for (BlackboardAttribute attr : attributes) {
|
||||
attrMap.put(BlackboardAttribute.ATTRIBUTE_TYPE.fromLabel(attr.
|
||||
getAttributeTypeName()), attr);
|
||||
}
|
||||
|
||||
if (attrMap.get(type.getDateTimeAttrubuteType()) == null) {
|
||||
Logger.getLogger(AttributeEventDescription.class.getName()).log(Level.WARNING, "Artifact {0} has no date/time attribute, skipping it.", artf.getArtifactID()); // NON-NLS
|
||||
if (artf.getAttribute(type.getDateTimeAttrubuteType()) == null) {
|
||||
LOGGER.log(Level.WARNING, "Artifact {0} has no date/time attribute, skipping it.", artf.getArtifactID()); // NON-NLS
|
||||
return null;
|
||||
}
|
||||
//use the hook provided by this subtype implementation
|
||||
return type.parseAttributesHelper(artf, attrMap);
|
||||
return type.parseAttributesHelper(artf);
|
||||
}
|
||||
|
||||
public static class AttributeExtractor implements BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> {
|
||||
static class AttributeExtractor implements Function<BlackboardArtifact, String> {
|
||||
|
||||
public String apply(BlackboardArtifact artf) {
|
||||
return Optional.ofNullable(getAttributeSafe(artf, attributeType))
|
||||
.map(BlackboardAttribute::getDisplayString)
|
||||
.map(StringUtils::defaultString)
|
||||
.orElse("");
|
||||
}
|
||||
|
||||
private final BlackboardAttribute.Type attributeType;
|
||||
|
||||
public AttributeExtractor(BlackboardAttribute.Type attribute) {
|
||||
this.attributeType = attribute;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class EmptyExtractor implements Function<BlackboardArtifact, String> {
|
||||
|
||||
@Override
|
||||
public String apply(BlackboardArtifact artf, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attrMap) {
|
||||
final BlackboardAttribute attr = attrMap.get(attribute);
|
||||
return (attr != null) ? StringUtils.defaultString(attr.getDisplayString()) : " ";
|
||||
}
|
||||
|
||||
private final BlackboardAttribute.ATTRIBUTE_TYPE attribute;
|
||||
|
||||
public AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE attribute) {
|
||||
this.attribute = attribute;
|
||||
}
|
||||
}
|
||||
|
||||
public static class EmptyExtractor implements BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> {
|
||||
|
||||
@Override
|
||||
public String apply(BlackboardArtifact t, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> u) {
|
||||
public String apply(BlackboardArtifact t) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static BlackboardAttribute getAttributeSafe(BlackboardArtifact artf, BlackboardAttribute.Type attrType) {
|
||||
try {
|
||||
return artf.getAttribute(attrType);
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting extracting attribute from artifact {0}.", artf.getArtifactID()), ex); // NON-NLS
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 Basis Technology Corp.
|
||||
* Copyright 2014-16 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -21,17 +21,19 @@ package org.sleuthkit.autopsy.timeline.datamodel.eventtype;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import javafx.scene.image.Image;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import static org.sleuthkit.autopsy.timeline.datamodel.eventtype.ArtifactEventType.getAttributeSafe;
|
||||
import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
@ -40,116 +42,113 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
public enum MiscTypes implements EventType, ArtifactEventType {
|
||||
|
||||
MESSAGE(NbBundle.getMessage(MiscTypes.class, "MiscTypes.message.name"), "message.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME,
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE),
|
||||
(artf, attrMap) -> {
|
||||
final BlackboardAttribute dir = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION);
|
||||
final BlackboardAttribute readStatus = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_READ_STATUS);
|
||||
final BlackboardAttribute name = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
|
||||
final BlackboardAttribute phoneNumber = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER);
|
||||
final BlackboardAttribute subject = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT);
|
||||
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_MESSAGE),
|
||||
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE)),
|
||||
artf -> {
|
||||
final BlackboardAttribute dir = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DIRECTION));
|
||||
final BlackboardAttribute readStatus = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_READ_STATUS));
|
||||
final BlackboardAttribute name = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME));
|
||||
final BlackboardAttribute phoneNumber = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER));
|
||||
final BlackboardAttribute subject = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SUBJECT));
|
||||
List<String> asList = Arrays.asList(stringValueOf(dir), stringValueOf(readStatus), name != null || phoneNumber != null ? toFrom(dir) : "", stringValueOf(name != null ? name : phoneNumber), (subject == null ? "" : stringValueOf(subject)));
|
||||
return StringUtils.join(asList, " ");
|
||||
},
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_TEXT))),
|
||||
GPS_ROUTE(NbBundle.getMessage(MiscTypes.class, "MiscTypes.GPSRoutes.name"), "gps-search.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME,
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION),
|
||||
(artf, attrMap) -> {
|
||||
final BlackboardAttribute latStart = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START);
|
||||
final BlackboardAttribute longStart = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START);
|
||||
final BlackboardAttribute latEnd = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END);
|
||||
final BlackboardAttribute longEnd = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END);
|
||||
return String.format("from %1$g %2$g to %3$g %4$g", latStart.getValueDouble(), longStart.getValueDouble(), latEnd.getValueDouble(), longEnd.getValueDouble()); // NON-NLS
|
||||
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_GPS_ROUTE),
|
||||
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_LOCATION)),
|
||||
artf -> {
|
||||
final BlackboardAttribute latStart = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START));
|
||||
final BlackboardAttribute longStart = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START));
|
||||
final BlackboardAttribute latEnd = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END));
|
||||
final BlackboardAttribute longEnd = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END));
|
||||
return String.format("from %1$s %2$s to %3$s %4$s", stringValueOf(latStart), stringValueOf(longStart), stringValueOf(latEnd), stringValueOf(longEnd)); // NON-NLS
|
||||
}),
|
||||
GPS_TRACKPOINT(NbBundle.getMessage(MiscTypes.class, "MiscTypes.GPSTrackpoint.name"), "gps-trackpoint.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME,
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME),
|
||||
(artf, attrMap) -> {
|
||||
final BlackboardAttribute longitude = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE);
|
||||
final BlackboardAttribute latitude = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE);
|
||||
return (latitude != null ? latitude.getValueDouble() : "") + " " + (longitude != null ? longitude.getValueDouble() : ""); // NON-NLS
|
||||
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_GPS_TRACKPOINT),
|
||||
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)),
|
||||
artf -> {
|
||||
final BlackboardAttribute longitude = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE));
|
||||
final BlackboardAttribute latitude = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE));
|
||||
return stringValueOf(latitude) + " " + stringValueOf(longitude); // NON-NLS
|
||||
},
|
||||
(artf, attrMap) -> ""),
|
||||
EMPTY_EXTRACTOR),
|
||||
CALL_LOG(NbBundle.getMessage(MiscTypes.class, "MiscTypes.Calls.name"), "calllog.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START,
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION)),
|
||||
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_CALLLOG),
|
||||
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_START),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_NAME)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DIRECTION))),
|
||||
EMAIL(NbBundle.getMessage(MiscTypes.class, "MiscTypes.Email.name"), "mail-icon-16.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT,
|
||||
(artifact, attrMap) -> {
|
||||
final BlackboardAttribute emailFrom = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_FROM);
|
||||
final BlackboardAttribute emailTo = attrMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_TO);
|
||||
return (emailFrom != null ? emailFrom.getValueString() : "") + " to " + (emailTo != null ? emailTo.getValueString() : ""); // NON-NLS
|
||||
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_EMAIL_MSG),
|
||||
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_SENT),
|
||||
artf -> {
|
||||
final BlackboardAttribute emailFrom = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_FROM));
|
||||
final BlackboardAttribute emailTo = getAttributeSafe(artf, new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_TO));
|
||||
return stringValueOf(emailFrom) + " to " + stringValueOf(emailTo); // NON-NLS
|
||||
},
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SUBJECT)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN))),
|
||||
RECENT_DOCUMENTS(NbBundle.getMessage(MiscTypes.class, "MiscTypes.recentDocuments.name"), "recent_docs.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME,
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH).andThen(
|
||||
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_RECENT_OBJECT),
|
||||
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)).andThen(
|
||||
(String t) -> (StringUtils.substringBeforeLast(StringUtils.substringBeforeLast(t, "\\"), "\\"))),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH).andThen(
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)).andThen(
|
||||
(String t) -> StringUtils.substringBeforeLast(t, "\\")),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH)) {
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH))) {
|
||||
|
||||
/**
|
||||
* Override
|
||||
* {@link ArtifactEventType#parseAttributesHelper(org.sleuthkit.datamodel.BlackboardArtifact, java.util.Map)}
|
||||
* with non-default description construction
|
||||
*/
|
||||
@Override
|
||||
public AttributeEventDescription parseAttributesHelper(BlackboardArtifact artf, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attrMap) throws TskCoreException {
|
||||
final BlackboardAttribute dateTimeAttr = attrMap.get(getDateTimeAttrubuteType());
|
||||
public AttributeEventDescription parseAttributesHelper(BlackboardArtifact artf) throws TskCoreException {
|
||||
final BlackboardAttribute dateTimeAttr = artf.getAttribute(getDateTimeAttrubuteType());
|
||||
|
||||
long time = dateTimeAttr.getValueLong();
|
||||
|
||||
//Non-default description construction
|
||||
String shortDescription = getShortExtractor().apply(artf, attrMap);
|
||||
String medDescription = getMedExtractor().apply(artf, attrMap);
|
||||
String fullDescription = getFullExtractor().apply(artf, attrMap);
|
||||
String shortDescription = getShortExtractor().apply(artf);
|
||||
String medDescription = getMedExtractor().apply(artf);
|
||||
String fullDescription = getFullExtractor().apply(artf);
|
||||
|
||||
return new AttributeEventDescription(time, shortDescription, medDescription, fullDescription);
|
||||
}
|
||||
},
|
||||
INSTALLED_PROGRAM(NbBundle.getMessage(MiscTypes.class, "MiscTypes.installedPrograms.name"), "programs.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_INSTALLED_PROG,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME,
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME),
|
||||
new EmptyExtractor(),
|
||||
new EmptyExtractor()),
|
||||
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_INSTALLED_PROG),
|
||||
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PROG_NAME)),
|
||||
EMPTY_EXTRACTOR,
|
||||
EMPTY_EXTRACTOR),
|
||||
EXIF(NbBundle.getMessage(MiscTypes.class, "MiscTypes.exif.name"), "camera-icon-16.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MAKE),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MODEL),
|
||||
(artifact, attributeMap) -> {
|
||||
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_METADATA_EXIF),
|
||||
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL)),
|
||||
artf -> {
|
||||
try {
|
||||
AbstractFile file = artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID());
|
||||
AbstractFile file = artf.getSleuthkitCase().getAbstractFileById(artf.getObjectID());
|
||||
if (file != null) {
|
||||
return file.getName();
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
Logger.getLogger(MiscTypes.class.getName()).log(Level.SEVERE, "Exif event type failed to look up backing file name", ex); //NON-NLS
|
||||
LOGGER.log(Level.SEVERE, "Exif event type failed to look up backing file name", ex); //NON-NLS
|
||||
}
|
||||
return " error loading file name"; // NON-NLS
|
||||
return "error loading file name";
|
||||
}),
|
||||
DEVICES_ATTACHED(NbBundle.getMessage(MiscTypes.class, "MiscTypes.devicesAttached.name"), "usb_devices.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME,
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MAKE),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MODEL),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID));
|
||||
TypeUtils.fromEnum(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED),
|
||||
new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DATETIME),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_DEVICE_ID)));
|
||||
|
||||
static public String stringValueOf(BlackboardAttribute attr) {
|
||||
return attr != null ? attr.getDisplayString() : "";
|
||||
return Optional.ofNullable(attr)
|
||||
.map(BlackboardAttribute::getDisplayString)
|
||||
.orElse("");
|
||||
}
|
||||
|
||||
public static String toFrom(BlackboardAttribute dir) {
|
||||
@ -167,7 +166,7 @@ public enum MiscTypes implements EventType, ArtifactEventType {
|
||||
}
|
||||
}
|
||||
|
||||
private final BlackboardAttribute.ATTRIBUTE_TYPE dateTimeAttributeType;
|
||||
private final BlackboardAttribute.Type dateTimeAttributeType;
|
||||
|
||||
private final String iconBase;
|
||||
|
||||
@ -178,47 +177,32 @@ public enum MiscTypes implements EventType, ArtifactEventType {
|
||||
return image;
|
||||
}
|
||||
|
||||
private final BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> longExtractor;
|
||||
private final Function<BlackboardArtifact, String> longExtractor;
|
||||
|
||||
private final BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> medExtractor;
|
||||
private final Function<BlackboardArtifact, String> medExtractor;
|
||||
|
||||
private final BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> shortExtractor;
|
||||
private final Function<BlackboardArtifact, String> shortExtractor;
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Override
|
||||
public BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> getFullExtractor() {
|
||||
public Function<BlackboardArtifact, String> getFullExtractor() {
|
||||
return longExtractor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Override
|
||||
public BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> getMedExtractor() {
|
||||
public Function<BlackboardArtifact, String> getMedExtractor() {
|
||||
return medExtractor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Override
|
||||
public BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> getShortExtractor() {
|
||||
public Function<BlackboardArtifact, String> getShortExtractor() {
|
||||
return shortExtractor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Override
|
||||
public BlackboardAttribute.ATTRIBUTE_TYPE getDateTimeAttrubuteType() {
|
||||
public BlackboardAttribute.Type getDateTimeAttrubuteType() {
|
||||
return dateTimeAttributeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*/
|
||||
@Override
|
||||
public EventTypeZoomLevel getZoomLevel() {
|
||||
return EventTypeZoomLevel.SUB_TYPE;
|
||||
@ -226,7 +210,7 @@ public enum MiscTypes implements EventType, ArtifactEventType {
|
||||
|
||||
private final String displayName;
|
||||
|
||||
private final BlackboardArtifact.ARTIFACT_TYPE artifactType;
|
||||
private final BlackboardArtifact.Type artifactType;
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
@ -243,11 +227,11 @@ public enum MiscTypes implements EventType, ArtifactEventType {
|
||||
return MiscTypes.valueOf(string);
|
||||
}
|
||||
|
||||
private MiscTypes(String displayName, String iconBase, BlackboardArtifact.ARTIFACT_TYPE artifactType,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE dateTimeAttributeType,
|
||||
BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> shortExtractor,
|
||||
BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> medExtractor,
|
||||
BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> longExtractor) {
|
||||
private MiscTypes(String displayName, String iconBase, BlackboardArtifact.Type artifactType,
|
||||
BlackboardAttribute.Type dateTimeAttributeType,
|
||||
Function<BlackboardArtifact, String> shortExtractor,
|
||||
Function<BlackboardArtifact, String> medExtractor,
|
||||
Function<BlackboardArtifact, String> longExtractor) {
|
||||
this.displayName = displayName;
|
||||
this.iconBase = iconBase;
|
||||
this.artifactType = artifactType;
|
||||
@ -269,7 +253,7 @@ public enum MiscTypes implements EventType, ArtifactEventType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlackboardArtifact.ARTIFACT_TYPE getArtifactType() {
|
||||
public BlackboardArtifact.Type getArtifactType() {
|
||||
return artifactType;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.timeline.datamodel.eventtype;
|
||||
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class TypeUtils {
|
||||
|
||||
//TODO: this will be unncessary once their is BlackboardArtifact.Type constructr that takes a BlackboardArtifact.ARTIFACT_TYPE
|
||||
static BlackboardArtifact.Type fromEnum(BlackboardArtifact.ARTIFACT_TYPE type) {
|
||||
return new BlackboardArtifact.Type(type.getTypeID(), type.getLabel(), type.getDisplayName());
|
||||
}
|
||||
|
||||
private TypeUtils() {
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 Basis Technology Corp.
|
||||
* Copyright 2014-16 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -21,14 +21,14 @@ package org.sleuthkit.autopsy.timeline.datamodel.eventtype;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import javafx.scene.image.Image;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.timeline.zooming.EventTypeZoomLevel;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -37,24 +37,19 @@ public enum WebTypes implements EventType, ArtifactEventType {
|
||||
|
||||
WEB_DOWNLOADS(NbBundle.getMessage(WebTypes.class, "WebTypes.webDownloads.name"),
|
||||
"downloads.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
|
||||
TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD),
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED),
|
||||
TopPrivateDomainExtractor.getInstance(),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL)) {
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL))) {
|
||||
|
||||
/**
|
||||
* Override
|
||||
* {@link ArtifactEventType#parseAttributesHelper(org.sleuthkit.datamodel.BlackboardArtifact, java.util.Map)}
|
||||
* with non default description construction
|
||||
*/
|
||||
@Override
|
||||
public AttributeEventDescription parseAttributesHelper(BlackboardArtifact artf, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attrMap) {
|
||||
long time = attrMap.get(getDateTimeAttrubuteType()).getValueLong();
|
||||
String domain = getShortExtractor().apply(artf, attrMap);
|
||||
String path = getMedExtractor().apply(artf, attrMap);
|
||||
public AttributeEventDescription parseAttributesHelper(BlackboardArtifact artf) throws TskCoreException {
|
||||
long time = artf.getAttribute(getDateTimeAttrubuteType()).getValueLong();
|
||||
String domain = getShortExtractor().apply(artf);
|
||||
String path = getMedExtractor().apply(artf);
|
||||
String fileName = StringUtils.substringAfterLast(path, "/");
|
||||
String url = getFullExtractor().apply(artf, attrMap);
|
||||
String url = getFullExtractor().apply(artf);
|
||||
|
||||
//TODO: review non default description construction
|
||||
String shortDescription = fileName + " from " + domain; // NON-NLS
|
||||
@ -66,37 +61,37 @@ public enum WebTypes implements EventType, ArtifactEventType {
|
||||
//TODO: review description separators
|
||||
WEB_COOKIE(NbBundle.getMessage(WebTypes.class, "WebTypes.webCookies.name"),
|
||||
"cookies.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME,
|
||||
TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE),
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME),
|
||||
TopPrivateDomainExtractor.getInstance(),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE))),
|
||||
//TODO: review description separators
|
||||
WEB_BOOKMARK(NbBundle.getMessage(WebTypes.class, "WebTypes.webBookmarks.name"),
|
||||
"bookmarks.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
|
||||
TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK),
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED),
|
||||
TopPrivateDomainExtractor.getInstance(),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE))),
|
||||
//TODO: review description separators
|
||||
WEB_HISTORY(NbBundle.getMessage(WebTypes.class, "WebTypes.webHistory.name"),
|
||||
"history.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
|
||||
TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY),
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED),
|
||||
TopPrivateDomainExtractor.getInstance(),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL)),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE))),
|
||||
//TODO: review description separators
|
||||
WEB_SEARCH(NbBundle.getMessage(WebTypes.class, "WebTypes.webSearch.name"),
|
||||
"searchquery.png", // NON-NLS
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT),
|
||||
TypeUtils.fromEnum(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY),
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED),
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT)),
|
||||
TopPrivateDomainExtractor.getInstance(),
|
||||
new AttributeExtractor(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME));
|
||||
new AttributeExtractor(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME)));
|
||||
|
||||
private final BlackboardAttribute.ATTRIBUTE_TYPE dateTimeAttributeType;
|
||||
private final BlackboardAttribute.Type dateTimeAttributeType;
|
||||
|
||||
private final String iconBase;
|
||||
|
||||
@ -108,7 +103,7 @@ public enum WebTypes implements EventType, ArtifactEventType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlackboardAttribute.ATTRIBUTE_TYPE getDateTimeAttrubuteType() {
|
||||
public BlackboardAttribute.Type getDateTimeAttrubuteType() {
|
||||
return dateTimeAttributeType;
|
||||
}
|
||||
|
||||
@ -117,30 +112,30 @@ public enum WebTypes implements EventType, ArtifactEventType {
|
||||
return EventTypeZoomLevel.SUB_TYPE;
|
||||
}
|
||||
|
||||
private final BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> longExtractor;
|
||||
private final Function<BlackboardArtifact, String> longExtractor;
|
||||
|
||||
private final BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> medExtractor;
|
||||
private final Function<BlackboardArtifact, String> medExtractor;
|
||||
|
||||
private final BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> shortExtractor;
|
||||
private final Function<BlackboardArtifact, String> shortExtractor;
|
||||
|
||||
@Override
|
||||
public BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> getFullExtractor() {
|
||||
public Function<BlackboardArtifact, String> getFullExtractor() {
|
||||
return longExtractor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> getMedExtractor() {
|
||||
public Function<BlackboardArtifact, String> getMedExtractor() {
|
||||
return medExtractor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> getShortExtractor() {
|
||||
public Function<BlackboardArtifact, String> getShortExtractor() {
|
||||
return shortExtractor;
|
||||
}
|
||||
|
||||
private final String displayName;
|
||||
|
||||
BlackboardArtifact.ARTIFACT_TYPE artifactType;
|
||||
private final BlackboardArtifact.Type artifactType;
|
||||
|
||||
@Override
|
||||
public String getIconBase() {
|
||||
@ -148,15 +143,15 @@ public enum WebTypes implements EventType, ArtifactEventType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlackboardArtifact.ARTIFACT_TYPE getArtifactType() {
|
||||
public BlackboardArtifact.Type getArtifactType() {
|
||||
return artifactType;
|
||||
}
|
||||
|
||||
private WebTypes(String displayName, String iconBase, BlackboardArtifact.ARTIFACT_TYPE artifactType,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE dateTimeAttributeType,
|
||||
BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> shortExtractor,
|
||||
BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> medExtractor,
|
||||
BiFunction<BlackboardArtifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute>, String> longExtractor) {
|
||||
private WebTypes(String displayName, String iconBase, BlackboardArtifact.Type artifactType,
|
||||
BlackboardAttribute.Type dateTimeAttributeType,
|
||||
Function<BlackboardArtifact, String> shortExtractor,
|
||||
Function<BlackboardArtifact, String> medExtractor,
|
||||
Function<BlackboardArtifact, String> longExtractor) {
|
||||
this.displayName = displayName;
|
||||
this.iconBase = iconBase;
|
||||
this.artifactType = artifactType;
|
||||
@ -196,8 +191,8 @@ public enum WebTypes implements EventType, ArtifactEventType {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apply(BlackboardArtifact artf, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attrMap) {
|
||||
String domainString = StringUtils.substringBefore(super.apply(artf, attrMap), "/");
|
||||
public String apply(BlackboardArtifact artf) {
|
||||
String domainString = StringUtils.substringBefore(super.apply(artf), "/");
|
||||
if (InternetDomainName.isValid(domainString)) {
|
||||
InternetDomainName domain = InternetDomainName.from(domainString);
|
||||
return (domain.isUnderPublicSuffix())
|
||||
@ -209,8 +204,7 @@ public enum WebTypes implements EventType, ArtifactEventType {
|
||||
}
|
||||
|
||||
TopPrivateDomainExtractor() {
|
||||
super(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN);
|
||||
super(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -461,6 +461,7 @@ public class EventsRepository {
|
||||
updateProgress(workDone, total);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // TODO (EUR-733): Do not use SleuthkitCase.getLastObjectId
|
||||
@Override
|
||||
@NbBundle.Messages({"progressWindow.msg.refreshingFileTags=Refreshing file tags",
|
||||
"progressWindow.msg.refreshingResultTags=Refreshing result tags",
|
||||
@ -654,7 +655,7 @@ public class EventsRepository {
|
||||
private void populateEventType(final ArtifactEventType type, EventDB.EventTransaction trans) {
|
||||
try {
|
||||
//get all the blackboard artifacts corresponding to the given event sub_type
|
||||
final ArrayList<BlackboardArtifact> blackboardArtifacts = skCase.getBlackboardArtifacts(type.getArtifactType());
|
||||
final ArrayList<BlackboardArtifact> blackboardArtifacts = skCase.getBlackboardArtifacts(type.getArtifactType().getTypeID());
|
||||
final int numArtifacts = blackboardArtifacts.size();
|
||||
restartProgressHandle(Bundle.progressWindow_populatingXevents(type.getDisplayName()), "", 0D, numArtifacts, true);
|
||||
for (int i = 0; i < numArtifacts; i++) {
|
||||
|
@ -6,8 +6,8 @@ OpenIDE-Module-Name=ImageGallery
|
||||
OpenIDE-Module-Short-Description=Advanced image and video gallery
|
||||
ImageGalleryOptionsPanel.enabledForCaseBox.text=Enable Image Gallery updates for the current case.
|
||||
ImageGalleryOptionsPanel.enabledByDefaultBox.text=Enable Image Gallery for new cases by default.
|
||||
ImageGalleryOptionsPanel.enabledForCaseBox.toolTipText=If Image Gallery is disabled, only the fact that an update is needed is recorded. If Image Gallery is enabled after ingest, it will do one bulk update based on the results form ingest. If Image Gallery is disabled, you will be prompted to enable it when attempting to open its window.
|
||||
ImageGalleryOptionsPanel.enabledForCaseBox.toolTipText=If Image Gallery is disabled, only the fact that an update is needed is recorded. If Image Gallery is enabled after ingest, it will do one bulk update based on the results from ingest. If Image Gallery is disabled, you will be prompted to enable it when attempting to open its window.
|
||||
ImageGalleryOptionsPanel.descriptionLabel.text=<html>To minimize its startup times, Image Gallery will constantly update its internal database. <br />This can cause ingest to be slower if you do not need the Image Gallery features. <br />Use these settings to disable Image Gallery if you do not need it.</html>
|
||||
ImageGalleryOptionsPanel.furtherDescriptionArea.text=If Image Gallery is disabled, only the fact that an update is needed is recorded. If Image Gallery is enabled after ingest, it will do one bulk update based on the results form ingest. If Image Gallery is disabled, you will be prompted to enable it when attempting to open its window.
|
||||
ImageGalleryOptionsPanel.furtherDescriptionArea.text=If Image Gallery is disabled, only the fact that an update is needed is recorded. If Image Gallery is enabled after ingest, it will do one bulk update based on the results from ingest. If Image Gallery is disabled, you will be prompted to enable it when attempting to open its window.
|
||||
ImageGalleryOptionsPanel.unavailableDuringInjestLabel.text=This setting is unavailable during ingest.
|
||||
ImageGalleryOptionsPanel.infoIconLabel.text=
|
||||
ImageGalleryOptionsPanel.groupCategorizationWarningBox.text=Don't show a warning when overwriting categories, by acting on an entire group.
|
||||
|
@ -35,6 +35,7 @@ import javafx.beans.Observable;
|
||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyBooleanWrapper;
|
||||
import javafx.beans.property.ReadOnlyDoubleProperty;
|
||||
import javafx.beans.property.ReadOnlyDoubleWrapper;
|
||||
import javafx.beans.property.ReadOnlyIntegerProperty;
|
||||
import javafx.beans.property.ReadOnlyIntegerWrapper;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
@ -95,6 +96,7 @@ public final class ImageGalleryController implements Executor {
|
||||
|
||||
private final Executor execDelegate = Executors.newSingleThreadExecutor();
|
||||
private Runnable showTree;
|
||||
private Toolbar toolbar;
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
@ -128,14 +130,13 @@ public final class ImageGalleryController implements Executor {
|
||||
*/
|
||||
private final SimpleBooleanProperty listeningEnabled = new SimpleBooleanProperty(false);
|
||||
|
||||
private final ReadOnlyIntegerWrapper queueSizeProperty = new ReadOnlyIntegerWrapper(0);
|
||||
|
||||
private final ReadOnlyBooleanWrapper regroupDisabled = new ReadOnlyBooleanWrapper(false);
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
private final ReadOnlyBooleanWrapper stale = new ReadOnlyBooleanWrapper(false);
|
||||
|
||||
private final ReadOnlyBooleanWrapper metaDataCollapsed = new ReadOnlyBooleanWrapper(false);
|
||||
private final ReadOnlyDoubleWrapper thumbnailSize = new ReadOnlyDoubleWrapper(100);
|
||||
|
||||
private final FileIDSelectionModel selectionModel = new FileIDSelectionModel(this);
|
||||
|
||||
@ -154,7 +155,6 @@ public final class ImageGalleryController implements Executor {
|
||||
|
||||
private Node infoOverlay;
|
||||
private SleuthkitCase sleuthKitCase;
|
||||
// private NavPanel navPanel;
|
||||
|
||||
public ReadOnlyBooleanProperty getMetaDataCollapsed() {
|
||||
return metaDataCollapsed.getReadOnlyProperty();
|
||||
@ -164,6 +164,10 @@ public final class ImageGalleryController implements Executor {
|
||||
this.metaDataCollapsed.set(metaDataCollapsed);
|
||||
}
|
||||
|
||||
public ReadOnlyDoubleProperty thumbnailSizeProperty() {
|
||||
return thumbnailSize.getReadOnlyProperty();
|
||||
}
|
||||
|
||||
private GroupViewState getViewState() {
|
||||
return historyManager.getCurrentState();
|
||||
}
|
||||
@ -176,7 +180,7 @@ public final class ImageGalleryController implements Executor {
|
||||
return historyManager.currentState();
|
||||
}
|
||||
|
||||
public synchronized FileIDSelectionModel getSelectionModel() {
|
||||
public FileIDSelectionModel getSelectionModel() {
|
||||
return selectionModel;
|
||||
}
|
||||
|
||||
@ -188,13 +192,17 @@ public final class ImageGalleryController implements Executor {
|
||||
return db;
|
||||
}
|
||||
|
||||
synchronized public void setListeningEnabled(boolean enabled) {
|
||||
public void setListeningEnabled(boolean enabled) {
|
||||
synchronized (listeningEnabled) {
|
||||
listeningEnabled.set(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized boolean isListeningEnabled() {
|
||||
boolean isListeningEnabled() {
|
||||
synchronized (listeningEnabled) {
|
||||
return listeningEnabled.get();
|
||||
}
|
||||
}
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.ANY)
|
||||
void setStale(Boolean b) {
|
||||
@ -249,12 +257,14 @@ public final class ImageGalleryController implements Executor {
|
||||
checkForGroups();
|
||||
});
|
||||
|
||||
IngestManager.getInstance().addIngestModuleEventListener((PropertyChangeEvent evt) -> {
|
||||
Platform.runLater(this::updateRegroupDisabled);
|
||||
});
|
||||
IngestManager.getInstance().addIngestJobEventListener((PropertyChangeEvent evt) -> {
|
||||
Platform.runLater(this::updateRegroupDisabled);
|
||||
});
|
||||
IngestManager ingestManager = IngestManager.getInstance();
|
||||
PropertyChangeListener ingestEventHandler =
|
||||
propertyChangeEvent -> Platform.runLater(this::updateRegroupDisabled);
|
||||
|
||||
ingestManager.addIngestModuleEventListener(ingestEventHandler);
|
||||
ingestManager.addIngestJobEventListener(ingestEventHandler);
|
||||
|
||||
queueSizeProperty.addListener(obs -> this.updateRegroupDisabled());
|
||||
}
|
||||
|
||||
public ReadOnlyBooleanProperty getCanAdvance() {
|
||||
@ -281,8 +291,9 @@ public final class ImageGalleryController implements Executor {
|
||||
return historyManager.retreat();
|
||||
}
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
private void updateRegroupDisabled() {
|
||||
regroupDisabled.set(getFileUpdateQueueSizeProperty().get() > 0 || IngestManager.getInstance().isIngestRunning());
|
||||
regroupDisabled.set((queueSizeProperty.get() > 0) || IngestManager.getInstance().isIngestRunning());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -313,7 +324,7 @@ public final class ImageGalleryController implements Executor {
|
||||
new ProgressIndicator()));
|
||||
}
|
||||
|
||||
} else if (getFileUpdateQueueSizeProperty().get() > 0) {
|
||||
} else if (queueSizeProperty.get() > 0) {
|
||||
replaceNotification(fullUIStackPane,
|
||||
new NoGroupsDialog(Bundle.ImageGalleryController_noGroupsDlg_msg3(),
|
||||
new ProgressIndicator()));
|
||||
@ -358,20 +369,14 @@ public final class ImageGalleryController implements Executor {
|
||||
}
|
||||
}
|
||||
|
||||
private void restartWorker() {
|
||||
if (dbWorkerThread != null) {
|
||||
synchronized private DBWorkerThread restartWorker() {
|
||||
if (dbWorkerThread == null) {
|
||||
dbWorkerThread = new DBWorkerThread(this);
|
||||
dbWorkerThread.start();
|
||||
} else {
|
||||
// Keep using the same worker thread if one exists
|
||||
return;
|
||||
}
|
||||
dbWorkerThread = new DBWorkerThread();
|
||||
|
||||
getFileUpdateQueueSizeProperty().addListener((Observable o) -> {
|
||||
Platform.runLater(this::updateRegroupDisabled);
|
||||
});
|
||||
|
||||
Thread th = new Thread(dbWorkerThread, "DB-Worker-Thread");
|
||||
th.setDaemon(false); // we want it to go away when it is done
|
||||
th.start();
|
||||
return dbWorkerThread;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -412,15 +417,18 @@ public final class ImageGalleryController implements Executor {
|
||||
setListeningEnabled(false);
|
||||
ThumbnailCache.getDefault().clearCache();
|
||||
historyManager.clear();
|
||||
groupManager.clear();
|
||||
tagsManager.clearFollowUpTagName();
|
||||
tagsManager.unregisterListener(groupManager);
|
||||
tagsManager.unregisterListener(categoryManager);
|
||||
dbWorkerThread.cancelAllTasks();
|
||||
dbWorkerThread.cancel();
|
||||
dbWorkerThread = null;
|
||||
restartWorker();
|
||||
dbWorkerThread = restartWorker();
|
||||
|
||||
if (toolbar != null) {
|
||||
toolbar.reset();
|
||||
}
|
||||
|
||||
Toolbar.getDefault(this).reset();
|
||||
groupManager.clear();
|
||||
if (db != null) {
|
||||
db.closeDBCon();
|
||||
}
|
||||
@ -432,17 +440,15 @@ public final class ImageGalleryController implements Executor {
|
||||
*
|
||||
* @param innerTask
|
||||
*/
|
||||
public void queueDBWorkerTask(InnerTask innerTask) {
|
||||
|
||||
// @@@ We could make a lock for the worker thread
|
||||
public synchronized void queueDBWorkerTask(BackgroundTask innerTask) {
|
||||
if (dbWorkerThread == null) {
|
||||
restartWorker();
|
||||
dbWorkerThread = restartWorker();
|
||||
}
|
||||
dbWorkerThread.addTask(innerTask);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
synchronized public DrawableFile<?> getFileFromId(Long fileID) throws TskCoreException {
|
||||
synchronized public DrawableFile getFileFromId(Long fileID) throws TskCoreException {
|
||||
if (Objects.isNull(db)) {
|
||||
LOGGER.log(Level.WARNING, "Could not get file from id, no DB set. The case is probably closed."); //NON-NLS
|
||||
return null;
|
||||
@ -456,8 +462,12 @@ public final class ImageGalleryController implements Executor {
|
||||
Platform.runLater(this::checkForGroups);
|
||||
}
|
||||
|
||||
public ReadOnlyIntegerProperty getFileUpdateQueueSizeProperty() {
|
||||
return queueSizeProperty.getReadOnlyProperty();
|
||||
public synchronized void setToolbar(Toolbar toolbar) {
|
||||
if (this.toolbar != null) {
|
||||
throw new IllegalStateException("Can not set the toolbar a second time!");
|
||||
}
|
||||
this.toolbar = toolbar;
|
||||
thumbnailSize.bind(toolbar.thumbnailSizeProperty());
|
||||
}
|
||||
|
||||
public ReadOnlyDoubleProperty regroupProgress() {
|
||||
@ -497,29 +507,43 @@ public final class ImageGalleryController implements Executor {
|
||||
return undoManager;
|
||||
}
|
||||
|
||||
// @@@ REVIEW IF THIS SHOLD BE STATIC...
|
||||
//TODO: concept seems like the controller deal with how much work to do at a given time
|
||||
public ReadOnlyIntegerProperty getDBTasksQueueSizeProperty() {
|
||||
return queueSizeProperty.getReadOnlyProperty();
|
||||
}
|
||||
private final ReadOnlyIntegerWrapper queueSizeProperty = new ReadOnlyIntegerWrapper(0);
|
||||
|
||||
// @@@ review this class for synchronization issues (i.e. reset and cancel being called, add, etc.)
|
||||
private class DBWorkerThread implements Runnable {
|
||||
static private class DBWorkerThread extends Thread implements Cancellable {
|
||||
|
||||
private final ImageGalleryController controller;
|
||||
|
||||
DBWorkerThread(ImageGalleryController controller) {
|
||||
super("DB-Worker-Thread");
|
||||
setDaemon(false);
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
// true if the process was requested to stop. Currently no way to reset it
|
||||
private volatile boolean cancelled = false;
|
||||
|
||||
// list of tasks to run
|
||||
private final BlockingQueue<InnerTask> workQueue = new LinkedBlockingQueue<>();
|
||||
private final BlockingQueue<BackgroundTask> workQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
/**
|
||||
* Cancel all of the queued up tasks and the currently scheduled task.
|
||||
* Note that after you cancel, you cannot submit new jobs to this
|
||||
* thread.
|
||||
*/
|
||||
public void cancelAllTasks() {
|
||||
@Override
|
||||
public boolean cancel() {
|
||||
cancelled = true;
|
||||
for (InnerTask it : workQueue) {
|
||||
for (BackgroundTask it : workQueue) {
|
||||
it.cancel();
|
||||
}
|
||||
workQueue.clear();
|
||||
queueSizeProperty.set(workQueue.size());
|
||||
int size = workQueue.size();
|
||||
Platform.runLater(() -> controller.queueSizeProperty.set(size));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -527,11 +551,10 @@ public final class ImageGalleryController implements Executor {
|
||||
*
|
||||
* @param it
|
||||
*/
|
||||
public void addTask(InnerTask it) {
|
||||
public void addTask(BackgroundTask it) {
|
||||
workQueue.add(it);
|
||||
Platform.runLater(() -> {
|
||||
queueSizeProperty.set(workQueue.size());
|
||||
});
|
||||
int size = workQueue.size();
|
||||
Platform.runLater(() -> controller.queueSizeProperty.set(size));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -539,19 +562,17 @@ public final class ImageGalleryController implements Executor {
|
||||
|
||||
// nearly infinite loop waiting for tasks
|
||||
while (true) {
|
||||
if (cancelled) {
|
||||
if (cancelled || isInterrupted()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
InnerTask it = workQueue.take();
|
||||
BackgroundTask it = workQueue.take();
|
||||
|
||||
if (it.isCancelled() == false) {
|
||||
it.run();
|
||||
}
|
||||
|
||||
Platform.runLater(() -> {
|
||||
queueSizeProperty.set(workQueue.size());
|
||||
});
|
||||
int size = workQueue.size();
|
||||
Platform.runLater(() -> controller.queueSizeProperty.set(size));
|
||||
|
||||
} catch (InterruptedException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to run DB worker thread", ex); //NON-NLS
|
||||
@ -569,7 +590,14 @@ public final class ImageGalleryController implements Executor {
|
||||
*/
|
||||
@NbBundle.Messages({"ImageGalleryController.InnerTask.progress.name=progress",
|
||||
"ImageGalleryController.InnerTask.message.name=status"})
|
||||
static public abstract class InnerTask implements Runnable, Cancellable {
|
||||
static public abstract class BackgroundTask implements Runnable, Cancellable {
|
||||
|
||||
private final SimpleObjectProperty<Worker.State> state = new SimpleObjectProperty<>(Worker.State.READY);
|
||||
private final SimpleDoubleProperty progress = new SimpleDoubleProperty(this, Bundle.ImageGalleryController_InnerTask_progress_name());
|
||||
private final SimpleStringProperty message = new SimpleStringProperty(this, Bundle.ImageGalleryController_InnerTask_message_name());
|
||||
|
||||
protected BackgroundTask() {
|
||||
}
|
||||
|
||||
public double getProgress() {
|
||||
return progress.get();
|
||||
@ -586,9 +614,6 @@ public final class ImageGalleryController implements Executor {
|
||||
public final void updateMessage(String Status) {
|
||||
this.message.set(Status);
|
||||
}
|
||||
private final SimpleObjectProperty<Worker.State> state = new SimpleObjectProperty<>(Worker.State.READY);
|
||||
private final SimpleDoubleProperty progress = new SimpleDoubleProperty(this, Bundle.ImageGalleryController_InnerTask_progress_name());
|
||||
private final SimpleStringProperty message = new SimpleStringProperty(this, Bundle.ImageGalleryController_InnerTask_message_name());
|
||||
|
||||
public SimpleDoubleProperty progressProperty() {
|
||||
return progress;
|
||||
@ -602,24 +627,21 @@ public final class ImageGalleryController implements Executor {
|
||||
return state.get();
|
||||
}
|
||||
|
||||
protected void updateState(Worker.State newState) {
|
||||
state.set(newState);
|
||||
}
|
||||
|
||||
public ReadOnlyObjectProperty<Worker.State> stateProperty() {
|
||||
return new ReadOnlyObjectWrapper<>(state.get());
|
||||
}
|
||||
|
||||
protected InnerTask() {
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public boolean cancel() {
|
||||
public synchronized boolean cancel() {
|
||||
updateState(Worker.State.CANCELLED);
|
||||
return true;
|
||||
}
|
||||
|
||||
synchronized protected boolean isCancelled() {
|
||||
protected void updateState(Worker.State newState) {
|
||||
state.set(newState);
|
||||
}
|
||||
|
||||
protected synchronized boolean isCancelled() {
|
||||
return getState() == Worker.State.CANCELLED;
|
||||
}
|
||||
}
|
||||
@ -627,7 +649,7 @@ public final class ImageGalleryController implements Executor {
|
||||
/**
|
||||
* Abstract base class for tasks associated with a file in the database
|
||||
*/
|
||||
static public abstract class FileTask extends InnerTask {
|
||||
static public abstract class FileTask extends BackgroundTask {
|
||||
|
||||
private final AbstractFile file;
|
||||
private final DrawableDB taskDB;
|
||||
@ -662,7 +684,7 @@ public final class ImageGalleryController implements Executor {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
DrawableFile<?> drawableFile = DrawableFile.create(getFile(), true, getTaskDB().isVideoFile(getFile()));
|
||||
DrawableFile drawableFile = DrawableFile.create(getFile(), true, false);
|
||||
getTaskDB().updateFile(drawableFile);
|
||||
} catch (NullPointerException ex) {
|
||||
// This is one of the places where we get many errors if the case is closed during processing.
|
||||
@ -704,7 +726,7 @@ public final class ImageGalleryController implements Executor {
|
||||
@NbBundle.Messages({"BulkTask.committingDb.status=commiting image/video database",
|
||||
"BulkTask.stopCopy.status=Stopping copy to drawable db task.",
|
||||
"BulkTask.errPopulating.errMsg=There was an error populating Image Gallery database."})
|
||||
abstract static private class BulkTransferTask extends InnerTask {
|
||||
abstract static private class BulkTransferTask extends BackgroundTask {
|
||||
|
||||
static private final String FILE_EXTENSION_CLAUSE =
|
||||
"(name LIKE '%." //NON-NLS
|
||||
@ -805,10 +827,11 @@ public final class ImageGalleryController implements Executor {
|
||||
* adds them to the Drawable DB. Uses the presence of a mimetype as an
|
||||
* approximation to 'analyzed'.
|
||||
*/
|
||||
@NbBundle.Messages({"CopyAnalyzedFiles.committingDb.status=commiting image/video database",
|
||||
"CopyAnalyzedFiles.stopCopy.status=Stopping copy to drawable db task.",
|
||||
"CopyAnalyzedFiles.errPopulating.errMsg=There was an error populating Image Gallery database."})
|
||||
static private class CopyAnalyzedFiles extends BulkTransferTask {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(CopyAnalyzedFiles.class.getName());
|
||||
|
||||
CopyAnalyzedFiles(ImageGalleryController controller, DrawableDB taskDB, SleuthkitCase tskCase) {
|
||||
super(controller, taskDB, tskCase);
|
||||
}
|
||||
@ -866,6 +889,7 @@ public final class ImageGalleryController implements Executor {
|
||||
* TODO: create methods to simplify progress value/text updates to both
|
||||
* netbeans and ImageGallery progress/status
|
||||
*/
|
||||
@NbBundle.Messages({"PrePopulateDataSourceFiles.committingDb.status=commiting image/video database"})
|
||||
static private class PrePopulateDataSourceFiles extends BulkTransferTask {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(PrePopulateDataSourceFiles.class.getName());
|
||||
|
@ -25,44 +25,55 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
|
||||
<Component id="unavailableDuringInjestLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="enabledByDefaultBox" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="enabledForCaseBox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="descriptionLabel" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
|
||||
<Component id="infoIconLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="furtherDescriptionArea" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="enabledByDefaultBox" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="enabledForCaseBox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="descriptionLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="groupCategorizationWarningBox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="46" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="36" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jSeparator1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="descriptionLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="enabledByDefaultBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="enabledForCaseBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="unavailableDuringInjestLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="infoIconLabel" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="furtherDescriptionArea" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="furtherDescriptionArea" min="-2" pref="100" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="45" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jSeparator1" min="-2" pref="10" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="groupCategorizationWarningBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -145,9 +156,6 @@
|
||||
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
|
||||
<Image iconType="3" name="/org/sleuthkit/autopsy/imagegallery/images/info-icon-16.png"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/imagegallery/Bundle.properties" key="ImageGalleryOptionsPanel.infoIconLabel.text" replaceFormat="NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="unavailableDuringInjestLabel">
|
||||
@ -165,5 +173,14 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator1">
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="groupCategorizationWarningBox">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/imagegallery/Bundle.properties" key="ImageGalleryOptionsPanel.groupCategorizationWarningBox.text" replaceFormat="NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-15 Basis Technology Corp.
|
||||
* Copyright 2013-16 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,17 +18,17 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.imagegallery;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
|
||||
/** The Image/Video Gallery panel in the NetBeans provided Options Dialogs
|
||||
/**
|
||||
* The Image/Video Gallery panel in the NetBeans provided Options Dialogs
|
||||
* accessed via Tools -> Options
|
||||
*
|
||||
* Uses {@link ImageGalleryPreferences} and {@link PerCaseProperties} to
|
||||
* persist settings
|
||||
* Uses {@link ImageGalleryPreferences} and {@link PerCaseProperties} to persist
|
||||
* settings
|
||||
*/
|
||||
final class ImageGalleryOptionsPanel extends javax.swing.JPanel {
|
||||
|
||||
@ -50,10 +50,10 @@ final class ImageGalleryOptionsPanel extends javax.swing.JPanel {
|
||||
});
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
@ -64,6 +64,8 @@ final class ImageGalleryOptionsPanel extends javax.swing.JPanel {
|
||||
furtherDescriptionArea = new javax.swing.JTextArea();
|
||||
infoIconLabel = new javax.swing.JLabel();
|
||||
unavailableDuringInjestLabel = new javax.swing.JLabel();
|
||||
jSeparator1 = new javax.swing.JSeparator();
|
||||
groupCategorizationWarningBox = new javax.swing.JCheckBox();
|
||||
|
||||
setFont(getFont().deriveFont(getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
|
||||
@ -98,32 +100,38 @@ final class ImageGalleryOptionsPanel extends javax.swing.JPanel {
|
||||
|
||||
infoIconLabel.setFont(infoIconLabel.getFont().deriveFont(infoIconLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
infoIconLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/imagegallery/images/info-icon-16.png"))); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(infoIconLabel, NbBundle.getMessage(ImageGalleryOptionsPanel.class, "ImageGalleryOptionsPanel.infoIconLabel.text")); // NOI18N
|
||||
|
||||
unavailableDuringInjestLabel.setFont(unavailableDuringInjestLabel.getFont().deriveFont(unavailableDuringInjestLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
|
||||
unavailableDuringInjestLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/imagegallery/images/warning16.png"))); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(unavailableDuringInjestLabel, NbBundle.getMessage(ImageGalleryOptionsPanel.class, "ImageGalleryOptionsPanel.unavailableDuringInjestLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(groupCategorizationWarningBox, NbBundle.getMessage(ImageGalleryOptionsPanel.class, "ImageGalleryOptionsPanel.groupCategorizationWarningBox.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(21, 21, 21)
|
||||
.addComponent(unavailableDuringInjestLabel))
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(enabledByDefaultBox)
|
||||
.addComponent(enabledForCaseBox)
|
||||
.addComponent(descriptionLabel, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(21, 21, 21)
|
||||
.addComponent(infoIconLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(furtherDescriptionArea, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addComponent(enabledByDefaultBox)
|
||||
.addComponent(enabledForCaseBox)
|
||||
.addComponent(descriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addContainerGap(46, Short.MAX_VALUE))
|
||||
.addComponent(furtherDescriptionArea, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
|
||||
.addComponent(groupCategorizationWarningBox))
|
||||
.addGap(0, 36, Short.MAX_VALUE))
|
||||
.addComponent(jSeparator1))
|
||||
.addContainerGap())
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -139,8 +147,12 @@ final class ImageGalleryOptionsPanel extends javax.swing.JPanel {
|
||||
.addGap(18, 18, 18)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(infoIconLabel)
|
||||
.addComponent(furtherDescriptionArea, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(45, 45, 45))
|
||||
.addComponent(furtherDescriptionArea, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(groupCategorizationWarningBox)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@ -152,7 +164,6 @@ final class ImageGalleryOptionsPanel extends javax.swing.JPanel {
|
||||
// TODO add your handling code here:
|
||||
}//GEN-LAST:event_enabledForCaseBoxActionPerformed
|
||||
|
||||
/** {@inheritDoc} */
|
||||
void load() {
|
||||
enabledByDefaultBox.setSelected(ImageGalleryPreferences.isEnabledByDefault());
|
||||
if (Case.isCaseOpen() && IngestManager.getInstance().isIngestRunning() == false) {
|
||||
@ -162,20 +173,21 @@ final class ImageGalleryOptionsPanel extends javax.swing.JPanel {
|
||||
enabledForCaseBox.setEnabled(false);
|
||||
enabledForCaseBox.setSelected(enabledByDefaultBox.isSelected());
|
||||
}
|
||||
groupCategorizationWarningBox.setSelected(ImageGalleryPreferences.isGroupCategorizationWarningDisabled());
|
||||
}
|
||||
|
||||
/** {@inheritDoc } */
|
||||
void store() {
|
||||
ImageGalleryPreferences.setEnabledByDefault(enabledByDefaultBox.isSelected());
|
||||
ImageGalleryController.getDefault().setListeningEnabled(enabledForCaseBox.isSelected());
|
||||
if (Case.isCaseOpen()) {
|
||||
new PerCaseProperties(Case.getCurrentCase()).setConfigSetting(ImageGalleryModule.getModuleName(), PerCaseProperties.ENABLED, Boolean.toString(enabledForCaseBox.isSelected()));
|
||||
}
|
||||
ImageGalleryPreferences.setGroupCategorizationWarningDisabled(groupCategorizationWarningBox.isSelected());
|
||||
}
|
||||
|
||||
/** {@inheritDoc }
|
||||
*
|
||||
* @return true, since there is no way for this form to be invalid */
|
||||
/**
|
||||
* @return true, since there is no way for this form to be invalid
|
||||
*/
|
||||
boolean valid() {
|
||||
// TODO check whether form is consistent and complete
|
||||
return true;
|
||||
@ -186,7 +198,9 @@ final class ImageGalleryOptionsPanel extends javax.swing.JPanel {
|
||||
private javax.swing.JCheckBox enabledByDefaultBox;
|
||||
private javax.swing.JCheckBox enabledForCaseBox;
|
||||
private javax.swing.JTextArea furtherDescriptionArea;
|
||||
private javax.swing.JCheckBox groupCategorizationWarningBox;
|
||||
private javax.swing.JLabel infoIconLabel;
|
||||
private javax.swing.JSeparator jSeparator1;
|
||||
private javax.swing.JLabel unavailableDuringInjestLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Copyright 2013-16 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -22,14 +22,21 @@ import java.util.prefs.PreferenceChangeListener;
|
||||
import java.util.prefs.Preferences;
|
||||
import org.openide.util.NbPreferences;
|
||||
|
||||
/** Persists Image Analyzer preference to a per user .properties file */
|
||||
class ImageGalleryPreferences {
|
||||
/**
|
||||
* Persists Image Gallery preference to a per user .properties file
|
||||
*/
|
||||
public class ImageGalleryPreferences {
|
||||
|
||||
/** NBPreferences object used to persist settings */
|
||||
/**
|
||||
* NBPreferences object used to persist settings
|
||||
*/
|
||||
private static final Preferences preferences = NbPreferences.forModule(ImageGalleryPreferences.class);
|
||||
|
||||
/** key for the listening enabled for new cases setting */
|
||||
/**
|
||||
* key for the listening enabled for new cases setting
|
||||
*/
|
||||
private static final String ENABLED_BY_DEFAULT = "enabled_by_default"; //NON-NLS
|
||||
private static final String GROUP_CATEGORIZATION_WARNING_DISABLED = "group_categorization_warning_disabled"; //NON-NLS
|
||||
|
||||
/**
|
||||
* Return setting of whether Image Analyzer should be automatically enabled
|
||||
@ -38,15 +45,30 @@ class ImageGalleryPreferences {
|
||||
*
|
||||
* @return true if new cases should have image analyzer enabled.
|
||||
*/
|
||||
static boolean isEnabledByDefault() {
|
||||
public static boolean isEnabledByDefault() {
|
||||
final boolean aBoolean = preferences.getBoolean(ENABLED_BY_DEFAULT, true);
|
||||
return aBoolean;
|
||||
}
|
||||
|
||||
static void setEnabledByDefault(boolean b) {
|
||||
public static void setEnabledByDefault(boolean b) {
|
||||
preferences.putBoolean(ENABLED_BY_DEFAULT, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the warning about overwriting categories when acting on an
|
||||
* entire group is disabled.
|
||||
*
|
||||
* @return true if the warning is disabled.
|
||||
*/
|
||||
public static boolean isGroupCategorizationWarningDisabled() {
|
||||
final boolean aBoolean = preferences.getBoolean(GROUP_CATEGORIZATION_WARNING_DISABLED, false);
|
||||
return aBoolean;
|
||||
}
|
||||
|
||||
public static void setGroupCategorizationWarningDisabled(boolean b) {
|
||||
preferences.putBoolean(GROUP_CATEGORIZATION_WARNING_DISABLED, b);
|
||||
}
|
||||
|
||||
static void addChangeListener(PreferenceChangeListener l) {
|
||||
preferences.addPreferenceChangeListener(l);
|
||||
}
|
||||
|
@ -148,7 +148,8 @@ public final class ImageGalleryTopComponent extends TopComponent implements Expl
|
||||
fullUIStack.getChildren().add(borderPane);
|
||||
splitPane = new SplitPane();
|
||||
borderPane.setCenter(splitPane);
|
||||
borderPane.setTop(Toolbar.getDefault(controller));
|
||||
Toolbar toolbar = new Toolbar(controller);
|
||||
borderPane.setTop(toolbar);
|
||||
borderPane.setBottom(new StatusBar(controller));
|
||||
|
||||
metaDataTable = new MetaDataPane(controller);
|
||||
@ -168,6 +169,7 @@ public final class ImageGalleryTopComponent extends TopComponent implements Expl
|
||||
splitPane.setDividerPositions(0.1, 1.0);
|
||||
|
||||
ImageGalleryController.getDefault().setStacks(fullUIStack, centralStack);
|
||||
ImageGalleryController.getDefault().setToolbar(toolbar);
|
||||
ImageGalleryController.getDefault().setShowTree(() -> tabPane.getSelectionModel().select(groupTree));
|
||||
});
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ public enum ThumbnailCache {
|
||||
* could not be generated
|
||||
*/
|
||||
@Nullable
|
||||
public Image get(DrawableFile<?> file) {
|
||||
public Image get(DrawableFile file) {
|
||||
try {
|
||||
return cache.get(file.getId(), () -> load(file));
|
||||
} catch (UncheckedExecutionException | CacheLoader.InvalidCacheLoadException | ExecutionException ex) {
|
||||
@ -124,9 +124,9 @@ public enum ThumbnailCache {
|
||||
*
|
||||
* @return an (possibly empty) optional containing a thumbnail
|
||||
*/
|
||||
private Image load(DrawableFile<?> file) {
|
||||
private Image load(DrawableFile file) {
|
||||
|
||||
if (FileTypeUtils.isGIF(file)) {
|
||||
if (FileTypeUtils.isGIF(file.getAbstractFile())) {
|
||||
//directly read gif to preserve potential animation,
|
||||
//NOTE: not saved to disk!
|
||||
return new Image(new BufferedInputStream(new ReadContentInputStream(file.getAbstractFile())), MAX_THUMBNAIL_SIZE, MAX_THUMBNAIL_SIZE, true, true);
|
||||
@ -171,7 +171,7 @@ public enum ThumbnailCache {
|
||||
* @return a Optional containing a File to store the cached icon in or an
|
||||
* empty optional if there was a problem.
|
||||
*/
|
||||
private static Optional<File> getCacheFile(DrawableFile<?> file) {
|
||||
private static Optional<File> getCacheFile(DrawableFile file) {
|
||||
try {
|
||||
return Optional.of(ImageUtils.getCachedThumbnailFile(file.getAbstractFile(), MAX_THUMBNAIL_SIZE));
|
||||
|
||||
@ -181,7 +181,7 @@ public enum ThumbnailCache {
|
||||
}
|
||||
}
|
||||
|
||||
public Task<Image> getThumbnailTask(DrawableFile<?> file) {
|
||||
public Task<Image> getThumbnailTask(DrawableFile file) {
|
||||
final Image thumbnail = cache.getIfPresent(file.getId());
|
||||
if (thumbnail != null) {
|
||||
return TaskUtils.taskFrom(() -> thumbnail);
|
||||
|
@ -90,10 +90,10 @@ public class AddTagAction extends Action {
|
||||
DrawableTagsManager tagsManager = controller.getTagsManager();
|
||||
for (Long fileID : selectedFiles) {
|
||||
try {
|
||||
final DrawableFile<?> file = controller.getFileFromId(fileID);
|
||||
final DrawableFile file = controller.getFileFromId(fileID);
|
||||
LOGGER.log(Level.INFO, "tagging {0} with {1} and comment {2}", new Object[]{file.getName(), tagName.getDisplayName(), comment}); //NON-NLS
|
||||
|
||||
List<ContentTag> contentTags = tagsManager.getContentTagsByContent(file);
|
||||
List<ContentTag> contentTags = tagsManager.getContentTags(file);
|
||||
Optional<TagName> duplicateTagName = contentTags.stream()
|
||||
.map(ContentTag::getName)
|
||||
.filter(tagName::equals)
|
||||
|
@ -76,7 +76,7 @@ public class CategorizeAction extends Action {
|
||||
this.selectedFileIDs = selectedFileIDs;
|
||||
this.createUndo = createUndo;
|
||||
setGraphic(cat.getGraphic());
|
||||
setEventHandler(actionEvent -> addCatToFiles());
|
||||
setEventHandler(actionEvent -> addCatToFiles(selectedFileIDs));
|
||||
setAccelerator(new KeyCodeCombination(KeyCode.getKeyCode(Integer.toString(cat.getCategoryNumber()))));
|
||||
}
|
||||
|
||||
@ -84,9 +84,10 @@ public class CategorizeAction extends Action {
|
||||
return new CategoryMenu(controller);
|
||||
}
|
||||
|
||||
private void addCatToFiles() {
|
||||
Logger.getAnonymousLogger().log(Level.INFO, "categorizing{0} as {1}", new Object[]{selectedFileIDs.toString(), cat.getDisplayName()}); //NON-NLS
|
||||
controller.queueDBWorkerTask(new CategorizeTask(selectedFileIDs, cat, createUndo));
|
||||
|
||||
final void addCatToFiles(Set<Long> ids) {
|
||||
Logger.getAnonymousLogger().log(Level.INFO, "categorizing{0} as {1}", new Object[]{ids.toString(), cat.getDisplayName()}); //NON-NLS
|
||||
controller.queueDBWorkerTask(new CategorizeTask(ids, cat, createUndo));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,7 +113,7 @@ public class CategorizeAction extends Action {
|
||||
@NbBundle.Messages({"# {0} - fileID number",
|
||||
"CategorizeTask.errorUnable.msg=Unable to categorize {0}.",
|
||||
"CategorizeTask.errorUnable.title=Categorizing Error"})
|
||||
private class CategorizeTask extends ImageGalleryController.InnerTask {
|
||||
private class CategorizeTask extends ImageGalleryController.BackgroundTask {
|
||||
|
||||
private final Set<Long> fileIDs;
|
||||
|
||||
@ -136,7 +137,7 @@ public class CategorizeAction extends Action {
|
||||
TagName catZeroTagName = categoryManager.getTagName(Category.ZERO);
|
||||
for (long fileID : fileIDs) {
|
||||
try {
|
||||
DrawableFile<?> file = controller.getFileFromId(fileID); //drawable db access
|
||||
DrawableFile file = controller.getFileFromId(fileID); //drawable db access
|
||||
if (createUndo) {
|
||||
Category oldCat = file.getCategory(); //drawable db access
|
||||
TagName oldCatTagName = categoryManager.getTagName(oldCat);
|
||||
@ -145,8 +146,8 @@ public class CategorizeAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
final List<ContentTag> fileTags = tagsManager.getContentTagsByContent(file);
|
||||
if (tagName.equals(catZeroTagName)) {
|
||||
final List<ContentTag> fileTags = tagsManager.getContentTags(file);
|
||||
if (tagName == categoryManager.getTagName(Category.ZERO)) {
|
||||
// delete all cat tags for cat-0
|
||||
fileTags.stream()
|
||||
.filter(tag -> CategoryManager.isCategoryTagName(tag.getName()))
|
||||
@ -203,8 +204,8 @@ public class CategorizeAction extends Action {
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
CategorizeAction categorizeAction = new CategorizeAction(controller, newCategory, this.oldCategories.keySet(), false);
|
||||
categorizeAction.addCatToFiles();
|
||||
new CategorizeAction(controller, newCategory, this.oldCategories.keySet(), false)
|
||||
.handle(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -216,7 +217,7 @@ public class CategorizeAction extends Action {
|
||||
|
||||
for (Map.Entry<Long, Category> entry : oldCategories.entrySet()) {
|
||||
new CategorizeAction(controller, entry.getValue(), Collections.singleton(entry.getKey()), false)
|
||||
.addCatToFiles();
|
||||
.handle(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,16 +18,110 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.imagegallery.actions;
|
||||
|
||||
import java.util.HashSet;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.geometry.Orientation;
|
||||
import javafx.geometry.VPos;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.ButtonBar;
|
||||
import javafx.scene.control.ButtonType;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.ContentDisplay;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Separator;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryPreferences;
|
||||
import org.sleuthkit.autopsy.imagegallery.datamodel.Category;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
*
|
||||
* An action that categorizes all the files in the currently active group with
|
||||
* the given category.
|
||||
*/
|
||||
public class CategorizeGroupAction extends CategorizeAction {
|
||||
|
||||
public CategorizeGroupAction(Category cat, ImageGalleryController controller) {
|
||||
super(controller, cat, new HashSet<>(controller.viewState().get().getGroup().getFileIDs()));
|
||||
private final static Logger LOGGER = Logger.getLogger(CategorizeGroupAction.class.getName());
|
||||
|
||||
public CategorizeGroupAction(Category newCat, ImageGalleryController controller) {
|
||||
super(controller, newCat, null);
|
||||
setEventHandler(actionEvent -> {
|
||||
ObservableList<Long> fileIDs = controller.viewState().get().getGroup().getFileIDs();
|
||||
|
||||
if (ImageGalleryPreferences.isGroupCategorizationWarningDisabled()) {
|
||||
//if they have preveiously disabled the warning, just go ahead and apply categories.
|
||||
addCatToFiles(ImmutableSet.copyOf(fileIDs));
|
||||
} else {
|
||||
final Map<Category, Long> catCountMap = new HashMap<>();
|
||||
|
||||
for (Long fileID : fileIDs) {
|
||||
try {
|
||||
Category category = controller.getFileFromId(fileID).getCategory();
|
||||
if (false == Category.ZERO.equals(category) && newCat.equals(category) == false) {
|
||||
catCountMap.merge(category, 1L, Long::sum);
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Failed to categorize files.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (catCountMap.isEmpty()) {
|
||||
//if there are not going to be any categories overwritten, skip the warning.
|
||||
addCatToFiles(ImmutableSet.copyOf(fileIDs));
|
||||
} else {
|
||||
showConfirmationDialog(catCountMap, newCat, fileIDs);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NbBundle.Messages({"CategorizeGroupAction.OverwriteButton.text=Overwrite",
|
||||
"# {0} - number of files with the category", "# {1} - the name of the category",
|
||||
"CategorizeGroupAction.fileCountMessage={0} with {1}",
|
||||
"CategorizeGroupAction.dontShowAgain=Don't show this message again",
|
||||
"CategorizeGroupAction.fileCountHeader=Files in the following categories will have their categories overwritten: "})
|
||||
private void showConfirmationDialog(final Map<Category, Long> catCountMap, Category newCat, ObservableList<Long> fileIDs) {
|
||||
|
||||
ButtonType categorizeButtonType =
|
||||
new ButtonType(Bundle.CategorizeGroupAction_OverwriteButton_text(), ButtonBar.ButtonData.APPLY);
|
||||
|
||||
VBox textFlow = new VBox();
|
||||
|
||||
for (Map.Entry<Category, Long> entry : catCountMap.entrySet()) {
|
||||
if (entry.getKey().equals(newCat) == false) {
|
||||
if (entry.getValue() > 0) {
|
||||
Label label = new Label(Bundle.CategorizeGroupAction_fileCountMessage(entry.getValue(), entry.getKey().getDisplayName()),
|
||||
entry.getKey().getGraphic());
|
||||
label.setContentDisplay(ContentDisplay.RIGHT);
|
||||
textFlow.getChildren().add(label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox checkBox = new CheckBox(Bundle.CategorizeGroupAction_dontShowAgain());
|
||||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION, "", categorizeButtonType, ButtonType.CANCEL); //NON-NLS
|
||||
Separator separator = new Separator(Orientation.HORIZONTAL);
|
||||
separator.setPrefHeight(30);
|
||||
separator.setValignment(VPos.BOTTOM);
|
||||
VBox.setVgrow(separator, Priority.ALWAYS);
|
||||
VBox vBox = new VBox(5, textFlow, separator, checkBox);
|
||||
alert.getDialogPane().setContent(vBox);
|
||||
alert.setHeaderText(Bundle.CategorizeGroupAction_fileCountHeader());
|
||||
alert.showAndWait()
|
||||
.filter(categorizeButtonType::equals)
|
||||
.ifPresent(button -> {
|
||||
//if they accept the overwrites, then apply them.
|
||||
addCatToFiles(ImmutableSet.copyOf(fileIDs));
|
||||
if (checkBox.isSelected()) {
|
||||
//do we want to save this even on cancel also?
|
||||
ImageGalleryPreferences.setGroupCategorizationWarningDisabled(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,9 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.Category;
|
||||
public class CategorizeSelectedFilesAction extends CategorizeAction {
|
||||
|
||||
public CategorizeSelectedFilesAction(Category cat, ImageGalleryController controller) {
|
||||
super(controller, cat, controller.getSelectionModel().getSelected());
|
||||
super(controller, cat, null);
|
||||
setEventHandler(actionEvent ->
|
||||
addCatToFiles(controller.getSelectionModel().getSelected())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public class DeleteFollowUpTagAction extends Action {
|
||||
private static final Logger LOGGER = Logger.getLogger(DeleteFollowUpTagAction.class.getName());
|
||||
|
||||
@NbBundle.Messages("DeleteFollwUpTagAction.displayName=Delete Follow Up Tag")
|
||||
public DeleteFollowUpTagAction(final ImageGalleryController controller, final DrawableFile<?> file) {
|
||||
public DeleteFollowUpTagAction(final ImageGalleryController controller, final DrawableFile file) {
|
||||
super(Bundle.DeleteFollwUpTagAction_displayName());
|
||||
setEventHandler((ActionEvent t) -> {
|
||||
new SwingWorker<Void, Void>() {
|
||||
@ -52,7 +52,7 @@ public class DeleteFollowUpTagAction extends Action {
|
||||
try {
|
||||
final TagName followUpTagName = tagsManager.getFollowUpTagName();
|
||||
|
||||
List<ContentTag> contentTagsByContent = tagsManager.getContentTagsByContent(file);
|
||||
List<ContentTag> contentTagsByContent = tagsManager.getContentTags(file);
|
||||
for (ContentTag ct : contentTagsByContent) {
|
||||
if (ct.getName().getDisplayName().equals(followUpTagName.getDisplayName())) {
|
||||
tagsManager.deleteContentTag(ct);
|
||||
|
@ -39,7 +39,7 @@ public class OpenExternalViewerAction extends Action {
|
||||
private static final Image EXTERNAL = new Image(OpenExternalViewerAction.class.getResource("/org/sleuthkit/autopsy/imagegallery/images/external.png").toExternalForm()); //NON-NLS
|
||||
private static final ActionEvent ACTION_EVENT = new ActionEvent(OpenExternalViewerAction.class, ActionEvent.ACTION_PERFORMED, ""); //Swing ActionEvent //NOI18N
|
||||
|
||||
public OpenExternalViewerAction(DrawableFile<?> file) {
|
||||
public OpenExternalViewerAction(DrawableFile file) {
|
||||
super(Bundle.OpenExternalViewerAction_displayName());
|
||||
|
||||
/**
|
||||
|
@ -28,6 +28,10 @@ import org.sleuthkit.datamodel.TagName;
|
||||
public class TagGroupAction extends AddTagAction {
|
||||
|
||||
public TagGroupAction(final TagName tagName, ImageGalleryController controller) {
|
||||
super(controller, tagName, ImmutableSet.copyOf(controller.viewState().get().getGroup().getFileIDs()));
|
||||
super(controller, tagName, null);
|
||||
setEventHandler(actionEvent ->
|
||||
new AddTagAction(controller, tagName, ImmutableSet.copyOf(controller.viewState().get().getGroup().getFileIDs())).
|
||||
handle(actionEvent)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,10 @@ import org.sleuthkit.datamodel.TagName;
|
||||
public class TagSelectedFilesAction extends AddTagAction {
|
||||
|
||||
public TagSelectedFilesAction(final TagName tagName, ImageGalleryController controller) {
|
||||
super(controller, tagName, controller.getSelectionModel().getSelected());
|
||||
super(controller, tagName, null);
|
||||
setEventHandler(actionEvent ->
|
||||
new AddTagAction(controller, tagName, controller.getSelectionModel().getSelected()).
|
||||
handle(actionEvent)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -248,7 +248,7 @@ public class CategoryManager {
|
||||
final DrawableTagsManager tagsManager = controller.getTagsManager();
|
||||
try {
|
||||
//remove old category tag(s) if necessary
|
||||
for (ContentTag ct : tagsManager.getContentTagsByContent(addedTag.getContent())) {
|
||||
for (ContentTag ct : tagsManager.getContentTags(addedTag.getContent())) {
|
||||
if (ct.getId() != addedTag.getId()
|
||||
&& CategoryManager.isCategoryTagName(ct.getName())) {
|
||||
try {
|
||||
|
@ -111,13 +111,13 @@ public class DrawableAttribute<T extends Comparable<T>> {
|
||||
new DrawableAttribute<>(AttributeName.CREATED_TIME, Bundle.DrawableAttribute_createdTime(),
|
||||
true,
|
||||
"clock--plus.png", //NON-NLS
|
||||
f -> Collections.singleton(ContentUtils.getStringTime(f.getCrtime(), f)));
|
||||
f -> Collections.singleton(ContentUtils.getStringTime(f.getCrtime(), f.getAbstractFile())));
|
||||
|
||||
public final static DrawableAttribute<String> MODIFIED_TIME =
|
||||
new DrawableAttribute<>(AttributeName.MODIFIED_TIME, Bundle.DrawableAttribute_modifiedTime(),
|
||||
true,
|
||||
"clock--pencil.png", //NON-NLS
|
||||
f -> Collections.singleton(ContentUtils.getStringTime(f.getMtime(), f)));
|
||||
f -> Collections.singleton(ContentUtils.getStringTime(f.getMtime(), f.getAbstractFile())));
|
||||
|
||||
public final static DrawableAttribute<String> MAKE =
|
||||
new DrawableAttribute<>(AttributeName.MAKE, Bundle.DrawableAttribute_cameraMake(),
|
||||
@ -168,9 +168,9 @@ public class DrawableAttribute<T extends Comparable<T>> {
|
||||
Arrays.asList(NAME, ANALYZED, CATEGORY, TAGS, PATH, CREATED_TIME,
|
||||
MODIFIED_TIME, MD5_HASH, HASHSET, MAKE, MODEL, OBJ_ID, WIDTH, HEIGHT, MIME_TYPE);
|
||||
|
||||
private final Function<DrawableFile<?>, Collection<T>> extractor;
|
||||
private final Function<DrawableFile, Collection<T>> extractor;
|
||||
|
||||
private DrawableAttribute(AttributeName name, String displayName, Boolean isDBColumn, String imageName, Function<DrawableFile<?>, Collection<T>> extractor) {
|
||||
private DrawableAttribute(AttributeName name, String displayName, Boolean isDBColumn, String imageName, Function<DrawableFile, Collection<T>> extractor) {
|
||||
this.attrName = name;
|
||||
this.displayName = new ReadOnlyStringWrapper(displayName);
|
||||
this.isDBColumn = isDBColumn;
|
||||
@ -223,7 +223,7 @@ public class DrawableAttribute<T extends Comparable<T>> {
|
||||
return displayName.get();
|
||||
}
|
||||
|
||||
public Collection<T> getValue(DrawableFile<?> f) {
|
||||
public Collection<T> getValue(DrawableFile f) {
|
||||
return extractor.apply(f);
|
||||
}
|
||||
|
||||
|
@ -497,9 +497,9 @@ public final class DrawableDB {
|
||||
ArrayList<BlackboardArtifact> artifacts = tskCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT, fileID);
|
||||
|
||||
for (BlackboardArtifact a : artifacts) {
|
||||
List<BlackboardAttribute> attributes = a.getAttributes(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME);
|
||||
for (BlackboardAttribute attr : attributes) {
|
||||
hashNames.add(attr.getValueString());
|
||||
BlackboardAttribute attribute = a.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
|
||||
if (attribute != null) {
|
||||
hashNames.add(attribute.getValueString());
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableSet(hashNames);
|
||||
@ -569,23 +569,23 @@ public final class DrawableDB {
|
||||
return removeFile;
|
||||
}
|
||||
|
||||
public void updateFile(DrawableFile<?> f) {
|
||||
public void updateFile(DrawableFile f) {
|
||||
DrawableTransaction trans = beginTransaction();
|
||||
updateFile(f, trans);
|
||||
commitTransaction(trans, true);
|
||||
}
|
||||
|
||||
public void insertFile(DrawableFile<?> f) {
|
||||
public void insertFile(DrawableFile f) {
|
||||
DrawableTransaction trans = beginTransaction();
|
||||
insertFile(f, trans);
|
||||
commitTransaction(trans, true);
|
||||
}
|
||||
|
||||
public void insertFile(DrawableFile<?> f, DrawableTransaction tr) {
|
||||
public void insertFile(DrawableFile f, DrawableTransaction tr) {
|
||||
insertOrUpdateFile(f, tr, insertFileStmt);
|
||||
}
|
||||
|
||||
public void updateFile(DrawableFile<?> f, DrawableTransaction tr) {
|
||||
public void updateFile(DrawableFile f, DrawableTransaction tr) {
|
||||
insertOrUpdateFile(f, tr, updateFileStmt);
|
||||
}
|
||||
|
||||
@ -602,7 +602,7 @@ public final class DrawableDB {
|
||||
* @param tr a transaction to use, must not be null
|
||||
* @param stmt the statement that does the actull inserting
|
||||
*/
|
||||
private void insertOrUpdateFile(DrawableFile<?> f, @Nonnull DrawableTransaction tr, @Nonnull PreparedStatement stmt) {
|
||||
private void insertOrUpdateFile(DrawableFile f, @Nonnull DrawableTransaction tr, @Nonnull PreparedStatement stmt) {
|
||||
|
||||
if (tr.isClosed()) {
|
||||
throw new IllegalArgumentException("can't update database with closed transaction");
|
||||
@ -686,7 +686,7 @@ public final class DrawableDB {
|
||||
tr.commit(notify);
|
||||
}
|
||||
|
||||
public Boolean isFileAnalyzed(DrawableFile<?> f) {
|
||||
public Boolean isFileAnalyzed(DrawableFile f) {
|
||||
return isFileAnalyzed(f.getId());
|
||||
}
|
||||
|
||||
@ -979,7 +979,7 @@ public final class DrawableDB {
|
||||
* @throws TskCoreException if unable to get a file from the currently open
|
||||
* {@link SleuthkitCase}
|
||||
*/
|
||||
private DrawableFile<?> getFileFromID(Long id, boolean analyzed) throws TskCoreException {
|
||||
private DrawableFile getFileFromID(Long id, boolean analyzed) throws TskCoreException {
|
||||
try {
|
||||
AbstractFile f = tskCase.getAbstractFileById(id);
|
||||
return DrawableFile.create(f, analyzed, isVideoFile(f));
|
||||
@ -997,7 +997,7 @@ public final class DrawableDB {
|
||||
* @throws TskCoreException if unable to get a file from the currently open
|
||||
* {@link SleuthkitCase}
|
||||
*/
|
||||
public DrawableFile<?> getFileFromID(Long id) throws TskCoreException {
|
||||
public DrawableFile getFileFromID(Long id) throws TskCoreException {
|
||||
try {
|
||||
AbstractFile f = tskCase.getAbstractFileById(id);
|
||||
return DrawableFile.create(f,
|
||||
@ -1242,8 +1242,8 @@ public final class DrawableDB {
|
||||
String fileIdsList = "(" + StringUtils.join(fileIDs, ",") + " )";
|
||||
|
||||
//count the fileids that are in the given list and don't have a non-zero category assigned to them.
|
||||
String name =
|
||||
"SELECT COUNT(obj_id) FROM tsk_files where obj_id IN " + fileIdsList //NON-NLS
|
||||
String name
|
||||
= "SELECT COUNT(obj_id) FROM tsk_files where obj_id IN " + fileIdsList //NON-NLS
|
||||
+ " AND obj_id NOT IN (SELECT obj_id FROM content_tags WHERE content_tags.tag_name_id IN " + catTagNameIDs + ")"; //NON-NLS
|
||||
try (SleuthkitCase.CaseDbQuery executeQuery = controller.getSleuthKitCase().executeQuery(name);
|
||||
ResultSet resultSet = executeQuery.getResultSet();) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-15 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,6 +19,7 @@
|
||||
package org.sleuthkit.autopsy.imagegallery.datamodel;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@ -42,39 +43,36 @@ import org.sleuthkit.autopsy.imagegallery.ThumbnailCache;
|
||||
import org.sleuthkit.autopsy.imagegallery.utils.TaskUtils;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentVisitor;
|
||||
import org.sleuthkit.datamodel.ReadContentInputStream;
|
||||
import org.sleuthkit.datamodel.SleuthkitItemVisitor;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.Tag;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* @TODO: There is something I don't understand or have done wrong about
|
||||
* implementing this class,as it is unreadable by
|
||||
* {@link ReadContentInputStream}. As a work around we keep a reference to the
|
||||
* original {@link AbstractFile} to use when reading the image. -jm
|
||||
* A file that contains visual information such as an image or video.
|
||||
*/
|
||||
public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile {
|
||||
public abstract class DrawableFile {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(DrawableFile.class.getName());
|
||||
|
||||
public static DrawableFile<?> create(AbstractFile abstractFileById, boolean analyzed) {
|
||||
public static DrawableFile create(AbstractFile abstractFileById, boolean analyzed) {
|
||||
return create(abstractFileById, analyzed, FileTypeUtils.isVideoFile(abstractFileById));
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip the database query if we have already determined the file type.
|
||||
*/
|
||||
public static DrawableFile<?> create(AbstractFile abstractFileById, boolean analyzed, boolean isVideo) {
|
||||
public static DrawableFile create(AbstractFile abstractFileById, boolean analyzed, boolean isVideo) {
|
||||
return isVideo
|
||||
? new VideoFile<>(abstractFileById, analyzed)
|
||||
: new ImageFile<>(abstractFileById, analyzed);
|
||||
? new VideoFile(abstractFileById, analyzed)
|
||||
: new ImageFile(abstractFileById, analyzed);
|
||||
}
|
||||
|
||||
public static DrawableFile<?> create(Long id, boolean analyzed) throws TskCoreException, IllegalStateException {
|
||||
public static DrawableFile create(Long id, boolean analyzed) throws TskCoreException, IllegalStateException {
|
||||
return create(Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(id), analyzed);
|
||||
}
|
||||
|
||||
@ -82,7 +80,7 @@ public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile
|
||||
|
||||
private String drawablePath;
|
||||
|
||||
private final T file;
|
||||
private final AbstractFile file;
|
||||
|
||||
private final SimpleBooleanProperty analyzed;
|
||||
|
||||
@ -92,89 +90,77 @@ public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile
|
||||
|
||||
private String model;
|
||||
|
||||
protected DrawableFile(T file, Boolean analyzed) {
|
||||
/*
|
||||
* @TODO: the two 'new Integer(0).shortValue()' values and null are
|
||||
* placeholders because the super constructor expects values i can't get
|
||||
* easily at the moment. I assume this is related to why
|
||||
* ReadContentInputStream can't read from DrawableFiles.
|
||||
*/
|
||||
|
||||
super(file.getSleuthkitCase(),
|
||||
file.getId(),
|
||||
file.getAttrType(),
|
||||
file.getAttrId(),
|
||||
file.getName(),
|
||||
file.getType(),
|
||||
file.getMetaAddr(),
|
||||
(int) file.getMetaSeq(),
|
||||
file.getDirType(),
|
||||
file.getMetaType(),
|
||||
null,
|
||||
new Integer(0).shortValue(),
|
||||
file.getSize(),
|
||||
file.getCtime(),
|
||||
file.getCrtime(),
|
||||
file.getAtime(),
|
||||
file.getMtime(),
|
||||
new Integer(0).shortValue(),
|
||||
file.getUid(),
|
||||
file.getGid(),
|
||||
file.getMd5Hash(),
|
||||
file.getKnown(),
|
||||
file.getParentPath(),
|
||||
file.getMIMEType());
|
||||
protected DrawableFile(AbstractFile file, Boolean analyzed) {
|
||||
this.analyzed = new SimpleBooleanProperty(analyzed);
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public abstract boolean isVideo();
|
||||
|
||||
@Override
|
||||
public boolean isRoot() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(SleuthkitItemVisitor<T> v) {
|
||||
return file.accept(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ContentVisitor<T> v) {
|
||||
return file.accept(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Content> getChildren() throws TskCoreException {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Long> getChildrenIds() throws TskCoreException {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<Pair<DrawableAttribute<?>, Collection<?>>> getAttributesList() {
|
||||
return DrawableAttribute.getValues().stream()
|
||||
.map(this::makeAttributeValuePair)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public String getMIMEType() {
|
||||
return file.getMIMEType();
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return file.getId();
|
||||
}
|
||||
|
||||
public long getCtime() {
|
||||
return file.getCtime();
|
||||
}
|
||||
|
||||
public long getCrtime() {
|
||||
return file.getCrtime();
|
||||
}
|
||||
|
||||
public long getAtime() {
|
||||
return file.getAtime();
|
||||
}
|
||||
|
||||
public long getMtime() {
|
||||
return file.getMtime();
|
||||
}
|
||||
|
||||
public String getMd5Hash() {
|
||||
return file.getMd5Hash();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return file.getName();
|
||||
}
|
||||
|
||||
public String getAtimeAsDate() {
|
||||
return file.getAtimeAsDate();
|
||||
}
|
||||
|
||||
public synchronized String getUniquePath() throws TskCoreException {
|
||||
return file.getUniquePath();
|
||||
}
|
||||
|
||||
public SleuthkitCase getSleuthkitCase() {
|
||||
return file.getSleuthkitCase();
|
||||
}
|
||||
|
||||
private Pair<DrawableAttribute<?>, Collection<?>> makeAttributeValuePair(DrawableAttribute<?> t) {
|
||||
return new Pair<>(t, t.getValue(DrawableFile.this));
|
||||
}
|
||||
|
||||
public String getModel() {
|
||||
if (model == null) {
|
||||
model = WordUtils.capitalizeFully((String) getValueOfBBAttribute(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MODEL));
|
||||
model = WordUtils.capitalizeFully((String) getValueOfBBAttribute(ARTIFACT_TYPE.TSK_METADATA_EXIF, ATTRIBUTE_TYPE.TSK_DEVICE_MODEL));
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
public String getMake() {
|
||||
if (make == null) {
|
||||
make = WordUtils.capitalizeFully((String) getValueOfBBAttribute(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MAKE));
|
||||
make = WordUtils.capitalizeFully((String) getValueOfBBAttribute(ARTIFACT_TYPE.TSK_METADATA_EXIF, ATTRIBUTE_TYPE.TSK_DEVICE_MAKE));
|
||||
}
|
||||
return make;
|
||||
}
|
||||
@ -182,18 +168,18 @@ public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile
|
||||
public Set<TagName> getTagNames() {
|
||||
try {
|
||||
|
||||
return getSleuthkitCase().getContentTagsByContent(this).stream()
|
||||
return getContentTags().stream()
|
||||
.map(Tag::getName)
|
||||
.collect(Collectors.toSet());
|
||||
} catch (TskCoreException ex) {
|
||||
Logger.getAnonymousLogger().log(Level.WARNING, "problem looking up " + DrawableAttribute.TAGS.getDisplayName() + " for " + file.getName(), ex); //NON-NLS
|
||||
} catch (IllegalStateException ex) {
|
||||
Logger.getAnonymousLogger().log(Level.WARNING, "there is no case open; failed to look up " + DrawableAttribute.TAGS.getDisplayName() + " for " + file.getName()); //NON-NLS
|
||||
Logger.getAnonymousLogger().log(Level.WARNING, "there is no case open; failed to look up " + DrawableAttribute.TAGS.getDisplayName() + " for " + getContentPathSafe(), ex); //NON-NLS
|
||||
}
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
protected Object getValueOfBBAttribute(BlackboardArtifact.ARTIFACT_TYPE artType, BlackboardAttribute.ATTRIBUTE_TYPE attrType) {
|
||||
protected Object getValueOfBBAttribute(ARTIFACT_TYPE artType, ATTRIBUTE_TYPE attrType) {
|
||||
try {
|
||||
|
||||
//why doesn't file.getArtifacts() work?
|
||||
@ -203,8 +189,8 @@ public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile
|
||||
for (BlackboardArtifact artf : artifacts) {
|
||||
if (artf.getArtifactTypeID() == artType.getTypeID()) {
|
||||
for (BlackboardAttribute attr : artf.getAttributes()) {
|
||||
if (attr.getAttributeTypeID() == attrType.getTypeID()) {
|
||||
switch (attr.getValueType()) {
|
||||
if (attr.getAttributeType().getTypeID() == attrType.getTypeID()) {
|
||||
switch (attr.getAttributeType().getValueType()) {
|
||||
case BYTE:
|
||||
return attr.getValueBytes();
|
||||
case DOUBLE:
|
||||
@ -223,7 +209,8 @@ public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
Logger.getAnonymousLogger().log(Level.WARNING, "problem looking up {0}/{1}" + " " + " for {2}", new Object[]{artType.getDisplayName(), attrType.getDisplayName(), getName()}); //NON-NLS
|
||||
Logger.getAnonymousLogger().log(Level.WARNING, ex,
|
||||
() -> MessageFormat.format("problem looking up {0}/{1}" + " " + " for {2}", new Object[]{artType.getDisplayName(), attrType.getDisplayName(), getContentPathSafe()})); //NON-NLS
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@ -247,7 +234,7 @@ public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile
|
||||
*/
|
||||
private void updateCategory() {
|
||||
try {
|
||||
category.set(getSleuthkitCase().getContentTagsByContent(this).stream()
|
||||
category.set(getContentTags().stream()
|
||||
.map(Tag::getName).filter(CategoryManager::isCategoryTagName)
|
||||
.map(TagName::getDisplayName)
|
||||
.map(Category::fromDisplayName)
|
||||
@ -255,12 +242,16 @@ public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile
|
||||
.orElse(Category.ZERO)
|
||||
);
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.WARNING, "problem looking up category for file " + this.getName() + ex.getLocalizedMessage()); //NON-NLS
|
||||
LOGGER.log(Level.WARNING, "problem looking up category for " + this.getContentPathSafe(), ex); //NON-NLS
|
||||
} catch (IllegalStateException ex) {
|
||||
// We get here many times if the case is closed during ingest, so don't print out a ton of warnings.
|
||||
}
|
||||
}
|
||||
|
||||
private List<ContentTag> getContentTags() throws TskCoreException {
|
||||
return getSleuthkitCase().getContentTagsByContent(file);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Image getThumbnail() {
|
||||
try {
|
||||
@ -317,7 +308,7 @@ public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile
|
||||
return analyzed.get();
|
||||
}
|
||||
|
||||
public T getAbstractFile() {
|
||||
public AbstractFile getAbstractFile() {
|
||||
return this.file;
|
||||
}
|
||||
|
||||
@ -333,12 +324,16 @@ public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile
|
||||
drawablePath = StringUtils.removeEnd(getUniquePath(), getName());
|
||||
return drawablePath;
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.WARNING, "failed to get drawablePath from {0}", getName()); //NON-NLS
|
||||
LOGGER.log(Level.WARNING, "failed to get drawablePath from " + getContentPathSafe(), ex); //NON-NLS
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getHashSetNames() throws TskCoreException {
|
||||
return file.getHashSetNames();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Set<String> getHashSetNamesUnchecked() {
|
||||
try {
|
||||
@ -359,7 +354,7 @@ public abstract class DrawableFile<T extends AbstractFile> extends AbstractFile
|
||||
*/
|
||||
public String getContentPathSafe() {
|
||||
try {
|
||||
return this.getUniquePath();
|
||||
return getUniquePath();
|
||||
} catch (TskCoreException tskCoreException) {
|
||||
String contentName = this.getName();
|
||||
LOGGER.log(Level.SEVERE, "Failed to get unique path for " + contentName, tskCoreException); //NOI18N NON-NLS
|
||||
|
@ -185,21 +185,35 @@ public class DrawableTagsManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets content tags count by content.
|
||||
* Gets content tags by content.
|
||||
*
|
||||
* @param The content of interest.
|
||||
* @param content The content of interest.
|
||||
*
|
||||
* @return A list, possibly empty, of the tags that have been applied to the
|
||||
* artifact.
|
||||
* content.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
* @throws TskCoreException if there was an error reading from the db
|
||||
*/
|
||||
public List<ContentTag> getContentTagsByContent(Content content) throws TskCoreException {
|
||||
public List<ContentTag> getContentTags(Content content) throws TskCoreException {
|
||||
synchronized (autopsyTagsManagerLock) {
|
||||
return autopsyTagsManager.getContentTagsByContent(content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets content tags by DrawableFile.
|
||||
*
|
||||
* @param drawable The DrawableFile of interest.
|
||||
*
|
||||
* @return A list, possibly empty, of the tags that have been applied to the
|
||||
* DrawableFile.
|
||||
*
|
||||
* @throws TskCoreException if there was an error reading from the db
|
||||
*/
|
||||
public List<ContentTag> getContentTags(DrawableFile drawable) throws TskCoreException {
|
||||
return getContentTags(drawable.getAbstractFile());
|
||||
}
|
||||
|
||||
public TagName getTagName(String displayName) throws TskCoreException {
|
||||
synchronized (autopsyTagsManagerLock) {
|
||||
try {
|
||||
@ -213,7 +227,7 @@ public class DrawableTagsManager {
|
||||
} catch (TagsManager.TagNameAlreadyExistsException ex) {
|
||||
throw new TskCoreException("tagame exists but wasn't found", ex);
|
||||
}
|
||||
} catch (IllegalStateException ex) {
|
||||
} catch (NullPointerException | IllegalStateException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Case was closed out from underneath", ex); //NON-NLS
|
||||
throw new TskCoreException("Case was closed out from underneath", ex);
|
||||
}
|
||||
@ -228,7 +242,7 @@ public class DrawableTagsManager {
|
||||
}
|
||||
}
|
||||
|
||||
public ContentTag addContentTag(DrawableFile<?> file, TagName tagName, String comment) throws TskCoreException {
|
||||
public ContentTag addContentTag(DrawableFile file, TagName tagName, String comment) throws TskCoreException {
|
||||
synchronized (autopsyTagsManagerLock) {
|
||||
return autopsyTagsManager.addContentTag(file.getAbstractFile(), tagName, comment);
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ package org.sleuthkit.autopsy.imagegallery.datamodel;
|
||||
import java.io.IOException;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.scene.image.Image;
|
||||
import javax.imageio.ImageIO;
|
||||
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
@ -31,17 +30,12 @@ import org.sleuthkit.datamodel.AbstractFile;
|
||||
* wrapper(/decorator?/adapter?) around {@link AbstractFile} and provides
|
||||
* methods to get an thumbnail sized and a full sized {@link Image}.
|
||||
*/
|
||||
public class ImageFile<T extends AbstractFile> extends DrawableFile<T> {
|
||||
public class ImageFile extends DrawableFile {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ImageFile.class.getName());
|
||||
|
||||
static {
|
||||
ImageIO.scanForPlugins();
|
||||
}
|
||||
|
||||
ImageFile(T f, Boolean analyzed) {
|
||||
ImageFile(AbstractFile f, Boolean analyzed) {
|
||||
super(f, analyzed);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -36,13 +36,13 @@ import org.sleuthkit.autopsy.coreutils.VideoUtils;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
|
||||
public class VideoFile<T extends AbstractFile> extends DrawableFile<T> {
|
||||
public class VideoFile extends DrawableFile {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(VideoFile.class.getName());
|
||||
|
||||
private static final Image VIDEO_ICON = new Image("org/sleuthkit/autopsy/imagegallery/images/Clapperboard.png"); //NON-NLS
|
||||
|
||||
VideoFile(T file, Boolean analyzed) {
|
||||
VideoFile(AbstractFile file, Boolean analyzed) {
|
||||
super(file, analyzed);
|
||||
}
|
||||
|
||||
|
@ -170,7 +170,7 @@ public class GroupManager {
|
||||
* file is a part of
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
synchronized public Set<GroupKey<?>> getGroupKeysForFile(DrawableFile<?> file) {
|
||||
synchronized public Set<GroupKey<?>> getGroupKeysForFile(DrawableFile file) {
|
||||
Set<GroupKey<?>> resultSet = new HashSet<>();
|
||||
for (Comparable<?> val : groupBy.getValue(file)) {
|
||||
if (groupBy == DrawableAttribute.TAGS) {
|
||||
@ -194,7 +194,7 @@ public class GroupManager {
|
||||
synchronized public Set<GroupKey<?>> getGroupKeysForFileID(Long fileID) {
|
||||
try {
|
||||
if (nonNull(db)) {
|
||||
DrawableFile<?> file = db.getFileFromID(fileID);
|
||||
DrawableFile file = db.getFileFromID(fileID);
|
||||
return getGroupKeysForFile(file);
|
||||
} else {
|
||||
Logger.getLogger(GroupManager.class.getName()).log(Level.WARNING, "Failed to load file with id: {0} from database. There is no database assigned.", fileID); //NON-NLS
|
||||
|
@ -1,16 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import java.lang.*?>
|
||||
<?import javafx.geometry.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.image.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.ProgressBar?>
|
||||
<?import javafx.scene.image.Image?>
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.BorderPane?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.StackPane?>
|
||||
|
||||
<fx:root id="AnchorPane" maxHeight="-Infinity" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" type="javafx.scene.layout.AnchorPane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<fx:root id="AnchorPane" maxHeight="-Infinity" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" type="javafx.scene.layout.AnchorPane" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<children>
|
||||
<BorderPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<right>
|
||||
<HBox alignment="CENTER_RIGHT" prefHeight="-1.0" prefWidth="-1.0" BorderPane.alignment="CENTER_RIGHT">
|
||||
<HBox alignment="CENTER_RIGHT" prefHeight="-1.0" prefWidth="-1.0" spacing="5.0" BorderPane.alignment="CENTER_RIGHT">
|
||||
<children>
|
||||
<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" HBox.hgrow="NEVER">
|
||||
<children>
|
||||
@ -18,7 +22,10 @@
|
||||
<Label id="fileUpdateLabel" fx:id="fileUpdateTaskLabel" alignment="CENTER" contentDisplay="CENTER" graphicTextGap="0.0" labelFor="$fileTaskProgresBar" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="-1.0" text="0 File Update Tasks" StackPane.alignment="CENTER">
|
||||
<StackPane.margin>
|
||||
<Insets left="3.0" right="3.0" />
|
||||
</StackPane.margin></Label>
|
||||
</StackPane.margin>
|
||||
<padding>
|
||||
<Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
|
||||
</padding></Label>
|
||||
</children>
|
||||
<HBox.margin>
|
||||
<Insets />
|
||||
@ -27,10 +34,13 @@
|
||||
<StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="-1.0" prefWidth="-1.0" HBox.hgrow="NEVER">
|
||||
<children>
|
||||
<ProgressBar fx:id="bgTaskProgressBar" maxHeight="-1.0" maxWidth="-1.0" minHeight="-Infinity" minWidth="-1.0" prefHeight="24.0" prefWidth="-1.0" progress="0.0" StackPane.alignment="CENTER" />
|
||||
<Label fx:id="bgTaskLabel" alignment="CENTER" cache="false" contentDisplay="CENTER" disable="false" focusTraversable="false" labelFor="$uiTaskProgressBar" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" text="" StackPane.alignment="CENTER">
|
||||
<Label fx:id="bgTaskLabel" alignment="CENTER" cache="false" contentDisplay="CENTER" disable="false" focusTraversable="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" text="" StackPane.alignment="CENTER">
|
||||
<StackPane.margin>
|
||||
<Insets left="3.0" right="3.0" />
|
||||
</StackPane.margin></Label>
|
||||
</StackPane.margin>
|
||||
<padding>
|
||||
<Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
|
||||
</padding></Label>
|
||||
</children>
|
||||
<HBox.margin>
|
||||
<Insets right="5.0" />
|
||||
@ -42,19 +52,6 @@
|
||||
</BorderPane.margin>
|
||||
</HBox>
|
||||
</right>
|
||||
<center>
|
||||
<HBox>
|
||||
<children>
|
||||
<Label fx:id="statusLabel" maxWidth="-Infinity" minWidth="-Infinity" wrapText="true" BorderPane.alignment="CENTER" HBox.hgrow="ALWAYS">
|
||||
<BorderPane.margin>
|
||||
<Insets left="10.0" right="10.0" />
|
||||
</BorderPane.margin>
|
||||
<HBox.margin>
|
||||
<Insets left="10.0" right="10.0" />
|
||||
</HBox.margin></Label>
|
||||
</children>
|
||||
</HBox>
|
||||
</center>
|
||||
<left><Label fx:id="staleLabel" text="Some data may be out of date. Enable listening to ingest to update." BorderPane.alignment="CENTER">
|
||||
<graphic><ImageView fitHeight="16.0" fitWidth="16.0" pickOnBounds="true" preserveRatio="true">
|
||||
<image>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-14 Basis Technology Corp.
|
||||
* Copyright 2013-16 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,8 +19,6 @@
|
||||
package org.sleuthkit.autopsy.imagegallery.gui;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
@ -38,21 +36,12 @@ public class StatusBar extends AnchorPane {
|
||||
|
||||
private final ImageGalleryController controller;
|
||||
|
||||
@FXML
|
||||
private ResourceBundle resources;
|
||||
|
||||
@FXML
|
||||
private URL location;
|
||||
|
||||
@FXML
|
||||
private ProgressBar fileTaskProgresBar;
|
||||
|
||||
@FXML
|
||||
private Label fileUpdateTaskLabel;
|
||||
|
||||
@FXML
|
||||
private Label statusLabel;
|
||||
|
||||
@FXML
|
||||
private Label bgTaskLabel;
|
||||
|
||||
@ -69,18 +58,11 @@ public class StatusBar extends AnchorPane {
|
||||
void initialize() {
|
||||
assert fileTaskProgresBar != null : "fx:id=\"fileTaskProgresBar\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
||||
assert fileUpdateTaskLabel != null : "fx:id=\"fileUpdateTaskLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
||||
assert statusLabel != null : "fx:id=\"statusLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
||||
assert bgTaskLabel != null : "fx:id=\"bgTaskLabel\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
||||
assert bgTaskProgressBar != null : "fx:id=\"bgTaskProgressBar\" was not injected: check your FXML file 'StatusBar.fxml'.";
|
||||
|
||||
fileUpdateTaskLabel.textProperty().bind(controller.getFileUpdateQueueSizeProperty().asString().concat(Bundle.StatusBar_fileUpdateTaskLabel_text()));//;setText(newSize.toString() + " File Update Tasks");
|
||||
fileTaskProgresBar.progressProperty().bind(controller.getFileUpdateQueueSizeProperty().negate());
|
||||
// controller.getFileUpdateQueueSizeProperty().addListener((ov, oldSize, newSize) -> {
|
||||
// Platform.runLater(() -> {
|
||||
//
|
||||
//
|
||||
// });
|
||||
// });
|
||||
fileUpdateTaskLabel.textProperty().bind(controller.getDBTasksQueueSizeProperty().asString().concat(Bundle.StatusBar_fileUpdateTaskLabel_text()));
|
||||
fileTaskProgresBar.progressProperty().bind(controller.getDBTasksQueueSizeProperty().negate());
|
||||
|
||||
controller.regroupProgress().addListener((ov, oldSize, newSize) -> {
|
||||
Platform.runLater(() -> {
|
||||
@ -96,10 +78,7 @@ public class StatusBar extends AnchorPane {
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Platform.runLater(() -> {
|
||||
staleLabel.setTooltip(new Tooltip(Bundle.StatuBar_toolTip()));
|
||||
});
|
||||
Platform.runLater(() -> staleLabel.setTooltip(new Tooltip(Bundle.StatuBar_toolTip())));
|
||||
staleLabel.visibleProperty().bind(controller.stale());
|
||||
}
|
||||
|
||||
@ -116,14 +95,4 @@ public class StatusBar extends AnchorPane {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setLabelText(final String newText) {
|
||||
Platform.runLater(() -> {
|
||||
statusLabel.setText(newText);
|
||||
});
|
||||
}
|
||||
|
||||
public String getLabeltext() {
|
||||
return statusLabel.getText();
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ import javafx.application.Platform;
|
||||
import javafx.beans.InvalidationListener;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.beans.property.DoubleProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.ComboBox;
|
||||
@ -35,8 +34,6 @@ import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.control.Slider;
|
||||
import javafx.scene.control.SplitMenuButton;
|
||||
import javafx.scene.control.ToolBar;
|
||||
import javax.swing.SortOrder;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
|
||||
@ -74,8 +71,6 @@ public class Toolbar extends ToolBar {
|
||||
@FXML
|
||||
private Label groupByLabel;
|
||||
|
||||
|
||||
|
||||
@FXML
|
||||
private Label tagImageViewLabel;
|
||||
|
||||
@ -85,10 +80,6 @@ public class Toolbar extends ToolBar {
|
||||
@FXML
|
||||
private Label thumbnailSizeLabel;
|
||||
|
||||
private static Toolbar instance;
|
||||
|
||||
private final SimpleObjectProperty<SortOrder> orderProperty = new SimpleObjectProperty<>(SortOrder.ASCENDING);
|
||||
|
||||
private final ImageGalleryController controller;
|
||||
private SortChooser<DrawableGroup, GroupSortBy> sortChooser;
|
||||
|
||||
@ -102,17 +93,10 @@ public class Toolbar extends ToolBar {
|
||||
}
|
||||
};
|
||||
|
||||
public DoubleProperty sizeSliderValue() {
|
||||
public DoubleProperty thumbnailSizeProperty() {
|
||||
return sizeSlider.valueProperty();
|
||||
}
|
||||
|
||||
static synchronized public Toolbar getDefault(ImageGalleryController controller) {
|
||||
if (instance == null) {
|
||||
instance = new Toolbar(controller);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@FXML
|
||||
@NbBundle.Messages({"Toolbar.groupByLabel=Group By:",
|
||||
"Toolbar.sortByLabel=Sort By:",
|
||||
@ -148,11 +132,6 @@ public class Toolbar extends ToolBar {
|
||||
}
|
||||
});
|
||||
|
||||
groupByLabel.setText(Bundle.Toolbar_groupByLabel());
|
||||
tagImageViewLabel.setText(Bundle.Toolbar_tagImageViewLabel());
|
||||
categoryImageViewLabel.setText(Bundle.Toolbar_categoryImageViewLabel());
|
||||
thumbnailSizeLabel.setText(Bundle.Toolbar_thumbnailSizeLabel());
|
||||
|
||||
CategorizeGroupAction cat5GroupAction = new CategorizeGroupAction(Category.FIVE, controller);
|
||||
catGroupMenuButton.setOnAction(cat5GroupAction);
|
||||
catGroupMenuButton.setText(cat5GroupAction.getText());
|
||||
@ -165,6 +144,11 @@ public class Toolbar extends ToolBar {
|
||||
}
|
||||
});
|
||||
|
||||
groupByLabel.setText(Bundle.Toolbar_groupByLabel());
|
||||
tagImageViewLabel.setText(Bundle.Toolbar_tagImageViewLabel());
|
||||
categoryImageViewLabel.setText(Bundle.Toolbar_categoryImageViewLabel());
|
||||
thumbnailSizeLabel.setText(Bundle.Toolbar_thumbnailSizeLabel());
|
||||
|
||||
groupByBox.setItems(FXCollections.observableList(DrawableAttribute.getGroupableAttrs()));
|
||||
groupByBox.getSelectionModel().select(DrawableAttribute.PATH);
|
||||
groupByBox.getSelectionModel().selectedItemProperty().addListener(queryInvalidationListener);
|
||||
@ -182,8 +166,6 @@ public class Toolbar extends ToolBar {
|
||||
queryInvalidationListener.invalidated(observable);
|
||||
});
|
||||
|
||||
|
||||
|
||||
sortChooser.sortOrderProperty().addListener(queryInvalidationListener);
|
||||
sortChooser.setComparator(GroupSortBy.PRIORITY);
|
||||
getItems().add(1, sortChooser);
|
||||
@ -202,13 +184,11 @@ public class Toolbar extends ToolBar {
|
||||
public void reset() {
|
||||
Platform.runLater(() -> {
|
||||
groupByBox.getSelectionModel().select(DrawableAttribute.PATH);
|
||||
// sortByBox.getSelectionModel().select(GroupSortBy.NONE);
|
||||
// orderGroup.selectToggle(ascRadio);
|
||||
sizeSlider.setValue(SIZE_SLIDER_DEFAULT);
|
||||
});
|
||||
}
|
||||
|
||||
private Toolbar(ImageGalleryController controller) {
|
||||
public Toolbar(ImageGalleryController controller) {
|
||||
this.controller = controller;
|
||||
FXMLConstructor.construct(this, "Toolbar.fxml"); //NON-NLS
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ public class VideoPlayer extends BorderPane {
|
||||
mp.seek(Duration.millis(timeSlider.getValue()));
|
||||
}
|
||||
};
|
||||
private final VideoFile<?> file;
|
||||
private final VideoFile file;
|
||||
|
||||
@FXML
|
||||
@NbBundle.Messages({"# {0} - exception type",
|
||||
@ -236,7 +236,7 @@ public class VideoPlayer extends BorderPane {
|
||||
}
|
||||
}
|
||||
|
||||
public VideoPlayer(MediaPlayer mp, VideoFile<?> file) {
|
||||
public VideoPlayer(MediaPlayer mp, VideoFile file) {
|
||||
this.file = file;
|
||||
this.mp = mp;
|
||||
FXMLConstructor.construct(this, "MediaControl.fxml"); //NON-NLS
|
||||
|
@ -31,13 +31,10 @@ import javafx.scene.image.Image;
|
||||
import javafx.scene.input.MouseButton;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.paint.Color;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
|
||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||
import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile;
|
||||
import org.sleuthkit.autopsy.imagegallery.gui.Toolbar;
|
||||
import org.sleuthkit.datamodel.AbstractContent;
|
||||
|
||||
/**
|
||||
* GUI component that represents a single image as a tile with an icon, a label,
|
||||
@ -66,8 +63,8 @@ public class DrawableTile extends DrawableTileBase {
|
||||
setCache(true);
|
||||
setCacheHint(CacheHint.SPEED);
|
||||
nameLabel.prefWidthProperty().bind(imageView.fitWidthProperty());
|
||||
imageView.fitHeightProperty().bind(Toolbar.getDefault(getController()).sizeSliderValue());
|
||||
imageView.fitWidthProperty().bind(Toolbar.getDefault(getController()).sizeSliderValue());
|
||||
imageView.fitHeightProperty().bind(getController().thumbnailSizeProperty());
|
||||
imageView.fitWidthProperty().bind(getController().thumbnailSizeProperty());
|
||||
|
||||
selectionModel.lastSelectedProperty().addListener(new WeakChangeListener<>(lastSelectionListener));
|
||||
|
||||
@ -108,12 +105,12 @@ public class DrawableTile extends DrawableTileBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
Task<Image> newReadImageTask(DrawableFile<?> file) {
|
||||
Task<Image> newReadImageTask(DrawableFile file) {
|
||||
return file.getThumbnailTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTextForLabel() {
|
||||
return getFile().map(AbstractContent::getName).orElse("");
|
||||
return getFile().map(DrawableFile::getName).orElse("");
|
||||
}
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ public abstract class DrawableTileBase extends DrawableUIBase {
|
||||
t.consume();
|
||||
}
|
||||
|
||||
private ContextMenu buildContextMenu(DrawableFile<?> file) {
|
||||
private ContextMenu buildContextMenu(DrawableFile file) {
|
||||
final ArrayList<MenuItem> menuItems = new ArrayList<>();
|
||||
|
||||
menuItems.add(CategorizeAction.getCategoriesMenu(getController()));
|
||||
|
@ -66,7 +66,7 @@ abstract public class DrawableUIBase extends AnchorPane implements DrawableView
|
||||
|
||||
private final ImageGalleryController controller;
|
||||
|
||||
private Optional<DrawableFile<?>> fileOpt = Optional.empty();
|
||||
private Optional<DrawableFile> fileOpt = Optional.empty();
|
||||
|
||||
private Optional<Long> fileIDOpt = Optional.empty();
|
||||
private volatile Task<Image> imageTask;
|
||||
@ -89,12 +89,12 @@ abstract public class DrawableUIBase extends AnchorPane implements DrawableView
|
||||
this.fileIDOpt = fileIDOpt;
|
||||
}
|
||||
|
||||
synchronized void setFileOpt(Optional<DrawableFile<?>> fileOpt) {
|
||||
synchronized void setFileOpt(Optional<DrawableFile> fileOpt) {
|
||||
this.fileOpt = fileOpt;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public Optional<DrawableFile<?>> getFile() {
|
||||
synchronized public Optional<DrawableFile> getFile() {
|
||||
if (fileIDOpt.isPresent()) {
|
||||
if (fileOpt.isPresent() && fileOpt.get().getId() == fileIDOpt.get()) {
|
||||
return fileOpt;
|
||||
@ -131,7 +131,7 @@ abstract public class DrawableUIBase extends AnchorPane implements DrawableView
|
||||
}
|
||||
}
|
||||
|
||||
synchronized Node doReadImageTask(DrawableFile<?> file) {
|
||||
synchronized Node doReadImageTask(DrawableFile file) {
|
||||
Task<Image> myTask = newReadImageTask(file);
|
||||
imageTask = myTask;
|
||||
Node progressNode = newProgressIndicator(myTask);
|
||||
@ -191,7 +191,7 @@ abstract public class DrawableUIBase extends AnchorPane implements DrawableView
|
||||
}
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
private void showImage(DrawableFile<?> file, Task<Image> imageTask) {
|
||||
private void showImage(DrawableFile file, Task<Image> imageTask) {
|
||||
//Note that all error conditions are allready logged in readImageTask.succeeded()
|
||||
try {
|
||||
Image fxImage = imageTask.get();
|
||||
@ -210,7 +210,7 @@ abstract public class DrawableUIBase extends AnchorPane implements DrawableView
|
||||
}
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
void showErrorNode(String errorMessage, DrawableFile<?> file) {
|
||||
void showErrorNode(String errorMessage, DrawableFile file) {
|
||||
Button createButton = ActionUtils.createButton(new OpenExternalViewerAction(file));
|
||||
|
||||
VBox vBox = new VBox(10, new Label(errorMessage), createButton);
|
||||
@ -218,5 +218,5 @@ abstract public class DrawableUIBase extends AnchorPane implements DrawableView
|
||||
imageBorder.setCenter(vBox);
|
||||
}
|
||||
|
||||
abstract Task<Image> newReadImageTask(DrawableFile<?> file);
|
||||
abstract Task<Image> newReadImageTask(DrawableFile file);
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public interface DrawableView {
|
||||
|
||||
Region getCategoryBorderRegion();
|
||||
|
||||
Optional<DrawableFile<?>> getFile();
|
||||
Optional<DrawableFile> getFile();
|
||||
|
||||
void setFile(final Long fileID);
|
||||
|
||||
|
@ -128,7 +128,6 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.DrawableGroup;
|
||||
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupViewMode;
|
||||
import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupViewState;
|
||||
import org.sleuthkit.autopsy.imagegallery.gui.GuiUtils;
|
||||
import org.sleuthkit.autopsy.imagegallery.gui.Toolbar;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
@ -308,7 +307,7 @@ public class GroupPane extends BorderPane {
|
||||
|
||||
}
|
||||
|
||||
void syncCatToggle(DrawableFile<?> file) {
|
||||
void syncCatToggle(DrawableFile file) {
|
||||
getToggleForCategory(file.getCategory()).setSelected(true);
|
||||
}
|
||||
|
||||
@ -418,7 +417,7 @@ public class GroupPane extends BorderPane {
|
||||
flashAnimation.setAutoReverse(true);
|
||||
|
||||
//configure gridView cell properties
|
||||
DoubleBinding cellSize = Toolbar.getDefault(controller).sizeSliderValue().add(75);
|
||||
DoubleBinding cellSize = controller.thumbnailSizeProperty().add(75);
|
||||
gridView.cellHeightProperty().bind(cellSize);
|
||||
gridView.cellWidthProperty().bind(cellSize);
|
||||
gridView.setCellFactory((GridView<Long> param) -> new DrawableCell());
|
||||
|
@ -201,7 +201,7 @@ public class MetaDataPane extends DrawableUIBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
Task<Image> newReadImageTask(DrawableFile<?> file) {
|
||||
Task<Image> newReadImageTask(DrawableFile file) {
|
||||
return file.getThumbnailTask();
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,6 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.VideoFile;
|
||||
import org.sleuthkit.autopsy.imagegallery.gui.VideoPlayer;
|
||||
import static org.sleuthkit.autopsy.imagegallery.gui.drawableviews.DrawableUIBase.exec;
|
||||
import static org.sleuthkit.autopsy.imagegallery.gui.drawableviews.DrawableView.CAT_BORDER_WIDTH;
|
||||
import org.sleuthkit.datamodel.AbstractContent;
|
||||
|
||||
/**
|
||||
* Displays the files of a group one at a time. Designed to be embedded in a
|
||||
@ -186,16 +185,16 @@ public class SlideShowView extends DrawableTileBase {
|
||||
synchronized protected void updateContent() {
|
||||
disposeContent();
|
||||
if (getFile().isPresent()) {
|
||||
DrawableFile<?> file = getFile().get();
|
||||
DrawableFile file = getFile().get();
|
||||
if (file.isVideo()) {
|
||||
doMediaLoadTask((VideoFile<?>) file);
|
||||
doMediaLoadTask((VideoFile) file);
|
||||
} else {
|
||||
doReadImageTask(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized private Node doMediaLoadTask(VideoFile<?> file) {
|
||||
synchronized private Node doMediaLoadTask(VideoFile file) {
|
||||
|
||||
//specially handling for videos
|
||||
MediaLoadTask myTask = new MediaLoadTask(file);
|
||||
@ -225,7 +224,7 @@ public class SlideShowView extends DrawableTileBase {
|
||||
}
|
||||
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.JFX)
|
||||
private void showMedia(DrawableFile<?> file, Task<Node> mediaTask) {
|
||||
private void showMedia(DrawableFile file, Task<Node> mediaTask) {
|
||||
//Note that all error conditions are allready logged in readImageTask.succeeded()
|
||||
try {
|
||||
Node mediaNode = mediaTask.get();
|
||||
@ -265,7 +264,7 @@ public class SlideShowView extends DrawableTileBase {
|
||||
*/
|
||||
@Override
|
||||
protected String getTextForLabel() {
|
||||
return getFile().map(AbstractContent::getName).orElse("") + " " + getSupplementalText();
|
||||
return getFile().map(DrawableFile::getName).orElse("") + " " + getSupplementalText();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -308,7 +307,7 @@ public class SlideShowView extends DrawableTileBase {
|
||||
@Override
|
||||
@ThreadConfined(type = ThreadType.ANY)
|
||||
public Category updateCategory() {
|
||||
Optional<DrawableFile<?>> file = getFile();
|
||||
Optional<DrawableFile> file = getFile();
|
||||
if (file.isPresent()) {
|
||||
Category updateCategory = super.updateCategory();
|
||||
Platform.runLater(() -> getGroupPane().syncCatToggle(file.get()));
|
||||
@ -319,7 +318,7 @@ public class SlideShowView extends DrawableTileBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
Task<Image> newReadImageTask(DrawableFile<?> file) {
|
||||
Task<Image> newReadImageTask(DrawableFile file) {
|
||||
return file.getReadFullSizeImageTask();
|
||||
|
||||
}
|
||||
@ -328,9 +327,9 @@ public class SlideShowView extends DrawableTileBase {
|
||||
"MediaLoadTask.messageText=Reading video: {0}"})
|
||||
private class MediaLoadTask extends Task<Node> {
|
||||
|
||||
private final VideoFile<?> file;
|
||||
private final VideoFile file;
|
||||
|
||||
MediaLoadTask(VideoFile<?> file) {
|
||||
MediaLoadTask(VideoFile file) {
|
||||
updateMessage(Bundle.MediaLoadTask_messageText(file.getName()));
|
||||
this.file = file;
|
||||
}
|
||||
|
@ -274,9 +274,10 @@ public class ExtractedContentViewer implements DataContentViewer {
|
||||
} else {
|
||||
try {
|
||||
// Get the associated artifact attribute and return its value as the ID
|
||||
List<BlackboardAttribute> blackboardAttributes = artifact.getAttributes(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT);
|
||||
if (!blackboardAttributes.isEmpty()) {
|
||||
return blackboardAttributes.get(0).getValueLong();
|
||||
BlackboardAttribute blackboardAttribute = artifact.getAttribute(
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
|
||||
if (blackboardAttribute != null) {
|
||||
return blackboardAttribute.getValueLong();
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error getting associated artifact attributes", ex); //NON-NLS
|
||||
|
@ -52,12 +52,12 @@ class KeywordCachedArtifact {
|
||||
}
|
||||
|
||||
void add(BlackboardAttribute attribute) {
|
||||
attributes.put(attribute.getAttributeTypeID(), attribute);
|
||||
attributes.put(attribute.getAttributeType().getTypeID(), attribute);
|
||||
}
|
||||
|
||||
void add(Collection<BlackboardAttribute> attributes) {
|
||||
for (BlackboardAttribute attr : attributes) {
|
||||
this.attributes.put(attr.getAttributeTypeID(), attr);
|
||||
this.attributes.put(attr.getAttributeType().getTypeID(), attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user