mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-20 11:26:53 +00:00
Merge pull request #1384 from rcordovano/closed-case-checks
Closed case checks
This commit is contained in:
commit
e1599e13a1
@ -1392,29 +1392,33 @@ public class Case {
|
|||||||
Case.clearTempFolder();
|
Case.clearTempFolder();
|
||||||
checkSubFolders(toChangeTo);
|
checkSubFolders(toChangeTo);
|
||||||
|
|
||||||
// enable these menus
|
if (IngestManager.getInstance().isRunningInteractively()) {
|
||||||
CallableSystemAction.get(AddImageAction.class).setEnabled(true);
|
// enable these menus
|
||||||
CallableSystemAction.get(CaseCloseAction.class).setEnabled(true);
|
CallableSystemAction.get(AddImageAction.class).setEnabled(true);
|
||||||
CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true);
|
CallableSystemAction.get(CaseCloseAction.class).setEnabled(true);
|
||||||
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true); // Delete Case menu
|
CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true);
|
||||||
|
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true); // Delete Case menu
|
||||||
|
|
||||||
if (toChangeTo.hasData()) {
|
if (toChangeTo.hasData()) {
|
||||||
// open all top components
|
// open all top components
|
||||||
CoreComponentControl.openCoreWindows();
|
CoreComponentControl.openCoreWindows();
|
||||||
} else {
|
} else {
|
||||||
// close all top components
|
// close all top components
|
||||||
CoreComponentControl.closeCoreWindows();
|
CoreComponentControl.closeCoreWindows();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else { // case is closed
|
} else { // case is closed
|
||||||
// close all top components first
|
if (IngestManager.getInstance().isRunningInteractively()) {
|
||||||
CoreComponentControl.closeCoreWindows();
|
// close all top components first
|
||||||
|
CoreComponentControl.closeCoreWindows();
|
||||||
// disable these menus
|
|
||||||
CallableSystemAction.get(AddImageAction.class).setEnabled(false); // Add Image menu
|
|
||||||
CallableSystemAction.get(CaseCloseAction.class).setEnabled(false); // Case Close menu
|
|
||||||
CallableSystemAction.get(CasePropertiesAction.class).setEnabled(false); // Case Properties menu
|
|
||||||
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(false); // Delete Case menu
|
|
||||||
|
|
||||||
|
// disable these menus
|
||||||
|
CallableSystemAction.get(AddImageAction.class).setEnabled(false); // Add Image menu
|
||||||
|
CallableSystemAction.get(CaseCloseAction.class).setEnabled(false); // Case Close menu
|
||||||
|
CallableSystemAction.get(CasePropertiesAction.class).setEnabled(false); // Case Properties menu
|
||||||
|
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(false); // Delete Case menu
|
||||||
|
}
|
||||||
|
|
||||||
//clear pending notifications
|
//clear pending notifications
|
||||||
MessageNotifyUtil.Notify.clear();
|
MessageNotifyUtil.Notify.clear();
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2013-2014 Basis Technology Corp.
|
* Copyright 2013-2015 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -180,16 +180,40 @@ public class DeletedContent implements AutopsyVisitableItem {
|
|||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
String eventType = evt.getPropertyName();
|
String eventType = evt.getPropertyName();
|
||||||
|
|
||||||
// new file was added
|
|
||||||
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
|
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
|
||||||
// @@@ COULD CHECK If the new file is deleted before notifying...
|
/**
|
||||||
update();
|
* Checking for a current case is a stop gap measure
|
||||||
|
* until a different way of handling the closing of
|
||||||
|
* cases is worked out. Currently, remote events may be
|
||||||
|
* received for a case that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
// new file was added
|
||||||
|
// @@@ COULD CHECK If the new file is deleted before notifying...
|
||||||
|
update();
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|
||||||
update();
|
|| eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
||||||
} else if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
/**
|
||||||
update();
|
* Checking for a current case is a stop gap measure
|
||||||
|
* until a different way of handling the closing of
|
||||||
|
* cases is worked out. Currently, remote events may be
|
||||||
|
* received for a case that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
update();
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||||
if (evt.getNewValue() == null) {
|
if (evt.getNewValue() == null) {
|
||||||
|
@ -204,17 +204,47 @@ public class EmailExtracted implements AutopsyVisitableItem {
|
|||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
String eventType = evt.getPropertyName();
|
String eventType = evt.getPropertyName();
|
||||||
|
|
||||||
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
||||||
if (((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG) {
|
/**
|
||||||
emailResults.update();
|
* Checking for a current case is a stop gap measure until a
|
||||||
|
* different way of handling the closing of cases is worked
|
||||||
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
/**
|
||||||
|
* Even with the check above, it is still possible that the
|
||||||
|
* case will be closed in a different thread before this
|
||||||
|
* code executes. If that happens, it is possible for the
|
||||||
|
* event to have a null oldValue.
|
||||||
|
*/
|
||||||
|
ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue();
|
||||||
|
if (null != eventData && eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG) {
|
||||||
|
emailResults.update();
|
||||||
|
}
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||||
else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
/**
|
||||||
emailResults.update();
|
* Checking for a current case is a stop gap measure until a
|
||||||
}
|
* different way of handling the closing of cases is worked
|
||||||
else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
emailResults.update();
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||||
if (evt.getNewValue() == null) {
|
if (evt.getNewValue() == null) {
|
||||||
removeNotify();
|
removeNotify();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2014 Basis Technology Corp.
|
* Copyright 2011-2015 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -126,7 +126,7 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
|||||||
* more specific form elsewhere in the tree.
|
* more specific form elsewhere in the tree.
|
||||||
*/
|
*/
|
||||||
private class TypeFactory extends ChildFactory.Detachable<BlackboardArtifact.ARTIFACT_TYPE> {
|
private class TypeFactory extends ChildFactory.Detachable<BlackboardArtifact.ARTIFACT_TYPE> {
|
||||||
private final ArrayList<BlackboardArtifact.ARTIFACT_TYPE> doNotShow;
|
private final ArrayList<BlackboardArtifact.ARTIFACT_TYPE> doNotShow = new ArrayList<>();
|
||||||
// maps the artifact type to its child node
|
// maps the artifact type to its child node
|
||||||
private final HashMap<BlackboardArtifact.ARTIFACT_TYPE, TypeNode> typeNodeList = new HashMap<>();
|
private final HashMap<BlackboardArtifact.ARTIFACT_TYPE, TypeNode> typeNodeList = new HashMap<>();
|
||||||
|
|
||||||
@ -134,7 +134,6 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
|||||||
super();
|
super();
|
||||||
|
|
||||||
// these are shown in other parts of the UI tree
|
// these are shown in other parts of the UI tree
|
||||||
doNotShow = new ArrayList<>();
|
|
||||||
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO);
|
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO);
|
||||||
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG);
|
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG);
|
||||||
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT);
|
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT);
|
||||||
@ -143,26 +142,53 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
|||||||
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT);
|
doNotShow.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
|
||||||
@Override
|
String eventType = evt.getPropertyName();
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
||||||
String eventType = evt.getPropertyName();
|
/**
|
||||||
|
* This is a stop gap measure until a different way of
|
||||||
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
* handling the closing of cases is worked out. Currently,
|
||||||
|
* remote events may be received for a case that is already
|
||||||
|
* closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
/**
|
||||||
|
* Due to some unresolved issues with how cases are
|
||||||
|
* closed, it is possible for the event to have a null
|
||||||
|
* oldValue if the event is a remote event.
|
||||||
|
*/
|
||||||
final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue();
|
final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue();
|
||||||
if (doNotShow.contains(event.getArtifactType()) == false) {
|
if (null != event && doNotShow.contains(event.getArtifactType()) == false) {
|
||||||
refresh(true);
|
refresh(true);
|
||||||
}
|
}
|
||||||
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
} catch (IllegalStateException notUsed) {
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
/**
|
||||||
refresh(true);
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||||
if (evt.getNewValue() == null) {
|
/**
|
||||||
removeNotify();
|
* This is a stop gap measure until a different way of
|
||||||
skCase = null;
|
* handling the closing of cases is worked out. Currently,
|
||||||
}
|
* remote events may be received for a case that is already
|
||||||
|
* closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
refresh(true);
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||||
|
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||||
|
if (evt.getNewValue() == null) {
|
||||||
|
removeNotify();
|
||||||
|
skCase = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -362,15 +388,46 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
|||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
String eventType = evt.getPropertyName();
|
String eventType = evt.getPropertyName();
|
||||||
|
|
||||||
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
||||||
final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue();
|
/**
|
||||||
if (event.getArtifactType() == type) {
|
* Checking for a current case is a stop gap measure until a
|
||||||
refresh(true);
|
* different way of handling the closing of cases is worked
|
||||||
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
/**
|
||||||
|
* Even with the check above, it is still possible that
|
||||||
|
* the case will be closed in a different thread before
|
||||||
|
* this code executes. If that happens, it is possible
|
||||||
|
* for the event to have a null oldValue.
|
||||||
|
*/
|
||||||
|
final ModuleDataEvent event = (ModuleDataEvent) evt.getOldValue();
|
||||||
|
if (null != event && event.getArtifactType() == type) {
|
||||||
|
refresh(true);
|
||||||
|
}
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||||
refresh(true);
|
/**
|
||||||
|
* Checking for a current case is a stop gap measure until a
|
||||||
|
* different way of handling the closing of cases is worked
|
||||||
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
refresh(true);
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2013-2014 Basis Technology Corp.
|
* Copyright 2013-2015 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -178,15 +178,40 @@ public class FileSize implements AutopsyVisitableItem {
|
|||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
String eventType = evt.getPropertyName();
|
String eventType = evt.getPropertyName();
|
||||||
|
|
||||||
// new file was added
|
|
||||||
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
|
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
|
||||||
// @@@ could check the size here and only fire off updates if we know the file meets the min size criteria
|
/**
|
||||||
update();
|
* Checking for a current case is a stop gap measure
|
||||||
|
* until a different way of handling the closing of
|
||||||
|
* cases is worked out. Currently, remote events may be
|
||||||
|
* received for a case that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
// new file was added
|
||||||
|
// @@@ could check the size here and only fire off updates if we know the file meets the min size criteria
|
||||||
|
Case.getCurrentCase();
|
||||||
|
update();
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|
||||||
update();
|
|| eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
||||||
} else if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
/**
|
||||||
update();
|
* Checking for a current case is a stop gap measure
|
||||||
|
* until a different way of handling the closing of
|
||||||
|
* cases is worked out. Currently, remote events may be
|
||||||
|
* received for a case that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
update();
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||||
if (evt.getNewValue() == null) {
|
if (evt.getNewValue() == null) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2014 Basis Technology Corp.
|
* Copyright 2011-2015 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -152,15 +152,24 @@ public class FileTypesNode extends DisplayableItemNode {
|
|||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
String eventType = evt.getPropertyName();
|
String eventType = evt.getPropertyName();
|
||||||
|
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())
|
||||||
// new file was added
|
|| eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||||
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
|
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|
||||||
update();
|
|| eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
||||||
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
/**
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
* Checking for a current case is a stop gap measure
|
||||||
update();
|
* until a different way of handling the closing of
|
||||||
} else if (eventType.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
* cases is worked out. Currently, remote events may be
|
||||||
update();
|
* received for a case that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
update();
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||||
if (evt.getNewValue() == null) {
|
if (evt.getNewValue() == null) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2014 Basis Technology Corp.
|
* Copyright 2011-2015 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -181,17 +181,46 @@ public class HashsetHits implements AutopsyVisitableItem {
|
|||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
String eventType = evt.getPropertyName();
|
String eventType = evt.getPropertyName();
|
||||||
|
|
||||||
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
||||||
if (((ModuleDataEvent) evt.getOldValue()).getArtifactType() == ARTIFACT_TYPE.TSK_HASHSET_HIT) {
|
/**
|
||||||
hashsetResults.update();
|
* Checking for a current case is a stop gap measure until a
|
||||||
|
* different way of handling the closing of cases is worked
|
||||||
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
/**
|
||||||
|
* Due to some unresolved issues with how cases are
|
||||||
|
* closed, it is possible for the event to have a null
|
||||||
|
* oldValue if the event is a remote event.
|
||||||
|
*/
|
||||||
|
ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue();
|
||||||
|
if (null != eventData && eventData.getArtifactType() == ARTIFACT_TYPE.TSK_HASHSET_HIT) {
|
||||||
|
hashsetResults.update();
|
||||||
|
}
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||||
else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
/**
|
||||||
hashsetResults.update();
|
* Checking for a current case is a stop gap measure until a
|
||||||
}
|
* different way of handling the closing of cases is worked
|
||||||
else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
hashsetResults.update();
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||||
if (evt.getNewValue() == null) {
|
if (evt.getNewValue() == null) {
|
||||||
removeNotify();
|
removeNotify();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011 Basis Technology Corp.
|
* Copyright 2011-2015 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.datamodel;
|
package org.sleuthkit.autopsy.datamodel;
|
||||||
|
|
||||||
|
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
@ -50,34 +49,34 @@ import org.sleuthkit.datamodel.SleuthkitCase;
|
|||||||
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
|
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
|
||||||
public class InterestingHits implements AutopsyVisitableItem {
|
public class InterestingHits implements AutopsyVisitableItem {
|
||||||
|
|
||||||
private static final String INTERESTING_ITEMS = NbBundle
|
private static final String INTERESTING_ITEMS = NbBundle
|
||||||
.getMessage(InterestingHits.class, "InterestingHits.interestingItems.text");
|
.getMessage(InterestingHits.class, "InterestingHits.interestingItems.text");
|
||||||
private static final String DISPLAY_NAME = NbBundle.getMessage(InterestingHits.class, "InterestingHits.displayName.text");
|
private static final String DISPLAY_NAME = NbBundle.getMessage(InterestingHits.class, "InterestingHits.displayName.text");
|
||||||
private static final Logger logger = Logger.getLogger(InterestingHits.class.getName());
|
private static final Logger logger = Logger.getLogger(InterestingHits.class.getName());
|
||||||
private SleuthkitCase skCase;
|
private SleuthkitCase skCase;
|
||||||
private final InterestingResults interestingResults = new InterestingResults();
|
private final InterestingResults interestingResults = new InterestingResults();
|
||||||
|
|
||||||
public InterestingHits(SleuthkitCase skCase) {
|
public InterestingHits(SleuthkitCase skCase) {
|
||||||
this.skCase = skCase;
|
this.skCase = skCase;
|
||||||
interestingResults.update();
|
interestingResults.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class InterestingResults extends Observable {
|
private class InterestingResults extends Observable {
|
||||||
|
|
||||||
private final Map<String, Set<Long>> interestingItemsMap = new LinkedHashMap<>();
|
private final Map<String, Set<Long>> interestingItemsMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
public List<String> getSetNames() {
|
public List<String> getSetNames() {
|
||||||
List<String> setNames = new ArrayList<>(interestingItemsMap.keySet());
|
List<String> setNames = new ArrayList<>(interestingItemsMap.keySet());
|
||||||
Collections.sort(setNames);
|
Collections.sort(setNames);
|
||||||
return setNames;
|
return setNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Long> getArtifactIds(String setName) {
|
public Set<Long> getArtifactIds(String setName) {
|
||||||
return interestingItemsMap.get(setName);
|
return interestingItemsMap.get(setName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
interestingItemsMap.clear();
|
interestingItemsMap.clear();
|
||||||
loadArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT);
|
loadArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT);
|
||||||
@ -85,16 +84,17 @@ public class InterestingHits implements AutopsyVisitableItem {
|
|||||||
setChanged();
|
setChanged();
|
||||||
notifyObservers();
|
notifyObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reads the artifacts of specified type, grouped by Set, and loads into the interestingItemsMap
|
* Reads the artifacts of specified type, grouped by Set, and loads into
|
||||||
|
* the interestingItemsMap
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
private void loadArtifacts(BlackboardArtifact.ARTIFACT_TYPE artType) {
|
private void loadArtifacts(BlackboardArtifact.ARTIFACT_TYPE artType) {
|
||||||
if (skCase == null) {
|
if (skCase == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int setNameId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID();
|
int setNameId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID();
|
||||||
int artId = artType.getTypeID();
|
int artId = artType.getTypeID();
|
||||||
String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS
|
String query = "SELECT value_text,blackboard_attributes.artifact_id,attribute_type_id " //NON-NLS
|
||||||
@ -118,13 +118,13 @@ public class InterestingHits implements AutopsyVisitableItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node for the interesting items
|
* Node for the interesting items
|
||||||
*/
|
*/
|
||||||
public class RootNode extends DisplayableItemNode {
|
public class RootNode extends DisplayableItemNode {
|
||||||
@ -140,7 +140,7 @@ public class InterestingHits implements AutopsyVisitableItem {
|
|||||||
public boolean isLeafTypeNode() {
|
public boolean isLeafTypeNode() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
@ -156,36 +156,67 @@ public class InterestingHits implements AutopsyVisitableItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
|
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
|
||||||
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.displayName"),
|
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.displayName"),
|
||||||
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"),
|
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"),
|
||||||
getName()));
|
getName()));
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SetNameFactory extends ChildFactory.Detachable<String> implements Observer {
|
|
||||||
|
|
||||||
/* This should probably be in the top-level class, but the factory has nice methods
|
private class SetNameFactory extends ChildFactory.Detachable<String> implements Observer {
|
||||||
* for its startup and shutdown, so it seemed like a cleaner place to register the
|
|
||||||
* property change listener.
|
/*
|
||||||
|
* This should probably be in the top-level class, but the factory has
|
||||||
|
* nice methods for its startup and shutdown, so it seemed like a
|
||||||
|
* cleaner place to register the property change listener.
|
||||||
*/
|
*/
|
||||||
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
private final PropertyChangeListener pcl = new PropertyChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
String eventType = evt.getPropertyName();
|
String eventType = evt.getPropertyName();
|
||||||
|
|
||||||
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
||||||
if ((((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT) ||
|
/**
|
||||||
(((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT)) {
|
* Checking for a current case is a stop gap measure until a
|
||||||
interestingResults.update();
|
* different way of handling the closing of cases is worked
|
||||||
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
/**
|
||||||
|
* Even with the check above, it is still possible that
|
||||||
|
* the case will be closed in a different thread before
|
||||||
|
* this code executes. If that happens, it is possible
|
||||||
|
* for the event to have a null oldValue.
|
||||||
|
*/
|
||||||
|
ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue();
|
||||||
|
if (null != eventData && (eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT
|
||||||
|
|| eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT)) {
|
||||||
|
interestingResults.update();
|
||||||
|
}
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||||
else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
/**
|
||||||
interestingResults.update();
|
* Checking for a current case is a stop gap measure until a
|
||||||
}
|
* different way of handling the closing of cases is worked
|
||||||
else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
interestingResults.update();
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||||
if (evt.getNewValue() == null) {
|
if (evt.getNewValue() == null) {
|
||||||
removeNotify();
|
removeNotify();
|
||||||
@ -211,7 +242,7 @@ public class InterestingHits implements AutopsyVisitableItem {
|
|||||||
Case.removePropertyChangeListener(pcl);
|
Case.removePropertyChangeListener(pcl);
|
||||||
interestingResults.deleteObserver(this);
|
interestingResults.deleteObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean createKeys(List<String> list) {
|
protected boolean createKeys(List<String> list) {
|
||||||
list.addAll(interestingResults.getSetNames());
|
list.addAll(interestingResults.getSetNames());
|
||||||
@ -228,9 +259,11 @@ public class InterestingHits implements AutopsyVisitableItem {
|
|||||||
refresh(true);
|
refresh(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SetNameNode extends DisplayableItemNode implements Observer {
|
public class SetNameNode extends DisplayableItemNode implements Observer {
|
||||||
|
|
||||||
private final String setName;
|
private final String setName;
|
||||||
|
|
||||||
public SetNameNode(String setName) {//, Set<Long> children) {
|
public SetNameNode(String setName) {//, Set<Long> children) {
|
||||||
super(Children.create(new HitFactory(setName), true), Lookups.singleton(setName));
|
super(Children.create(new HitFactory(setName), true), Lookups.singleton(setName));
|
||||||
this.setName = setName;
|
this.setName = setName;
|
||||||
@ -239,7 +272,7 @@ public class InterestingHits implements AutopsyVisitableItem {
|
|||||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/interesting_item.png"); //NON-NLS
|
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/interesting_item.png"); //NON-NLS
|
||||||
interestingResults.addObserver(this);
|
interestingResults.addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateDisplayName() {
|
private void updateDisplayName() {
|
||||||
super.setDisplayName(setName + " (" + interestingResults.getArtifactIds(setName).size() + ")");
|
super.setDisplayName(setName + " (" + interestingResults.getArtifactIds(setName).size() + ")");
|
||||||
}
|
}
|
||||||
@ -259,9 +292,9 @@ public class InterestingHits implements AutopsyVisitableItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
|
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
|
||||||
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
|
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
|
||||||
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"),
|
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"),
|
||||||
getName()));
|
getName()));
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -276,8 +309,9 @@ public class InterestingHits implements AutopsyVisitableItem {
|
|||||||
updateDisplayName();
|
updateDisplayName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class HitFactory extends ChildFactory<Long> implements Observer {
|
private class HitFactory extends ChildFactory<Long> implements Observer {
|
||||||
|
|
||||||
private final String setName;
|
private final String setName;
|
||||||
|
|
||||||
private HitFactory(String setName) {
|
private HitFactory(String setName) {
|
||||||
@ -297,7 +331,7 @@ public class InterestingHits implements AutopsyVisitableItem {
|
|||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(Long l) {
|
protected Node createNodeForKey(Long l) {
|
||||||
if (skCase == null) {
|
if (skCase == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return new BlackboardArtifactNode(skCase.getBlackboardArtifact(l));
|
return new BlackboardArtifactNode(skCase.getBlackboardArtifact(l));
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2014 Basis Technology Corp.
|
* Copyright 2011-2015 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -246,17 +246,47 @@ public class KeywordHits implements AutopsyVisitableItem {
|
|||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
String eventType = evt.getPropertyName();
|
String eventType = evt.getPropertyName();
|
||||||
|
|
||||||
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
||||||
if (((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT) {
|
/**
|
||||||
keywordResults.update();
|
* Checking for a current case is a stop gap measure until a
|
||||||
|
* different way of handling the closing of cases is worked
|
||||||
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
/**
|
||||||
|
* Even with the check above, it is still possible that
|
||||||
|
* the case will be closed in a different thread before
|
||||||
|
* this code executes. If that happens, it is possible
|
||||||
|
* for the event to have a null oldValue.
|
||||||
|
*/
|
||||||
|
ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue();
|
||||||
|
if (null != eventData && eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT) {
|
||||||
|
keywordResults.update();
|
||||||
|
}
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||||
else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||||
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
/**
|
||||||
keywordResults.update();
|
* Checking for a current case is a stop gap measure until a
|
||||||
}
|
* different way of handling the closing of cases is worked
|
||||||
else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
keywordResults.update();
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||||
if (evt.getNewValue() == null) {
|
if (evt.getNewValue() == null) {
|
||||||
removeNotify();
|
removeNotify();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2014 Basis Technology Corp.
|
* Copyright 2011-2015 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -98,7 +98,20 @@ public final class Reports implements AutopsyVisitableItem {
|
|||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
String eventType = evt.getPropertyName();
|
String eventType = evt.getPropertyName();
|
||||||
if (eventType.equals(Case.Events.REPORT_ADDED.toString())) {
|
if (eventType.equals(Case.Events.REPORT_ADDED.toString())) {
|
||||||
ReportNodeFactory.this.refresh(true);
|
/**
|
||||||
|
* Checking for a current case is a stop gap measure
|
||||||
|
* until a different way of handling the closing of
|
||||||
|
* cases is worked out. Currently, remote events may be
|
||||||
|
* received for a case that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
ReportNodeFactory.this.refresh(true);
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2013 Basis Technology Corp.
|
* Copyright 2011-2015 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -51,26 +51,23 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
// Creation of a RootNode object corresponding to a Tags object is done
|
// Creation of a RootNode object corresponding to a Tags object is done
|
||||||
// by a CreateAutopsyNodeVisitor dispatched from the AbstractContentChildren
|
// by a CreateAutopsyNodeVisitor dispatched from the AbstractContentChildren
|
||||||
// override of Children.Keys<T>.createNodes().
|
// override of Children.Keys<T>.createNodes().
|
||||||
|
|
||||||
private final TagResults tagResults = new TagResults();
|
private final TagResults tagResults = new TagResults();
|
||||||
private final String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text");
|
private final String DISPLAY_NAME = NbBundle.getMessage(RootNode.class, "TagsNode.displayName.text");
|
||||||
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T accept(AutopsyItemVisitor<T> v) {
|
public <T> T accept(AutopsyItemVisitor<T> v) {
|
||||||
return v.visit(this);
|
return v.visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class largely does nothing except act as a top-level object that
|
* This class largely does nothing except act as a top-level object that the
|
||||||
* the other nodes can listen to. This mimics what other nodes have (keword search, etc.),
|
* other nodes can listen to. This mimics what other nodes have (keword
|
||||||
* but theirs stores data.
|
* search, etc.), but theirs stores data.
|
||||||
*/
|
*/
|
||||||
private class TagResults extends Observable {
|
private class TagResults extends Observable {
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
setChanged();
|
setChanged();
|
||||||
notifyObservers();
|
notifyObservers();
|
||||||
@ -123,20 +120,56 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
String eventType = evt.getPropertyName();
|
String eventType = evt.getPropertyName();
|
||||||
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
||||||
/* Note: this is a hack. In an ideal world, TagsManager
|
/**
|
||||||
* would fire events so that the directory tree would
|
* Checking for a current case is a stop gap measure until a
|
||||||
* refresh. But, we haven't had a chance to add that so, we
|
* different way of handling the closing of cases is worked
|
||||||
* fire these events and the tree refreshes based on them. */
|
* out. Currently, remote events may be received for a case
|
||||||
if ((((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT)
|
* that is already closed.
|
||||||
|| ((ModuleDataEvent) evt.getOldValue()).getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE) {
|
*/
|
||||||
refresh(true);
|
try {
|
||||||
tagResults.update();
|
Case.getCurrentCase();
|
||||||
|
/**
|
||||||
|
* There are two things to note here. * First, even with
|
||||||
|
* the check above, it is still possible that the case
|
||||||
|
* will be closed in a different thread before this code
|
||||||
|
* executes. If that happens, it is possible for the
|
||||||
|
* event to have a null oldValue. Second, the use of
|
||||||
|
* deprecated artifact types here is explained by the
|
||||||
|
* fact that in an ideal world, the TagsManager would
|
||||||
|
* fire tag-related events so that the tags tree would
|
||||||
|
* refresh. But, we haven't had a chance to add that, so
|
||||||
|
* we fire these events with bogus artifacts to indicate
|
||||||
|
* a tree refresh is required.
|
||||||
|
*/
|
||||||
|
ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue();
|
||||||
|
if (null != eventData
|
||||||
|
&& (eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT
|
||||||
|
|| eventData.getArtifactType() == BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE)) {
|
||||||
|
refresh(true);
|
||||||
|
tagResults.update();
|
||||||
|
}
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
} else if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
||||||
refresh(true);
|
/**
|
||||||
tagResults.update();
|
* Checking for a current case is a stop gap measure until a
|
||||||
}
|
* different way of handling the closing of cases is worked
|
||||||
else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
refresh(true);
|
||||||
|
tagResults.update();
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||||
// case was closed. Remove listeners so that this can be garbage collected
|
// case was closed. Remove listeners so that this can be garbage collected
|
||||||
if (evt.getNewValue() == null) {
|
if (evt.getNewValue() == null) {
|
||||||
removeNotify();
|
removeNotify();
|
||||||
@ -187,15 +220,15 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Instances of this class are elements of Node hierarchies consisting of
|
* Instances of this class are elements of Node hierarchies consisting of
|
||||||
* content and blackboard artifact tags, grouped first by tag type, then by tag
|
* content and blackboard artifact tags, grouped first by tag type, then by
|
||||||
* name.
|
* tag name.
|
||||||
*/
|
*/
|
||||||
public class TagNameNode extends DisplayableItemNode implements Observer {
|
public class TagNameNode extends DisplayableItemNode implements Observer {
|
||||||
|
|
||||||
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
||||||
private final String BOOKMARK_TAG_ICON_PATH = "org/sleuthkit/autopsy/images/star-bookmark-icon-16.png"; //NON-NLS
|
private final String BOOKMARK_TAG_ICON_PATH = "org/sleuthkit/autopsy/images/star-bookmark-icon-16.png"; //NON-NLS
|
||||||
private final TagName tagName;
|
private final TagName tagName;
|
||||||
|
|
||||||
public TagNameNode(TagName tagName) {
|
public TagNameNode(TagName tagName) {
|
||||||
super(Children.create(new TagTypeNodeFactory(tagName), true), Lookups.singleton(NbBundle.getMessage(TagNameNode.class, "TagNameNode.namePlusTags.text", tagName.getDisplayName())));
|
super(Children.create(new TagTypeNodeFactory(tagName), true), Lookups.singleton(NbBundle.getMessage(TagNameNode.class, "TagNameNode.namePlusTags.text", tagName.getDisplayName())));
|
||||||
this.tagName = tagName;
|
this.tagName = tagName;
|
||||||
@ -250,12 +283,13 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
updateDisplayName();
|
updateDisplayName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates nodes for the two types of tags: file and artifact.
|
* Creates nodes for the two types of tags: file and artifact. Does not need
|
||||||
* Does not need observer / messages since it always has the same children
|
* observer / messages since it always has the same children
|
||||||
*/
|
*/
|
||||||
private class TagTypeNodeFactory extends ChildFactory<String> {
|
private class TagTypeNodeFactory extends ChildFactory<String> {
|
||||||
|
|
||||||
private final TagName tagName;
|
private final TagName tagName;
|
||||||
private final String CONTENT_TAG_TYPE_NODE_KEY = NbBundle.getMessage(TagNameNode.class, "TagNameNode.contentTagTypeNodeKey.text");
|
private final String CONTENT_TAG_TYPE_NODE_KEY = NbBundle.getMessage(TagNameNode.class, "TagNameNode.contentTagTypeNodeKey.text");
|
||||||
private final String BLACKBOARD_ARTIFACT_TAG_TYPE_NODE_KEY = NbBundle.getMessage(TagNameNode.class, "TagNameNode.bbArtTagTypeNodeKey.text");
|
private final String BLACKBOARD_ARTIFACT_TAG_TYPE_NODE_KEY = NbBundle.getMessage(TagNameNode.class, "TagNameNode.bbArtTagTypeNodeKey.text");
|
||||||
@ -284,19 +318,20 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String CONTENT_DISPLAY_NAME = NbBundle.getMessage(ContentTagTypeNode.class, "ContentTagTypeNode.displayName.text");
|
private final String CONTENT_DISPLAY_NAME = NbBundle.getMessage(ContentTagTypeNode.class, "ContentTagTypeNode.displayName.text");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Node for the content tags. Children are specific tags.
|
* Node for the content tags. Children are specific tags. Instances of this
|
||||||
* Instances of this class are are elements of a directory tree sub-tree
|
* class are are elements of a directory tree sub-tree consisting of content
|
||||||
* consisting of content and blackboard artifact tags, grouped first by tag
|
* and blackboard artifact tags, grouped first by tag type, then by tag
|
||||||
* type, then by tag name.
|
* name.
|
||||||
*/
|
*/
|
||||||
public class ContentTagTypeNode extends DisplayableItemNode implements Observer {
|
public class ContentTagTypeNode extends DisplayableItemNode implements Observer {
|
||||||
|
|
||||||
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
||||||
private TagName tagName;
|
private TagName tagName;
|
||||||
|
|
||||||
public ContentTagTypeNode(TagName tagName) {
|
public ContentTagTypeNode(TagName tagName) {
|
||||||
super(Children.create(new ContentTagNodeFactory(tagName), true), Lookups.singleton(tagName.getDisplayName() + " " + CONTENT_DISPLAY_NAME));
|
super(Children.create(new ContentTagNodeFactory(tagName), true), Lookups.singleton(tagName.getDisplayName() + " " + CONTENT_DISPLAY_NAME));
|
||||||
this.tagName = tagName;
|
this.tagName = tagName;
|
||||||
@ -305,7 +340,7 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
this.setIconBaseWithExtension(ICON_PATH);
|
this.setIconBaseWithExtension(ICON_PATH);
|
||||||
tagResults.addObserver(this);
|
tagResults.addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateDisplayName() {
|
private void updateDisplayName() {
|
||||||
long tagsCount = 0;
|
long tagsCount = 0;
|
||||||
try {
|
try {
|
||||||
@ -341,10 +376,11 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
@Override
|
@Override
|
||||||
public void update(Observable o, Object arg) {
|
public void update(Observable o, Object arg) {
|
||||||
updateDisplayName();
|
updateDisplayName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ContentTagNodeFactory extends ChildFactory<ContentTag> implements Observer {
|
private class ContentTagNodeFactory extends ChildFactory<ContentTag> implements Observer {
|
||||||
|
|
||||||
private final TagName tagName;
|
private final TagName tagName;
|
||||||
|
|
||||||
ContentTagNodeFactory(TagName tagName) {
|
ContentTagNodeFactory(TagName tagName) {
|
||||||
@ -377,13 +413,15 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final String ARTIFACT_DISPLAY_NAME = NbBundle.getMessage(BlackboardArtifactTagTypeNode.class, "BlackboardArtifactTagTypeNode.displayName.text");
|
private final String ARTIFACT_DISPLAY_NAME = NbBundle.getMessage(BlackboardArtifactTagTypeNode.class, "BlackboardArtifactTagTypeNode.displayName.text");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instances of this class are elements in a sub-tree of the Autopsy
|
* Instances of this class are elements in a sub-tree of the Autopsy
|
||||||
* presentation of the SleuthKit data model. The sub-tree consists of content
|
* presentation of the SleuthKit data model. The sub-tree consists of
|
||||||
* and blackboard artifact tags, grouped first by tag type, then by tag name.
|
* content and blackboard artifact tags, grouped first by tag type, then by
|
||||||
|
* tag name.
|
||||||
*/
|
*/
|
||||||
public class BlackboardArtifactTagTypeNode extends DisplayableItemNode implements Observer {
|
public class BlackboardArtifactTagTypeNode extends DisplayableItemNode implements Observer {
|
||||||
|
|
||||||
private TagName tagName;
|
private TagName tagName;
|
||||||
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
private final String ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; //NON-NLS
|
||||||
|
|
||||||
@ -395,7 +433,7 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
updateDisplayName();
|
updateDisplayName();
|
||||||
tagResults.addObserver(this);
|
tagResults.addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateDisplayName() {
|
private void updateDisplayName() {
|
||||||
long tagsCount = 0;
|
long tagsCount = 0;
|
||||||
try {
|
try {
|
||||||
@ -435,28 +473,29 @@ public class Tags implements AutopsyVisitableItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class BlackboardArtifactTagNodeFactory extends ChildFactory<BlackboardArtifactTag> {
|
private class BlackboardArtifactTagNodeFactory extends ChildFactory<BlackboardArtifactTag> {
|
||||||
private final TagName tagName;
|
|
||||||
|
|
||||||
BlackboardArtifactTagNodeFactory(TagName tagName) {
|
private final TagName tagName;
|
||||||
super();
|
|
||||||
this.tagName = tagName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
BlackboardArtifactTagNodeFactory(TagName tagName) {
|
||||||
protected boolean createKeys(List<BlackboardArtifactTag> keys) {
|
super();
|
||||||
try {
|
this.tagName = tagName;
|
||||||
// Use the blackboard artifact tags bearing the specified tag name as the keys.
|
}
|
||||||
keys.addAll(Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName));
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
Logger.getLogger(BlackboardArtifactTagNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(BlackboardArtifactTag key) {
|
protected boolean createKeys(List<BlackboardArtifactTag> keys) {
|
||||||
// The blackboard artifact tags to be wrapped are used as the keys.
|
try {
|
||||||
return new BlackboardArtifactTagNode(key);
|
// Use the blackboard artifact tags bearing the specified tag name as the keys.
|
||||||
}
|
keys.addAll(Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByTagName(tagName));
|
||||||
}
|
} catch (TskCoreException ex) {
|
||||||
|
Logger.getLogger(BlackboardArtifactTagNodeFactory.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Node createNodeForKey(BlackboardArtifactTag key) {
|
||||||
|
// The blackboard artifact tags to be wrapped are used as the keys.
|
||||||
|
return new BlackboardArtifactTagNode(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@ import java.util.logging.Level;
|
|||||||
import java.util.prefs.PreferenceChangeEvent;
|
import java.util.prefs.PreferenceChangeEvent;
|
||||||
import java.util.prefs.PreferenceChangeListener;
|
import java.util.prefs.PreferenceChangeListener;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import javax.swing.JPanel;
|
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.tree.TreeSelectionModel;
|
import javax.swing.tree.TreeSelectionModel;
|
||||||
import org.openide.explorer.ExplorerManager;
|
import org.openide.explorer.ExplorerManager;
|
||||||
@ -524,60 +523,83 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
String changed = evt.getPropertyName();
|
if (IngestManager.getInstance().isRunningInteractively()) {
|
||||||
Object oldValue = evt.getOldValue();
|
String changed = evt.getPropertyName();
|
||||||
Object newValue = evt.getNewValue();
|
if (changed.equals(Case.Events.CURRENT_CASE.toString())) { // changed current case
|
||||||
if (changed.equals(Case.Events.CURRENT_CASE.toString())) { // changed current case
|
// When a case is closed, the old value of this property is the
|
||||||
// When a case is closed, the old value of this property is the
|
// closed Case object and the new value is null. When a case is
|
||||||
// closed Case object and the new value is null. When a case is
|
// opened, the old value is null and the new value is the new Case
|
||||||
// opened, the old value is null and the new value is the new Case
|
// object.
|
||||||
// object.
|
// @@@ This needs to be revisited. Perhaps case closed and case
|
||||||
// @@@ This needs to be revisited. Perhaps case closed and case
|
// opened events instead of property change events would be a better
|
||||||
// opened events instead of property change events would be a better
|
// solution. Either way, more probably needs to be done to clean up
|
||||||
// solution. Either way, more probably needs to be done to clean up
|
// data model objects when a case is closed.
|
||||||
// data model objects when a case is closed.
|
if (evt.getOldValue() != null && evt.getNewValue() == null) {
|
||||||
if (oldValue != null && newValue == null) {
|
// The current case has been closed. Reset the ExplorerManager.
|
||||||
// The current case has been closed. Reset the ExplorerManager.
|
SwingUtilities.invokeLater(() -> {
|
||||||
SwingUtilities.invokeLater(() -> {
|
Node emptyNode = new AbstractNode(Children.LEAF);
|
||||||
Node emptyNode = new AbstractNode(Children.LEAF);
|
em.setRootContext(emptyNode);
|
||||||
em.setRootContext(emptyNode);
|
});
|
||||||
});
|
} else if (evt.getNewValue() != null) {
|
||||||
} else if (newValue != null) {
|
// A new case has been opened. Reset the ExplorerManager.
|
||||||
// A new case has been opened. Reset the ExplorerManager.
|
Case newCase = (Case) evt.getNewValue();
|
||||||
Case newCase = (Case) newValue;
|
final String newCaseName = newCase.getName();
|
||||||
final String newCaseName = newCase.getName();
|
SwingUtilities.invokeLater(() -> {
|
||||||
SwingUtilities.invokeLater(() -> {
|
em.getRootContext().setName(newCaseName);
|
||||||
em.getRootContext().setName(newCaseName);
|
em.getRootContext().setDisplayName(newCaseName);
|
||||||
em.getRootContext().setDisplayName(newCaseName);
|
|
||||||
|
|
||||||
// Reset the forward and back
|
// Reset the forward and back
|
||||||
// buttons. Note that a call to CoreComponentControl.openCoreWindows()
|
// buttons. Note that a call to CoreComponentControl.openCoreWindows()
|
||||||
// by the new Case object will lead to a componentOpened() call
|
// by the new Case object will lead to a componentOpened() call
|
||||||
// that will repopulate the tree.
|
// that will repopulate the tree.
|
||||||
// @@@ The repopulation of the tree in this fashion also merits
|
// @@@ The repopulation of the tree in this fashion also merits
|
||||||
// reconsideration.
|
// reconsideration.
|
||||||
resetHistory();
|
resetHistory();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} // if the image is added to the case
|
||||||
|
else if (changed.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
||||||
|
/**
|
||||||
|
* Checking for a current case is a stop gap measure until a
|
||||||
|
* different way of handling the closing of cases is worked out.
|
||||||
|
* Currently, remote events may be received for a case that is
|
||||||
|
* already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
CoreComponentControl.openCoreWindows();
|
||||||
|
SwingUtilities.invokeLater(this::componentOpened);
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
} // change in node selection
|
||||||
|
else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
respondSelection((Node[]) evt.getOldValue(), (Node[]) evt.getNewValue());
|
||||||
});
|
});
|
||||||
}
|
} else if (changed.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
||||||
} // if the image is added to the case
|
|
||||||
else if (changed.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
|
||||||
if (IngestManager.getInstance().isRunningInteractively()) {
|
|
||||||
CoreComponentControl.openCoreWindows();
|
|
||||||
}
|
|
||||||
SwingUtilities.invokeLater(this::componentOpened);
|
|
||||||
} // change in node selection
|
|
||||||
else if (changed.equals(ExplorerManager.PROP_SELECTED_NODES)) {
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
respondSelection((Node[]) oldValue, (Node[]) newValue);
|
|
||||||
});
|
|
||||||
} else if (changed.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
|
|
||||||
// nothing to do here.
|
// nothing to do here.
|
||||||
// all nodes should be listening for these events and update accordingly.
|
// all nodes should be listening for these events and update accordingly.
|
||||||
} else if (changed.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
} else if (changed.equals(IngestManager.IngestJobEvent.COMPLETED.toString())
|
||||||
|| changed.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
|
|| changed.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|
||||||
SwingUtilities.invokeLater(this::refreshDataSourceTree);
|
|| changed.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
|
||||||
} else if (changed.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
|
/**
|
||||||
SwingUtilities.invokeLater(this::refreshDataSourceTree);
|
* Checking for a current case is a stop gap measure until a
|
||||||
|
* different way of handling the closing of cases is worked out.
|
||||||
|
* Currently, remote events may be received for a case that is
|
||||||
|
* already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
SwingUtilities.invokeLater(this::refreshDataSourceTree);
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,9 @@ import javax.jms.ObjectMessage;
|
|||||||
import javax.jms.Session;
|
import javax.jms.Session;
|
||||||
import javax.jms.Topic;
|
import javax.jms.Topic;
|
||||||
import org.apache.activemq.ActiveMQConnectionFactory;
|
import org.apache.activemq.ActiveMQConnectionFactory;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides thread-safe support for publishing events to registered subscribers
|
* Provides thread-safe support for publishing events to registered subscribers
|
||||||
@ -99,7 +101,7 @@ final class RemoteEventPublisher {
|
|||||||
}
|
}
|
||||||
if (null != consumer) {
|
if (null != consumer) {
|
||||||
consumer.close();
|
consumer.close();
|
||||||
}
|
}
|
||||||
if (null != session) {
|
if (null != session) {
|
||||||
session.close();
|
session.close();
|
||||||
}
|
}
|
||||||
@ -134,21 +136,40 @@ final class RemoteEventPublisher {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(Message message) {
|
public void onMessage(Message message) {
|
||||||
try {
|
if (IngestManager.getInstance().isRunningInteractively()) {
|
||||||
if (message instanceof ObjectMessage) {
|
/**
|
||||||
ObjectMessage objectMessage = (ObjectMessage) message;
|
* This is a stop gap measure until a different way of handling
|
||||||
Object object = objectMessage.getObject();
|
* the closing of cases is worked out. Currently,
|
||||||
if (object instanceof AutopsyEvent) {
|
* Case.currentCase is set to null before
|
||||||
AutopsyEvent event = (AutopsyEvent) object;
|
* Case.Event.CURRENT_CASE is published. That means that clients
|
||||||
event.setSourceType(AutopsyEvent.SourceType.REMOTE);
|
* of this class have not had the chance to close their remote
|
||||||
localPublisher.publish(event);
|
* event channels and remote events may be received for a case
|
||||||
}
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do not publish the event.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (message instanceof ObjectMessage) {
|
||||||
|
ObjectMessage objectMessage = (ObjectMessage) message;
|
||||||
|
Object object = objectMessage.getObject();
|
||||||
|
if (object instanceof AutopsyEvent) {
|
||||||
|
AutopsyEvent event = (AutopsyEvent) object;
|
||||||
|
event.setSourceType(AutopsyEvent.SourceType.REMOTE);
|
||||||
|
localPublisher.publish(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error receiving message", ex);
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
|
||||||
logger.log(Level.SEVERE, "Error receiving message", ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ class DateSearchFilter extends AbstractFileSearchFilter<DateSearchPanel> {
|
|||||||
public String getPredicate() throws FilterValidationException {
|
public String getPredicate() throws FilterValidationException {
|
||||||
String query = "NULL";
|
String query = "NULL";
|
||||||
DateSearchPanel panel = this.getComponent();
|
DateSearchPanel panel = this.getComponent();
|
||||||
|
|
||||||
// first, get the selected timeZone from the dropdown list
|
// first, get the selected timeZone from the dropdown list
|
||||||
String tz = this.getComponent().getTimeZoneComboBox().getSelectedItem().toString();
|
String tz = this.getComponent().getTimeZoneComboBox().getSelectedItem().toString();
|
||||||
String tzID = tz.substring(tz.indexOf(" ") + 1); // 1 index after the space is the ID
|
String tzID = tz.substring(tz.indexOf(" ") + 1); // 1 index after the space is the ID
|
||||||
@ -126,7 +126,7 @@ class DateSearchFilter extends AbstractFileSearchFilter<DateSearchPanel> {
|
|||||||
toDate = fromDate;
|
toDate = fromDate;
|
||||||
fromDate = temp;
|
fromDate = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean modifiedChecked = panel.getModifiedCheckBox().isSelected();
|
final boolean modifiedChecked = panel.getModifiedCheckBox().isSelected();
|
||||||
final boolean changedChecked = panel.getChangedCheckBox().isSelected();
|
final boolean changedChecked = panel.getChangedCheckBox().isSelected();
|
||||||
final boolean accessedChecked = panel.getAccessedCheckBox().isSelected();
|
final boolean accessedChecked = panel.getAccessedCheckBox().isSelected();
|
||||||
@ -253,7 +253,20 @@ class DateSearchFilter extends AbstractFileSearchFilter<DateSearchPanel> {
|
|||||||
break;
|
break;
|
||||||
case DATA_SOURCE_ADDED:
|
case DATA_SOURCE_ADDED:
|
||||||
case DATA_SOURCE_DELETED:
|
case DATA_SOURCE_DELETED:
|
||||||
SwingUtilities.invokeLater(DateSearchFilter.this::updateTimeZoneList);
|
/**
|
||||||
|
* Checking for a current case is a stop gap measure until a
|
||||||
|
* different way of handling the closing of cases is worked
|
||||||
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
SwingUtilities.invokeLater(DateSearchFilter.this::updateTimeZoneList);
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ public final class BlackboardPostEvent extends AutopsyEvent implements Serializa
|
|||||||
*/
|
*/
|
||||||
public BlackboardPostEvent(ModuleDataEvent eventData) {
|
public BlackboardPostEvent(ModuleDataEvent eventData) {
|
||||||
/**
|
/**
|
||||||
* Putting a serializable data holding object into newValue to allow for
|
* Putting a serializable data holding object into oldValue to allow for
|
||||||
* lazy loading of the ModuleDataEvent object for remote events. This
|
* lazy loading of the ModuleDataEvent object for remote events. This
|
||||||
* bypasses the issues related to the serialization and de-serialization
|
* bypasses the issues related to the serialization and de-serialization
|
||||||
* of BlackboardArtifact objects when the event is published over a
|
* of BlackboardArtifact objects when the event is published over a
|
||||||
|
@ -680,10 +680,23 @@ public class TimeLineController {
|
|||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) {
|
switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) {
|
||||||
case FILE_DONE:
|
case FILE_DONE:
|
||||||
Platform.runLater(() -> {
|
/**
|
||||||
newEventsFlag.set(true);
|
* Checking for a current case is a stop gap measure until a
|
||||||
});
|
* different way of handling the closing of cases is worked
|
||||||
break;
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
newEventsFlag.set(true);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -696,9 +709,22 @@ public class TimeLineController {
|
|||||||
switch (IngestManager.IngestJobEvent.valueOf(evt.getPropertyName())) {
|
switch (IngestManager.IngestJobEvent.valueOf(evt.getPropertyName())) {
|
||||||
case CANCELLED:
|
case CANCELLED:
|
||||||
case COMPLETED:
|
case COMPLETED:
|
||||||
SwingUtilities.invokeLater(() -> {
|
/**
|
||||||
outOfDatePromptAndRebuild();
|
* Checking for a current case is a stop gap measure until a
|
||||||
});
|
* different way of handling the closing of cases is worked
|
||||||
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
outOfDatePromptAndRebuild();
|
||||||
|
});
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -711,9 +737,22 @@ public class TimeLineController {
|
|||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
switch (Case.Events.valueOf(evt.getPropertyName())) {
|
switch (Case.Events.valueOf(evt.getPropertyName())) {
|
||||||
case DATA_SOURCE_ADDED:
|
case DATA_SOURCE_ADDED:
|
||||||
SwingUtilities.invokeLater(() -> {
|
/**
|
||||||
outOfDatePromptAndRebuild();
|
* Checking for a current case is a stop gap measure until a
|
||||||
});
|
* different way of handling the closing of cases is worked
|
||||||
|
* out. Currently, remote events may be received for a case
|
||||||
|
* that is already closed.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
Case.getCurrentCase();
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
outOfDatePromptAndRebuild();
|
||||||
|
});
|
||||||
|
} catch (IllegalStateException notUsed) {
|
||||||
|
/**
|
||||||
|
* Case is closed, do nothing.
|
||||||
|
*/
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CURRENT_CASE:
|
case CURRENT_CASE:
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#Updated by build script
|
#Updated by build script
|
||||||
#Mon, 08 Jun 2015 11:37:44 -0400
|
#Fri, 19 Jun 2015 13:59:39 -0400
|
||||||
LBL_splash_window_title=Starting Autopsy
|
LBL_splash_window_title=Starting Autopsy
|
||||||
SPLASH_HEIGHT=314
|
SPLASH_HEIGHT=314
|
||||||
SPLASH_WIDTH=538
|
SPLASH_WIDTH=538
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#Updated by build script
|
#Updated by build script
|
||||||
#Mon, 08 Jun 2015 11:37:44 -0400
|
#Fri, 19 Jun 2015 13:59:39 -0400
|
||||||
|
|
||||||
CTL_MainWindow_Title=Autopsy 3.1.2
|
CTL_MainWindow_Title=Autopsy 3.1.2
|
||||||
CTL_MainWindow_Title_No_Project=Autopsy 3.1.2
|
CTL_MainWindow_Title_No_Project=Autopsy 3.1.2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user