1
0
mirror of https://github.com/elisspace/autopsy.git synced 2026-09-06 02:24:30 +00:00

Merge remote-tracking branch 'upstream/develop' into jython_ingest_modules

This commit is contained in:
Richard Cordovano
2014-08-11 15:20:31 -04:00
21 changed files with 210 additions and 165 deletions

View File

@@ -135,39 +135,29 @@ import org.sleuthkit.datamodel.TskException;
* @throws Exception
*/
@Override
public void run() {
errorList.clear();
//lock DB for writes in this thread
SleuthkitCase.acquireExclusiveLock();
addImageProcess = currentCase.makeAddImageProcess(timeZone, true, noFatOrphans);
dirFetcher = new Thread( new CurrentDirectoryFetcher(progressMonitor, addImageProcess));
public void run() {
errorList.clear();
try {
progressMonitor.setIndeterminate(true);
progressMonitor.setProgress(0);
dirFetcher.start();
addImageProcess.run(new String[]{this.imagePath});
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Core errors occurred while running add image. ", ex); //NON-NLS
//critical core/system error and process needs to be interrupted
hasCritError = true;
errorList.add(ex.getMessage());
} catch (TskDataException ex) {
logger.log(Level.WARNING, "Data errors occurred while running add image. ", ex); //NON-NLS
errorList.add(ex.getMessage());
}
// handle addImage done
postProcess();
// unclock the DB
SleuthkitCase.releaseExclusiveLock();
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(new String[]{this.imagePath});
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Core errors occurred while running add image. ", ex); //NON-NLS
hasCritError = true;
errorList.add(ex.getMessage());
} catch (TskDataException ex) {
logger.log(Level.WARNING, "Data errors occurred while running add image. ", ex); //NON-NLS
errorList.add(ex.getMessage());
}
postProcess();
} finally {
currentCase.getSleuthkitCase().releaseExclusiveLock();
}
}
/**

View File

@@ -140,6 +140,9 @@ public class Case implements SleuthkitCase.ErrorObserver {
private static final Logger logger = Logger.getLogger(Case.class.getName());
static final String CASE_EXTENSION = "aut"; //NON-NLS
static final String CASE_DOT_EXTENSION = "." + CASE_EXTENSION;
// we cache if the case has data in it yet since a few places ask for it and we dont' need to keep going to DB
private boolean hasData = false;
/**
* Constructor for the Case class
@@ -795,11 +798,14 @@ public class Case implements SleuthkitCase.ErrorObserver {
*/
public Long[] getImageIDs() {
Set<Long> ids = getImagePaths(db).keySet();
hasData = (ids.size() > 0);
return ids.toArray(new Long[ids.size()]);
}
public List<Image> getImages() throws TskCoreException {
return db.getImages();
List<Image> list = db.getImages();
hasData = (list.size() > 0);
return list;
}
/**
@@ -818,7 +824,9 @@ public class Case implements SleuthkitCase.ErrorObserver {
*/
public List<Content> getRootObjects() {
try {
return db.getRootObjects();
List<Content> list = db.getRootObjects();
hasData = (list.size() > 0);
return list;
} catch (TskException ex) {
throw new RuntimeException(NbBundle.getMessage(this.getClass(), "Case.exception.errGetRootObj"), ex);
}
@@ -1113,7 +1121,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true);
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true); // Delete Case menu
if (toChangeTo.getRootObjectsCount() > 0) {
if (toChangeTo.hasData()) {
// open all top components
CoreComponentControl.openCoreWindows();
} else {
@@ -1160,7 +1168,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
//delete image helper
private void doDeleteImage() {
// no more image left in this case
if (currentCase.getRootObjectsCount() == 0) {
if (currentCase.hasData()) {
// close all top components
CoreComponentControl.closeCoreWindows();
}
@@ -1193,4 +1201,16 @@ public class Case implements SleuthkitCase.ErrorObserver {
public List<Report> getAllReports() throws TskCoreException {
return this.db.getAllReports();
}
/**
* Returns if the case has data in it yet.
* @return
*/
public boolean hasData() {
// false is also the initial value, so make the DB trip if it is still false
if (!hasData) {
hasData = (getRootObjectsCount() > 0);
}
return hasData;
}
}

View File

@@ -27,7 +27,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
@@ -36,13 +35,13 @@ import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.DerivedFile;
import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.VirtualDirectory;
import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.Transaction;
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskFileRange;
import org.sleuthkit.datamodel.VirtualDirectory;
/**
* Abstraction to facilitate access to files and directories.
@@ -267,7 +266,7 @@ public class FileManager implements Closeable {
rootsToAdd.add(localFile);
}
Transaction trans = tskCase.createTransaction();
CaseDbTransaction trans = tskCase.beginTransaction();
// make a virtual top-level directory for this set of files/dirs
final VirtualDirectory fileSetRootDir = addLocalFileSetRootDir(trans);
@@ -295,8 +294,6 @@ public class FileManager implements Closeable {
trans.commit();
} catch (TskCoreException ex) {
trans.rollback();
} finally {
trans.close();
}
return fileSetRootDir;
}
@@ -309,7 +306,7 @@ public class FileManager implements Closeable {
*
* @throws TskCoreException
*/
private VirtualDirectory addLocalFileSetRootDir(Transaction trans) throws TskCoreException {
private VirtualDirectory addLocalFileSetRootDir(CaseDbTransaction trans) throws TskCoreException {
VirtualDirectory created = null;
@@ -343,7 +340,7 @@ public class FileManager implements Closeable {
* directory.
* @throws TskCoreException
*/
private AbstractFile addLocalDirInt(Transaction trans, VirtualDirectory parentVd,
private AbstractFile addLocalDirInt(CaseDbTransaction trans, VirtualDirectory parentVd,
java.io.File localFile, FileAddProgressUpdater addProgressUpdater) throws TskCoreException {
if (tskCase == null) {
@@ -399,7 +396,7 @@ public class FileManager implements Closeable {
* due to a critical system error or of the file
* manager has already been closed
*/
private synchronized LocalFile addLocalFileInt(AbstractFile parentFile, java.io.File localFile, Transaction trans) throws TskCoreException {
private synchronized LocalFile addLocalFileInt(AbstractFile parentFile, java.io.File localFile, CaseDbTransaction trans) throws TskCoreException {
if (tskCase == null) {
throw new TskCoreException(

View File

@@ -166,7 +166,7 @@ public final class DataContentTopComponent extends TopComponent implements DataC
@Override
public boolean canClose() {
return (!this.isDefault) || !Case.existsCurrentCase() || Case.getCurrentCase().getRootObjectsCount() == 0; // only allow this window to be closed when there's no case opened or no image in this case
return (!this.isDefault) || !Case.existsCurrentCase() || Case.getCurrentCase().hasData() == false; // only allow this window to be closed when there's no case opened or no image in this case
}
@Override

View File

@@ -457,7 +457,7 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
}
public boolean canClose() {
return (!this.isMain) || !Case.existsCurrentCase() || Case.getCurrentCase().getRootObjectsCount() == 0; // only allow this window to be closed when there's no case opened or no image in this case
return (!this.isMain) || !Case.existsCurrentCase() || Case.getCurrentCase().hasData() == false; // only allow this window to be closed when there's no case opened or no image in this case
}
@Override

View File

@@ -298,7 +298,7 @@ public class DataResultTopComponent extends TopComponent implements DataResult,
@Override
public boolean canClose() {
return (!this.isMain) || !Case.existsCurrentCase() || Case.getCurrentCase().getRootObjectsCount() == 0; // only allow this window to be closed when there's no case opened or no image in this case
return (!this.isMain) || !Case.existsCurrentCase() || Case.getCurrentCase().hasData() == false; // only allow this window to be closed when there's no case opened or no image in this case
}
/**

View File

@@ -299,14 +299,7 @@ import org.sleuthkit.datamodel.TskCoreException;
if (selectedNode == null) {
return false;
}
Children ch = selectedNode.getChildren();
for (Node n : ch.getNodes()) {
if (ThumbnailViewChildren.isSupported(n)) {
return true;
}
}
return false;
return true;
}
@Override

View File

@@ -58,6 +58,16 @@ ContentTagNode.createSheet.filePath.name=File Path
ContentTagNode.createSheet.filePath.displayName=File Path
ContentTagNode.createSheet.comment.name=Comment
ContentTagNode.createSheet.comment.displayName=Comment
ContentTagNode.createSheet.fileModifiedTime.name=Modified Time
ContentTagNode.createSheet.fileModifiedTime.displayName=Modified Time
ContentTagNode.createSheet.fileChangedTime.name=Changed Time
ContentTagNode.createSheet.fileChangedTime.displayName=Changed Time
ContentTagNode.createSheet.fileAccessedTime.name=Accessed Time
ContentTagNode.createSheet.fileAccessedTime.displayName=Accessed Time
ContentTagNode.createSheet.fileCreatedTime.name=Created Time
ContentTagNode.createSheet.fileCreatedTime.displayName=Created Time
ContentTagNode.createSheet.fileSize.name=Size
ContentTagNode.createSheet.fileSize.displayName=Size
ContentTagTypeNode.displayName.text=File Tags
ContentTagTypeNode.createSheet.name.name=Name
ContentTagTypeNode.createSheet.name.displayName=Name

View File

@@ -20,13 +20,15 @@ package org.sleuthkit.autopsy.datamodel;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.Action;
import org.openide.nodes.Children;
import org.openide.nodes.Sheet;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.actions.DeleteContentTagAction;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.TskCoreException;
@@ -51,24 +53,26 @@ class ContentTagNode extends DisplayableItemNode {
@Override
protected Sheet createSheet() {
Content content = tag.getContent();
String contentPath;
try {
contentPath = content.getUniquePath();
} catch (TskCoreException ex) {
Logger.getLogger(ContentTagNode.class.getName()).log(Level.SEVERE, "Failed to get path for content (id = " + content.getId() + ")", ex); //NON-NLS
contentPath = NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.unavail.path");
}
AbstractFile file = content instanceof AbstractFile ? (AbstractFile)content : null;
Sheet propertySheet = super.createSheet();
Sheet.Set properties = propertySheet.get(Sheet.PROPERTIES);
if (properties == null) {
properties = Sheet.createPropertiesSet();
propertySheet.put(properties);
}
properties.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.file.name"),
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.file.displayName"),
"",
tag.getContent().getName()));
String contentPath;
try {
contentPath = tag.getContent().getUniquePath();
} catch (TskCoreException ex) {
Logger.getLogger(ContentTagNode.class.getName()).log(Level.SEVERE, "Failed to get path for content (id = " + tag.getContent().getId() + ")", ex); //NON-NLS
contentPath = NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.unavail.path");
}
content.getName()));
properties.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.filePath.name"),
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.filePath.displayName"),
"",
@@ -77,7 +81,26 @@ class ContentTagNode extends DisplayableItemNode {
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.comment.displayName"),
"",
tag.getComment()));
properties.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileModifiedTime.name"),
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileModifiedTime.displayName"),
"",
file != null ? ContentUtils.getStringTime(file.getMtime(), file) : ""));
properties.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileChangedTime.name"),
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileChangedTime.displayName"),
"",
file != null ? ContentUtils.getStringTime(file.getCtime(), file) : ""));
properties.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileAccessedTime.name"),
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileAccessedTime.displayName"),
"",
file != null ? ContentUtils.getStringTime(file.getAtime(), file) : ""));
properties.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileCreatedTime.name"),
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileCreatedTime.displayName"),
"",
file != null ? ContentUtils.getStringTime(file.getCrtime(), file) : ""));
properties.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileSize.name"),
NbBundle.getMessage(this.getClass(), "ContentTagNode.createSheet.fileSize.displayName"),
"",
content.getSize()));
return propertySheet;
}

View File

@@ -226,6 +226,7 @@ public class DeletedContent implements AutopsyVisitableItem {
protected boolean createKeys(List<AbstractFile> list) {
List<AbstractFile> queryList = runFsQuery();
if (queryList.size() == MAX_OBJECTS) {
queryList.remove(queryList.size() - 1);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
@@ -235,8 +236,6 @@ public class DeletedContent implements AutopsyVisitableItem {
}
});
}
queryList.remove(queryList.size() - 1);
list.addAll(queryList);
return true;
}

View File

@@ -349,7 +349,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
Case currentCase = Case.getCurrentCase();
// close the top component if there's no image in this case
if (currentCase.getRootObjectsCount() == 0) {
if (currentCase.hasData() == false) {
//this.close();
((BeanTreeView) this.jScrollPane1).setRootVisible(false); // hide the root
} else {
@@ -483,7 +483,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
@Override
public boolean canClose() {
return !Case.existsCurrentCase() || Case.getCurrentCase().getRootObjectsCount() == 0; // only allow this window to be closed when there's no case opened or no image in this case
return !Case.existsCurrentCase() || Case.getCurrentCase().hasData() == false; // only allow this window to be closed when there's no case opened or no image in this case
}
/**

View File

@@ -19,9 +19,7 @@
package org.sleuthkit.autopsy.ingest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.sleuthkit.datamodel.AbstractFile;
/**
@@ -112,7 +110,7 @@ final class FileIngestPipeline {
}
file.close();
if (!context.isJobCancelled()) {
IngestManager.getInstance().fireFileIngestDone(file.getId());
IngestManager.getInstance().fireFileIngestDone(file);
}
ingestManager.setIngestTaskProgressCompleted(task);
return errors;

View File

@@ -193,46 +193,54 @@ final class IngestJob {
}
void process(DataSourceIngestTask task) throws InterruptedException {
if (!isCancelled() && !dataSourceIngestPipeline.isEmpty()) {
List<IngestModuleError> errors = new ArrayList<>();
errors.addAll(dataSourceIngestPipeline.process(task, dataSourceIngestProgress));
if (!errors.isEmpty()) {
logIngestModuleErrors(errors);
}
}
if (null != dataSourceIngestProgress) {
dataSourceIngestProgress.finish();
// This is safe because this method will be called at most once per
// ingest job and finish() will not be called while that single
// data source ingest task has not been reported complete by this
// code to the ingest scheduler.
dataSourceIngestProgress = null;
}
ingestTaskScheduler.notifyTaskCompleted(task);
}
void process(FileIngestTask task) throws InterruptedException {
if (!isCancelled()) {
FileIngestPipeline pipeline = fileIngestPipelines.take();
if (!pipeline.isEmpty()) {
AbstractFile file = task.getFile();
synchronized (this) {
++processedFiles;
if (processedFiles <= estimatedFilesToProcess) {
fileIngestProgress.progress(file.getName(), (int) processedFiles);
} else {
fileIngestProgress.progress(file.getName(), (int) estimatedFilesToProcess);
}
}
try {
if (!isCancelled() && !dataSourceIngestPipeline.isEmpty()) {
List<IngestModuleError> errors = new ArrayList<>();
errors.addAll(pipeline.process(task));
errors.addAll(dataSourceIngestPipeline.process(task, dataSourceIngestProgress));
if (!errors.isEmpty()) {
logIngestModuleErrors(errors);
}
}
fileIngestPipelines.put(pipeline);
if (null != dataSourceIngestProgress) {
dataSourceIngestProgress.finish();
// This is safe because this method will be called at most once per
// ingest job and finish() will not be called while that single
// data source ingest task has not been reported complete by this
// code to the ingest scheduler.
dataSourceIngestProgress = null;
}
}
finally {
ingestTaskScheduler.notifyTaskCompleted(task);
}
}
void process(FileIngestTask task) throws InterruptedException {
try {
if (!isCancelled()) {
FileIngestPipeline pipeline = fileIngestPipelines.take();
if (!pipeline.isEmpty()) {
AbstractFile file = task.getFile();
synchronized (this) {
++processedFiles;
if (processedFiles <= estimatedFilesToProcess) {
fileIngestProgress.progress(file.getName(), (int) processedFiles);
} else {
fileIngestProgress.progress(file.getName(), (int) estimatedFilesToProcess);
}
}
List<IngestModuleError> errors = new ArrayList<>();
errors.addAll(pipeline.process(task));
if (!errors.isEmpty()) {
logIngestModuleErrors(errors);
}
}
fileIngestPipelines.put(pipeline);
}
}
finally {
ingestTaskScheduler.notifyTaskCompleted(task);
}
ingestTaskScheduler.notifyTaskCompleted(task);
}
void finish() {

View File

@@ -31,17 +31,17 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JOptionPane;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.util.Cancellable;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.datamodel.Content;
import javax.swing.JOptionPane;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
/**
* Manages the execution of ingest jobs.
@@ -288,7 +288,7 @@ public class IngestManager {
/**
* Property change event fired when the ingest of a file is completed.
* The old value of the PropertyChangeEvent is the Autopsy object ID of
* the file, and the new value is set to null.
* the file. The new value is the AbstractFile for that ID.
*/
FILE_DONE,
};
@@ -383,10 +383,10 @@ public class IngestManager {
/**
* Fire an ingest event signifying the ingest of a file is completed.
*
* @param fileId The object id of file.
* @param file The file that is completed.
*/
void fireFileIngestDone(long fileId) {
fireIngestEventsThreadPool.submit(new FireIngestEventTask(ingestModuleEventPublisher, IngestModuleEvent.FILE_DONE, fileId, null));
void fireFileIngestDone(AbstractFile file) {
fireIngestEventsThreadPool.submit(new FireIngestEventTask(ingestModuleEventPublisher, IngestModuleEvent.FILE_DONE, file.getId(), file));
}
/**

View File

@@ -52,30 +52,34 @@ final class IngestScheduler {
private final AtomicLong nextIngestJobId = new AtomicLong(0L);
private final ConcurrentHashMap<Long, IngestJob> ingestJobsById = new ConcurrentHashMap<>();
private volatile boolean enabled = false;
// private volatile boolean cancellingAllTasks = false; TODO: Uncomment this with related code, if desired
// private volatile boolean cancellingAllTasks = false; TODO: Uncomment this with related code, if desired
private final DataSourceIngestTaskQueue dataSourceTaskDispenser = new DataSourceIngestTaskQueue();
private final FileIngestTaskQueue fileTaskDispenser = new FileIngestTaskQueue();
// The following five collections lie at the heart of the scheduler.
//
// The pending tasks queues are used to schedule tasks for an ingest job. If
// multiple jobs are scheduled, tasks from different jobs may become
// interleaved in these queues. Data source tasks go into a simple FIFO
// queue that is consumed by the ingest threads. File tasks are "shuffled"
// interleaved in these queues.
// FIFO queue for data source-level tasks.
private final LinkedBlockingQueue<DataSourceIngestTask> pendingDataSourceTasks = new LinkedBlockingQueue<>(); // Guarded by this
// File tasks are "shuffled"
// through root directory (priority queue), directory (LIFO), and file tasks
// queues (LIFO). If a file task makes it into the pending file tasks queue,
// it is consumed by the ingest threads.
//
// The "tasks in progress" list is used to determine when an ingest job is
// completed and should be shut down, i.e., the job should shut down its
// ingest pipelines and finish its progress bars. Tasks stay in the "tasks
// in progress" list either until discarded by the scheduler or the ingest
// thread that is working on the task notifies the scheduler that the task
// is completed.
private final LinkedBlockingQueue<DataSourceIngestTask> pendingDataSourceTasks = new LinkedBlockingQueue<>();
private final TreeSet<FileIngestTask> pendingRootDirectoryTasks = new TreeSet<>(new RootDirectoryTaskComparator()); // Guarded by this
private final List<FileIngestTask> pendingDirectoryTasks = new ArrayList<>(); // Guarded by this
private final BlockingDeque<FileIngestTask> pendingFileTasks = new LinkedBlockingDeque<>();
private final List<IngestTask> tasksInProgress = new ArrayList<>(); // Guarded by this
private final BlockingDeque<FileIngestTask> pendingFileTasks = new LinkedBlockingDeque<>(); // Not guarded
// The "tasks in progress" list has:
// - File and data source tasks that are running
// - File tasks that are in the pending file queue
// It is used to determine when a job is done. It has both pending and running
// tasks because we do not lock the 'pendingFileTasks' and a task needs to be in
// at least one of the pending or inprogress lists at all times before it is completed.
// files are added to this when the are added to pendingFilesTasks and removed when they complete
private final List<IngestTask> tasksInProgressAndPending = new ArrayList<>(); // Guarded by this
synchronized static IngestScheduler getInstance() {
if (instance == null) {
@@ -133,12 +137,12 @@ final class IngestScheduler {
synchronized private void scheduleDataSourceIngestTask(IngestJob job) throws InterruptedException {
DataSourceIngestTask task = new DataSourceIngestTask(job);
tasksInProgress.add(task);
tasksInProgressAndPending.add(task);
try {
// Should not block, queue is (theoretically) unbounded.
pendingDataSourceTasks.put(task);
} catch (InterruptedException ex) {
tasksInProgress.remove(task);
tasksInProgressAndPending.remove(task);
Logger.getLogger(IngestScheduler.class.getName()).log(Level.SEVERE, "Interruption of unexpected block on pending data source tasks queue", ex); //NON-NLS
throw ex;
}
@@ -149,7 +153,6 @@ final class IngestScheduler {
for (AbstractFile firstLevelFile : topLevelFiles) {
FileIngestTask task = new FileIngestTask(job, firstLevelFile);
if (shouldEnqueueFileTask(task)) {
tasksInProgress.add(task);
pendingRootDirectoryTasks.add(task);
}
}
@@ -212,9 +215,7 @@ final class IngestScheduler {
if (shouldEnqueueFileTask(directoryTask)) {
addToPendingFileTasksQueue(directoryTask);
tasksEnqueuedForDirectory = true;
} else {
tasksInProgress.remove(directoryTask);
}
}
// If the directory contains subdirectories or files, try to
// enqueue tasks for them as well.
@@ -227,13 +228,11 @@ final class IngestScheduler {
if (file.hasChildren()) {
// Found a subdirectory, put the task in the
// pending directory tasks queue.
tasksInProgress.add(childTask);
pendingDirectoryTasks.add(childTask);
tasksEnqueuedForDirectory = true;
} else if (shouldEnqueueFileTask(childTask)) {
// Found a file, put the task directly into the
// pending file tasks queue.
tasksInProgress.add(childTask);
addToPendingFileTasksQueue(childTask);
tasksEnqueuedForDirectory = true;
}
@@ -304,6 +303,7 @@ final class IngestScheduler {
}
synchronized private void addToPendingFileTasksQueue(FileIngestTask task) throws IllegalStateException {
tasksInProgressAndPending.add(task);
try {
// Should not block, queue is (theoretically) unbounded.
/* add to top of list because we had one image that had a folder with
@@ -313,7 +313,7 @@ final class IngestScheduler {
*/
pendingFileTasks.addFirst(task);
} catch (IllegalStateException ex) {
tasksInProgress.remove(task);
tasksInProgressAndPending.remove(task);
Logger.getLogger(IngestScheduler.class.getName()).log(Level.SEVERE, "Interruption of unexpected block on pending file tasks queue", ex); //NON-NLS
throw ex;
}
@@ -326,7 +326,6 @@ final class IngestScheduler {
// Send the file task directly to file tasks queue, no need to
// update the pending root directory or pending directory tasks
// queues.
tasksInProgress.add(task);
addToPendingFileTasksQueue(task);
}
}
@@ -344,7 +343,7 @@ final class IngestScheduler {
boolean jobIsCompleted;
IngestJob job = task.getIngestJob();
synchronized (this) {
tasksInProgress.remove(task);
tasksInProgressAndPending.remove(task);
jobIsCompleted = ingestJobIsComplete(job);
}
if (jobIsCompleted) {
@@ -382,7 +381,7 @@ final class IngestScheduler {
while (iterator.hasNext()) {
IngestTask task = (IngestTask) iterator.next();
if (task.getIngestJob().getId() == jobId) {
tasksInProgress.remove((IngestTask) task);
tasksInProgressAndPending.remove((IngestTask) task);
iterator.remove();
}
}
@@ -420,13 +419,13 @@ final class IngestScheduler {
synchronized private <T> void removeAllPendingTasks(Collection<T> taskQueue) {
Iterator<T> iterator = taskQueue.iterator();
while (iterator.hasNext()) {
tasksInProgress.remove((IngestTask) iterator.next());
tasksInProgressAndPending.remove((IngestTask) iterator.next());
iterator.remove();
}
}
synchronized private boolean ingestJobIsComplete(IngestJob job) {
for (IngestTask task : tasksInProgress) {
for (IngestTask task : tasksInProgressAndPending) {
if (task.getIngestJob().getId() == job.getId()) {
return false;
}

View File

@@ -51,7 +51,7 @@ import org.sleuthkit.autopsy.corecomponents.DataContentTopComponent;
defaultItem.addActionListener(new OpenTopComponentAction(contentWin));
if (!Case.existsCurrentCase() || Case.getCurrentCase().getRootObjectsCount() == 0) {
if (!Case.existsCurrentCase() || Case.getCurrentCase().hasData() == false) {
defaultItem.setEnabled(false); // disable the menu items when no case is opened
} else {
defaultItem.setEnabled(true); // enable the menu items when there's a case opened / created

View File

@@ -53,7 +53,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataExplorer;
JMenuItem item = new JMenuItem(explorerWin.getName());
item.addActionListener(new OpenTopComponentAction(explorerWin));
if(!Case.existsCurrentCase() || Case.getCurrentCase().getRootObjectsCount() == 0){
if(!Case.existsCurrentCase() || Case.getCurrentCase().hasData() == false){
item.setEnabled(false); // disable the menu when no case is opened
}
else{

View File

@@ -80,7 +80,7 @@ class WWFMessageAnalyzer {
try {
resultSet = statement.executeQuery(
"SELECT message,created_at,user_id,game_id FROM chat_messages ORDER BY game_id DESC, created_at DESC;");
"SELECT message,strftime('%s' ,created_at) as datetime,user_id,game_id FROM chat_messages ORDER BY game_id DESC, created_at DESC;");
String message; // WWF Message
String user_id; // the ID of the user who sent the message.
@@ -88,7 +88,7 @@ class WWFMessageAnalyzer {
while (resultSet.next()) {
message = resultSet.getString("message");
Long created_at = Long.valueOf(resultSet.getString("created_at")) / 1000;
Long created_at = resultSet.getLong("datetime");
user_id = resultSet.getString("user_id");
game_id = resultSet.getString("game_id");

View File

@@ -25,7 +25,7 @@ package org.sleuthkit.autopsy.report;
/**
* Interface for report modules that plug in to the reporting infrastructure.
*/
interface ReportModule {
interface ReportModule {
/**
* Get the name of the report this module generates.
@@ -37,13 +37,14 @@ package org.sleuthkit.autopsy.report;
* module generates.
*/
public String getDescription();
/**
* Gets the path of the report file, if any, generated by this module. If
* a report file is generated, the path should be relative to the reports
* directory.
*
* @return File path relative to the reports directory, may be null.
* Gets the relative path of the report file, if any, generated by this
* module. The path should be relative to the time stamp subdirectory of
* reports directory.
*
* @return Report file path relative to the time stamp subdirectory reports
* directory, may be null if the module does not produce a report file.
*/
public String getRelativeFilePath();
}
}

View File

@@ -1161,7 +1161,7 @@ public class Timeline extends CallableSystemAction implements Presenter.Toolbar,
skCase = currentCase.getSleuthkitCase();
try {
if (currentCase.getRootObjectsCount() == 0) {
if (currentCase.hasData() == false) {
logger.log(Level.INFO, "Error creating timeline, there are no data sources. "); //NON-NLS
} else {

View File

@@ -191,7 +191,7 @@ class ExtractRegistry extends Extract {
// parse the autopsy-specific output
if (regOutputFiles.autopsyPlugins.isEmpty() == false) {
if (parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile.getId(), usbMapper) == false) {
if (parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile, usbMapper) == false) {
this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults",
this.getName(), regFileName));
@@ -371,7 +371,14 @@ class ExtractRegistry extends Extract {
}
// @@@ VERIFY that we are doing the right thing when we parse multiple NTUSER.DAT
private boolean parseAutopsyPluginOutput(String regRecord, long orgId, UsbDeviceIdMapper extrctr) {
/**
*
* @param regRecord
* @param regFile File object for registry that we are parsing (to make blackboard artifacts with)
* @param extrctr
* @return
*/
private boolean parseAutopsyPluginOutput(String regRecord, AbstractFile regFile, UsbDeviceIdMapper extrctr) {
FileInputStream fstream = null;
try {
SleuthkitCase tempDb = currentCase.getSleuthkitCase();
@@ -447,7 +454,7 @@ class ExtractRegistry extends Extract {
Long usbMtime = Long.parseLong(artnode.getAttribute("mtime")); //NON-NLS
usbMtime = Long.valueOf(usbMtime.toString());
BlackboardArtifact bbart = tempDb.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),
NbBundle.getMessage(this.getClass(),
"ExtractRegistry.parentModuleName.noSpace"), usbMtime));
@@ -494,7 +501,7 @@ class ExtractRegistry extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),
NbBundle.getMessage(this.getClass(),
"ExtractRegistry.parentModuleName.noSpace"), itemMtime));
BlackboardArtifact bbart = tempDb.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
bbart.addAttributes(bbattributes);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS
@@ -526,7 +533,7 @@ class ExtractRegistry extends Extract {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),
NbBundle.getMessage(this.getClass(),
"ExtractRegistry.parentModuleName.noSpace"), installtime));
BlackboardArtifact bbart = tempDb.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
bbart.addAttributes(bbattributes);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS
@@ -537,7 +544,7 @@ class ExtractRegistry extends Extract {
String name = artnode.getAttribute("name"); //NON-NLS
try {
BlackboardArtifact bbart = tempDb.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
// @@@ BC: Consider removing this after some more testing. It looks like an Mtime associated with the root key and not the individual item
if (mtime != null) {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(),