Merge branch 'develop' into 2988-fix-cc-viewer

This commit is contained in:
Richard Cordovano 2017-09-06 10:20:43 -04:00 committed by GitHub
commit f9ca7b55f2
54 changed files with 904 additions and 588 deletions

View File

@ -377,7 +377,9 @@ public class Case {
*
* @param eventNames The events the subscriber is interested in.
* @param subscriber The subscriber (PropertyChangeListener) to add.
* @deprecated Use addEventTypeSubscriber instead.
*/
@Deprecated
public static void addEventSubscriber(Set<String> eventNames, PropertyChangeListener subscriber) {
eventPublisher.addSubscriber(eventNames, subscriber);
}
@ -385,9 +387,23 @@ public class Case {
/**
* Adds a subscriber to specific case events.
*
* @param eventName The event the subscriber is interested in.
* @param eventTypes The events the subscriber is interested in.
* @param subscriber The subscriber (PropertyChangeListener) to add.
*/
public static void addEventTypeSubscriber(Set<Events> eventTypes, PropertyChangeListener subscriber) {
eventTypes.forEach((Events event) -> {
eventPublisher.addSubscriber(event.toString(), subscriber);
});
}
/**
* Adds a subscriber to specific case events.
*
* @param eventName The event the subscriber is interested in.
* @param subscriber The subscriber (PropertyChangeListener) to add.
* @deprecated Use addEventTypeSubscriber instead.
*/
@Deprecated
public static void addEventSubscriber(String eventName, PropertyChangeListener subscriber) {
eventPublisher.addSubscriber(eventName, subscriber);
}
@ -412,6 +428,18 @@ public class Case {
eventPublisher.removeSubscriber(eventNames, subscriber);
}
/**
* Removes a subscriber to specific case events.
*
* @param eventTypes The events the subscriber is no longer interested in.
* @param subscriber The subscriber (PropertyChangeListener) to remove.
*/
public static void removeEventTypeSubscriber(Set<Events> eventTypes, PropertyChangeListener subscriber) {
eventTypes.forEach((Events event) -> {
eventPublisher.removeSubscriber(event.toString(), subscriber);
});
}
/**
* Checks if a case display name is valid, i.e., does not include any
* characters that cannot be used in file names.

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.casemodule;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.util.EnumSet;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.Action;
@ -49,7 +50,7 @@ final class CaseDeleteAction extends CallableSystemAction {
CaseDeleteAction() {
putValue(Action.NAME, NbBundle.getMessage(CaseDeleteAction.class, "CTL_CaseDeleteAction"));
this.setEnabled(false);
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), (PropertyChangeEvent evt) -> {
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent evt) -> {
setEnabled(null != evt.getNewValue() && UserPreferences.getMode() != UserPreferences.SelectedMode.REVIEW);
});
}

View File

@ -22,6 +22,7 @@ import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.util.EnumSet;
import javax.swing.Action;
import javax.swing.JDialog;
import javax.swing.SwingUtilities;
@ -42,7 +43,7 @@ final class CasePropertiesAction extends CallableSystemAction {
CasePropertiesAction() {
putValue(Action.NAME, NbBundle.getMessage(CasePropertiesAction.class, "CTL_CasePropertiesAction"));
this.setEnabled(false);
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), (PropertyChangeEvent evt) -> {
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent evt) -> {
setEnabled(null != evt.getNewValue());
});
}

View File

@ -24,9 +24,8 @@ import java.beans.PropertyChangeListener;
import java.io.Serializable;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@ -57,7 +56,8 @@ final class CollaborationMonitor {
private static final String EVENT_CHANNEL_NAME = "%s-Collaboration-Monitor-Events"; //NON-NLS
private static final String COLLABORATION_MONITOR_EVENT = "COLLABORATION_MONITOR_EVENT"; //NON-NLS
private static final Set<String> CASE_EVENTS_OF_INTEREST = new HashSet<>(Arrays.asList(new String[]{Case.Events.ADDING_DATA_SOURCE.toString(), Case.Events.DATA_SOURCE_ADDED.toString(), Case.Events.ADDING_DATA_SOURCE_FAILED.toString()}));
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.ADDING_DATA_SOURCE,
Case.Events.DATA_SOURCE_ADDED, Case.Events.ADDING_DATA_SOURCE_FAILED);
private static final int NUMBER_OF_PERIODIC_TASK_THREADS = 2;
private static final String PERIODIC_TASK_THREAD_NAME = "collab-monitor-periodic-tasks-%d"; //NON-NLS
private static final long HEARTBEAT_INTERVAL_MINUTES = 1;
@ -113,7 +113,7 @@ final class CollaborationMonitor {
*/
localTasksManager = new LocalTasksManager();
IngestManager.getInstance().addIngestJobEventListener(localTasksManager);
Case.addEventSubscriber(CASE_EVENTS_OF_INTEREST, localTasksManager);
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, localTasksManager);
/**
* Start periodic tasks that:
@ -141,7 +141,7 @@ final class CollaborationMonitor {
}
}
Case.removeEventSubscriber(CASE_EVENTS_OF_INTEREST, localTasksManager);
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, localTasksManager);
IngestManager.getInstance().removeIngestJobEventListener(localTasksManager);
if (null != eventPublisher) {

View File

@ -35,6 +35,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import static java.util.Objects.nonNull;
@ -153,7 +154,7 @@ public class ImageUtils {
SUPPORTED_IMAGE_MIME_TYPES.removeIf("application/octet-stream"::equals); //NON-NLS
//Clear the file map when the case changes, so we don't accidentaly get images from the old case.
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), evt -> cacheFileMap.clear());
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), evt -> cacheFileMap.clear());
}
/**

View File

@ -21,8 +21,10 @@ package org.sleuthkit.autopsy.datamodel;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
@ -53,6 +55,9 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
@NbBundle.Messages("AbstractAbstractFileNode.addFileProperty.desc=no description")
private static final String NO_DESCR = AbstractAbstractFileNode_addFileProperty_desc();
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE,
Case.Events.CONTENT_TAG_ADDED, Case.Events.CONTENT_TAG_DELETED);
/**
* @param abstractFile file to wrap
*/
@ -67,13 +72,14 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
IngestManager.getInstance().addIngestModuleEventListener(pcl);
}
}
// Listen for case events so that we can detect when case is closed
Case.addPropertyChangeListener(pcl);
// Listen for case events so that we can detect when the case is closed
// or when tags are added.
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
}
private void removeListeners() {
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
}
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
@ -95,7 +101,11 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
// If so, refresh our children.
try {
Children parentsChildren = getParentNode().getChildren();
if (parentsChildren != null) {
// We only want to refresh our parents children if we are in the
// data sources branch of the tree. The parent nodes in other
// branches of the tree (e.g. File Types and Deleted Files) do
// not need to be refreshed.
if (parentsChildren instanceof ContentChildren) {
((ContentChildren) parentsChildren).refreshChildren();
parentsChildren.getNodesCount();
}

View File

@ -25,31 +25,29 @@ import java.beans.PropertyChangeListener;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.stream.Collectors;
import javax.swing.Action;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.Sheet;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.WeakListeners;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
import static org.sleuthkit.autopsy.datamodel.DataModelActionsFactory.VIEW_IN_NEW_WINDOW;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import static org.sleuthkit.autopsy.datamodel.DisplayableItemNode.findLinked;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction;
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
import org.sleuthkit.datamodel.AbstractFile;
@ -68,6 +66,11 @@ import org.sleuthkit.datamodel.TskCoreException;
public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifact> {
private static final Logger LOGGER = Logger.getLogger(BlackboardArtifactNode.class.getName());
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED,
Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED,
Case.Events.CONTENT_TAG_ADDED,
Case.Events.CONTENT_TAG_DELETED,
Case.Events.CURRENT_CASE);
private static Cache<Long, Content> contentCache = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES).
@ -128,8 +131,9 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
};
/**
* Construct blackboard artifact node from an artifact and using provided
* icon
* Construct blackboard artifact node from an artifact, overriding the
* standard icon with the one at the path provided.
*
*
* @param artifact artifact to encapsulate
* @param iconPath icon to use for the artifact
@ -140,9 +144,9 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
this.artifact = artifact;
// Look for associated Content i.e. the source file for the artifact
for (Content content : this.getLookup().lookupAll(Content.class)) {
if ( (content != null) && (!(content instanceof BlackboardArtifact)) ){
this.associated = content;
for (Content lookupContent : this.getLookup().lookupAll(Content.class)) {
if ((lookupContent != null) && (!(lookupContent instanceof BlackboardArtifact))) {
this.associated = lookupContent;
break;
}
}
@ -150,7 +154,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
this.setName(Long.toString(artifact.getArtifactID()));
this.setDisplayName();
this.setIconBaseWithExtension(iconPath);
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, WeakListeners.propertyChange(pcl, null));
}
/**
@ -160,12 +164,11 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
* @param artifact artifact to encapsulate
*/
public BlackboardArtifactNode(BlackboardArtifact artifact) {
this(artifact, ExtractedContent.getIconFilePath(artifact.getArtifactTypeID()));
}
private void removeListeners() {
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
}
public BlackboardArtifact getArtifact() {
@ -268,7 +271,6 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
return srcName;
}
@NbBundle.Messages({
"BlackboardArtifactNode.createSheet.artifactType.displayName=Artifact Type",
"BlackboardArtifactNode.createSheet.artifactType.name=Artifact Type",
@ -476,11 +478,9 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE.getTypeID()) {
}
else if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) {
addEmailMsgProperty (map, attribute);
}
else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
} else if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()) {
addEmailMsgProperty(map, attribute);
} else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
} else if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_TOOL_OUTPUT.getTypeID()
&& attributeTypeID == ATTRIBUTE_TYPE.TSK_TEXT.getTypeID()) {
@ -496,8 +496,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
value = value.substring(0, 512);
}
map.put(attribute.getAttributeType().getDisplayName(), value);
}
else {
} else {
map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
}
}
@ -506,14 +505,14 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
}
}
/**
/**
* Fill map with EmailMsg properties, not all attributes are filled
*
* @param map map with preserved ordering, where property names/values
* are put
* @param attribute attribute to check/fill as property
*/
private void addEmailMsgProperty(Map<String, Object> map, BlackboardAttribute attribute ) {
private void addEmailMsgProperty(Map<String, Object> map, BlackboardAttribute attribute) {
final int attributeTypeID = attribute.getAttributeType().getTypeID();
@ -523,23 +522,19 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_RTF.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_BCC.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CC.getTypeID()
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_HEADERS.getTypeID()
) {
|| attributeTypeID == ATTRIBUTE_TYPE.TSK_HEADERS.getTypeID()) {
// do nothing
}
else if (attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN.getTypeID()) {
} else if (attributeTypeID == ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN.getTypeID()) {
String value = attribute.getDisplayString();
if (value.length() > 160) {
value = value.substring(0, 160) + "...";
}
map.put(attribute.getAttributeType().getDisplayName(), value);
}
else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
} else if (attribute.getAttributeType().getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
map.put(attribute.getAttributeType().getDisplayName(), ContentUtils.getStringTime(attribute.getValueLong(), associated));
}
else {
} else {
map.put(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString());
}

View File

@ -22,6 +22,7 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.logging.Level;
import org.openide.nodes.Sheet;
@ -88,13 +89,13 @@ public class DataSourcesNode extends DisplayableItemNode {
@Override
protected void addNotify() {
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl);
reloadKeys();
}
@Override
protected void removeNotify() {
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.DATA_SOURCE_ADDED), pcl);
currentKeys.clear();
setKeys(Collections.<Content>emptySet());
}

View File

@ -22,9 +22,11 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
@ -173,24 +175,26 @@ public class DeletedContent implements AutopsyVisitableItem {
* Listens for case and ingest invest. Updates observers when events are
* fired. Other nodes are listening to this for changes.
*/
private final class DeletedContentsChildrenObservable extends Observable {
private static final class DeletedContentsChildrenObservable extends Observable {
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(
Case.Events.DATA_SOURCE_ADDED,
Case.Events.CURRENT_CASE
);
DeletedContentsChildrenObservable() {
IngestManager.getInstance().addIngestJobEventListener(pcl);
IngestManager.getInstance().addIngestModuleEventListener(pcl);
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
}
private void removeListeners() {
deleteObservers();
IngestManager.getInstance().removeIngestJobEventListener(pcl);
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
}
private final PropertyChangeListener pcl = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
String eventType = evt.getPropertyName();
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())) {
/**
@ -235,7 +239,6 @@ public class DeletedContent implements AutopsyVisitableItem {
}
maxFilesDialogShown = false;
}
}
};
private void update() {

View File

@ -23,6 +23,7 @@ import java.beans.PropertyChangeListener;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@ -285,7 +286,7 @@ public class EmailExtracted implements AutopsyVisitableItem {
protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(pcl);
IngestManager.getInstance().addIngestModuleEventListener(pcl);
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
emailResults.update();
emailResults.addObserver(this);
}
@ -294,7 +295,7 @@ public class EmailExtracted implements AutopsyVisitableItem {
protected void removeNotify() {
IngestManager.getInstance().removeIngestJobEventListener(pcl);
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
emailResults.deleteObserver(this);
}

View File

@ -23,6 +23,7 @@ import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
@ -251,14 +252,14 @@ public class ExtractedContent implements AutopsyVisitableItem {
protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(pcl);
IngestManager.getInstance().addIngestModuleEventListener(pcl);
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
}
@Override
protected void removeNotify() {
IngestManager.getInstance().removeIngestJobEventListener(pcl);
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
typeNodeList.clear();
}
@ -309,7 +310,7 @@ public class ExtractedContent implements AutopsyVisitableItem {
*/
public class TypeNode extends DisplayableItemNode {
private BlackboardArtifact.Type type;
private final BlackboardArtifact.Type type;
private long childCount = 0;
TypeNode(BlackboardArtifact.Type type) {

View File

@ -22,9 +22,11 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.logging.Level;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.ChildFactory;
@ -169,32 +171,32 @@ public class FileSize implements AutopsyVisitableItem {
* Listens for case and ingest invest. Updates observers when events are
* fired. Size-based nodes are listening to this for changes.
*/
private final class FileSizeRootChildrenObservable extends Observable {
private static final class FileSizeRootChildrenObservable extends Observable {
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.CURRENT_CASE);
FileSizeRootChildrenObservable() {
IngestManager.getInstance().addIngestJobEventListener(pcl);
IngestManager.getInstance().addIngestModuleEventListener(pcl);
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
}
private void removeListeners() {
deleteObservers();
IngestManager.getInstance().removeIngestJobEventListener(pcl);
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
}
private final PropertyChangeListener pcl = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
String eventType = evt.getPropertyName();
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.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.
* 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
@ -210,10 +212,10 @@ public class FileSize implements AutopsyVisitableItem {
|| eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())
|| eventType.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.
* 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();
@ -229,7 +231,6 @@ public class FileSize implements AutopsyVisitableItem {
removeListeners();
}
}
}
};
private void update() {

View File

@ -21,10 +21,11 @@ package org.sleuthkit.autopsy.datamodel;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.function.Function;
import java.util.Set;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.apache.commons.lang.StringUtils;
@ -39,8 +40,6 @@ import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesKey;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
@ -75,9 +74,11 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
private class FileTypesByExtObservable extends Observable {
private final PropertyChangeListener pcl;
private final Set<Case.Events> CASE_EVENTS_OF_INTEREST;
private FileTypesByExtObservable() {
super();
this.CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.CURRENT_CASE);
this.pcl = (PropertyChangeEvent evt) -> {
String eventType = evt.getPropertyName();
if (eventType.equals(IngestManager.IngestModuleEvent.CONTENT_CHANGED.toString())
@ -109,15 +110,14 @@ public final class FileTypesByExtension implements AutopsyVisitableItem {
IngestManager.getInstance().addIngestJobEventListener(pcl);
IngestManager.getInstance().addIngestModuleEventListener(pcl);
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
}
private void removeListeners() {
deleteObservers();
IngestManager.getInstance().removeIngestJobEventListener(pcl);
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
}
private void update() {

View File

@ -24,11 +24,13 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
@ -44,7 +46,6 @@ import static org.sleuthkit.autopsy.core.UserPreferences.hideSlackFilesInViewsTr
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.FileTypes.FileTypesKey;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
@ -79,6 +80,8 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
*/
private final PropertyChangeListener pcl;
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.DATA_SOURCE_ADDED, Case.Events.CURRENT_CASE);
/**
* Create the base expression used as the where clause in the queries for
* files by mime type. Filters out certain kinds of files and directories,
@ -102,7 +105,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
private void removeListeners() {
deleteObservers();
IngestManager.getInstance().removeIngestJobEventListener(pcl);
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
}
/**
@ -175,7 +178,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
}
};
IngestManager.getInstance().addIngestJobEventListener(pcl);
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
populateHashMap();
}

View File

@ -24,6 +24,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@ -252,7 +253,7 @@ public class HashsetHits implements AutopsyVisitableItem {
protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(pcl);
IngestManager.getInstance().addIngestModuleEventListener(pcl);
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
hashsetResults.update();
hashsetResults.addObserver(this);
}
@ -261,7 +262,7 @@ public class HashsetHits implements AutopsyVisitableItem {
protected void removeNotify() {
IngestManager.getInstance().removeIngestJobEventListener(pcl);
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
hashsetResults.deleteObserver(this);
}

View File

@ -24,6 +24,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.logging.Level;
import javax.swing.Action;
@ -79,12 +80,12 @@ public class ImageNode extends AbstractContentNode<Image> {
// Listen for ingest events so that we can detect new added files (e.g. carved)
IngestManager.getInstance().addIngestModuleEventListener(pcl);
// Listen for case events so that we can detect when case is closed
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
}
private void removeListeners() {
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
}
/**

View File

@ -24,6 +24,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@ -188,9 +189,7 @@ public class InterestingHits implements AutopsyVisitableItem {
* 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() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
private final PropertyChangeListener pcl = (PropertyChangeEvent evt) -> {
String eventType = evt.getPropertyName();
if (eventType.equals(IngestManager.IngestModuleEvent.DATA_ADDED.toString())) {
/**
@ -240,14 +239,13 @@ public class InterestingHits implements AutopsyVisitableItem {
skCase = null;
}
}
}
};
@Override
protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(pcl);
IngestManager.getInstance().addIngestModuleEventListener(pcl);
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
interestingResults.update();
interestingResults.addObserver(this);
}
@ -256,7 +254,7 @@ public class InterestingHits implements AutopsyVisitableItem {
protected void removeNotify() {
IngestManager.getInstance().removeIngestJobEventListener(pcl);
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
interestingResults.deleteObserver(this);
}

View File

@ -24,6 +24,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
@ -455,7 +456,7 @@ public class KeywordHits implements AutopsyVisitableItem {
protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(pcl);
IngestManager.getInstance().addIngestModuleEventListener(pcl);
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
keywordResults.update();
super.addNotify();
}
@ -464,7 +465,7 @@ public class KeywordHits implements AutopsyVisitableItem {
protected void removeNotify() {
IngestManager.getInstance().removeIngestJobEventListener(pcl);
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
super.removeNotify();
}

View File

@ -28,7 +28,9 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.Action;
@ -103,8 +105,10 @@ public final class Reports implements AutopsyVisitableItem {
*/
private static final class ReportNodeFactory extends ChildFactory<Report> {
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.REPORT_ADDED, Case.Events.REPORT_DELETED);
ReportNodeFactory() {
Case.addPropertyChangeListener((PropertyChangeEvent evt) -> {
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, (PropertyChangeEvent evt) -> {
String eventType = evt.getPropertyName();
if (eventType.equals(Case.Events.REPORT_ADDED.toString()) || eventType.equals(Case.Events.REPORT_DELETED.toString())) {
/**

View File

@ -21,9 +21,11 @@ package org.sleuthkit.autopsy.datamodel;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.logging.Level;
import org.openide.nodes.ChildFactory;
import org.openide.nodes.Children;
@ -118,6 +120,12 @@ public class Tags implements AutopsyVisitableItem {
private class TagNameNodeFactory extends ChildFactory.Detachable<TagName> implements Observer {
private final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED,
Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED,
Case.Events.CONTENT_TAG_ADDED,
Case.Events.CONTENT_TAG_DELETED,
Case.Events.CURRENT_CASE);
private final PropertyChangeListener pcl = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
@ -171,7 +179,7 @@ public class Tags implements AutopsyVisitableItem {
protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(pcl);
IngestManager.getInstance().addIngestModuleEventListener(pcl);
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
tagResults.update();
tagResults.addObserver(this);
}
@ -180,7 +188,7 @@ public class Tags implements AutopsyVisitableItem {
protected void removeNotify() {
IngestManager.getInstance().removeIngestJobEventListener(pcl);
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, pcl);
tagResults.deleteObserver(this);
}

View File

@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.datamodel;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import javax.swing.Action;
import org.openide.nodes.Children;
@ -72,12 +73,12 @@ public class VolumeNode extends AbstractContentNode<Volume> {
// Listen for ingest events so that we can detect new added files (e.g. carved)
IngestManager.getInstance().addIngestModuleEventListener(pcl);
// Listen for case events so that we can detect when case is closed
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
}
private void removeListeners() {
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
}
/*

View File

@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
@ -311,7 +312,7 @@ final public class Accounts implements AutopsyVisitableItem {
protected void removeNotify() {
IngestManager.getInstance().removeIngestJobEventListener(pcl);
IngestManager.getInstance().removeIngestModuleEventListener(pcl);
Case.removePropertyChangeListener(pcl);
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
super.removeNotify();
}
@ -319,7 +320,7 @@ final public class Accounts implements AutopsyVisitableItem {
protected void addNotify() {
IngestManager.getInstance().addIngestJobEventListener(pcl);
IngestManager.getInstance().addIngestModuleEventListener(pcl);
Case.addPropertyChangeListener(pcl);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), pcl);
super.addNotify();
refreshKeys();
}

View File

@ -26,6 +26,7 @@ import java.beans.PropertyVetoException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
@ -151,7 +152,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
}
}
});
Case.addEventSubscriber(new HashSet<>(Arrays.asList(Case.Events.CURRENT_CASE.toString(), Case.Events.DATA_SOURCE_ADDED.toString())), this);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE, Case.Events.DATA_SOURCE_ADDED), this);
this.em.addPropertyChangeListener(this);
IngestManager.getInstance().addIngestJobEventListener(this);
IngestManager.getInstance().addIngestModuleEventListener(this);

View File

@ -56,3 +56,5 @@ SizeSearchPanel.sizeCompareComboBox.lessThan=less than
MimeTypePanel.jLabel1.text=*Note: Multiple MIME types can be selected
FileSearchPanel.searchButton.text=Search
MimeTypePanel.mimeTypeCheckBox.text=MIME Type:
HashSearchPanel.md5CheckBox.text=MD5:
HashSearchPanel.emptyHashMsg.text=Must enter something for hash search.

View File

@ -28,6 +28,7 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@ -53,6 +54,9 @@ class DateSearchFilter extends AbstractFileSearchFilter<DateSearchPanel> {
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy");
private static final String SEPARATOR = "SEPARATOR"; //NON-NLS
private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(Case.Events.CURRENT_CASE,
Case.Events.DATA_SOURCE_ADDED, Case.Events.DATA_SOURCE_DELETED);
/**
* New DateSearchFilter with the default panel
*/
@ -62,7 +66,7 @@ class DateSearchFilter extends AbstractFileSearchFilter<DateSearchPanel> {
private DateSearchFilter(DateSearchPanel panel) {
super(panel);
Case.addPropertyChangeListener(this.new CasePropertyChangeListener());
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, this.new CasePropertyChangeListener());
}
@Override

View File

@ -20,7 +20,7 @@ package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.EnumSet;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
@ -35,14 +35,10 @@ final class FileSearchAction extends CallableSystemAction implements FileSearchP
FileSearchAction() {
super();
setEnabled(Case.isCaseOpen());
Case.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent evt) -> {
if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
setEnabled(evt.getNewValue() != null);
}
}
});
}

View File

@ -95,6 +95,8 @@ class FileSearchPanel extends javax.swing.JPanel {
this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "FileSearchPanel.filterTitle.knownStatus"), new KnownStatusSearchFilter()));
this.filterAreas.add(new FilterArea(NbBundle.getMessage(this.getClass(), "HashSearchPanel.md5CheckBox.text"), new HashSearchFilter()));
for (FilterArea fa : this.filterAreas) {
fa.setMaximumSize(new Dimension(Integer.MAX_VALUE, fa.getMinimumSize().height));
fa.setAlignmentX(Component.LEFT_ALIGNMENT);

View File

@ -0,0 +1,66 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionListener;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.filesearch.FileSearchFilter.FilterValidationException;
/**
*
*/
class HashSearchFilter extends AbstractFileSearchFilter<HashSearchPanel> {
private static final String EMPTY_HASH_MESSAGE = NbBundle
.getMessage(HashSearchFilter.class, "HashSearchPanel.emptyHashMsg.text");
public HashSearchFilter() {
this(new HashSearchPanel());
}
public HashSearchFilter(HashSearchPanel component) {
super(component);
}
@Override
public boolean isEnabled() {
return this.getComponent().getHashCheckBox().isSelected();
}
@Override
public String getPredicate() throws FilterValidationException {
String md5Hash = this.getComponent().getSearchTextField().getText();
if (md5Hash.isEmpty()) {
throw new FilterValidationException(EMPTY_HASH_MESSAGE);
}
return "md5 = '" + md5Hash.toLowerCase() + "'"; //NON-NLS
}
@Override
public void addActionListener(ActionListener l) {
getComponent().addActionListener(l);
}
@Override
public boolean isValid() {
return !this.getComponent().getSearchTextField().getText().isEmpty();
}
}

View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
<Container class="javax.swing.JPopupMenu" name="rightClickMenu">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
<Property name="useNullLayout" type="boolean" value="true"/>
</Layout>
<SubComponents>
<MenuItem class="javax.swing.JMenuItem" name="cutMenuItem">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="NameSearchPanel.cutMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</MenuItem>
<MenuItem class="javax.swing.JMenuItem" name="copyMenuItem">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="NameSearchPanel.copyMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</MenuItem>
<MenuItem class="javax.swing.JMenuItem" name="pasteMenuItem">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="NameSearchPanel.pasteMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</MenuItem>
<MenuItem class="javax.swing.JMenuItem" name="selectAllMenuItem">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="NameSearchPanel.selectAllMenuItem.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</MenuItem>
</SubComponents>
</Container>
</NonVisualComponents>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="hashCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="searchTextField" min="-2" pref="247" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="hashCheckBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="searchTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JCheckBox" name="hashCheckBox">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="hashCheckBox" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="HashSearchPanel.md5CheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="hashCheckBoxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JTextField" name="searchTextField">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="searchTextField" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,175 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JCheckBox;
import javax.swing.JMenuItem;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
/**
*
*/
class HashSearchPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L;
/**
* Creates new form HashSearchPanel
*/
HashSearchPanel() {
initComponents();
customizeComponents();
setComponentsEnabled();
}
private void customizeComponents() {
searchTextField.setComponentPopupMenu(rightClickMenu);
ActionListener actList = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JMenuItem jmi = (JMenuItem) e.getSource();
if (jmi.equals(cutMenuItem)) {
searchTextField.cut();
} else if (jmi.equals(copyMenuItem)) {
searchTextField.copy();
} else if (jmi.equals(pasteMenuItem)) {
searchTextField.paste();
} else if (jmi.equals(selectAllMenuItem)) {
searchTextField.selectAll();
}
}
};
cutMenuItem.addActionListener(actList);
copyMenuItem.addActionListener(actList);
pasteMenuItem.addActionListener(actList);
selectAllMenuItem.addActionListener(actList);
this.searchTextField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}
@Override
public void removeUpdate(DocumentEvent e) {
firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}
@Override
public void changedUpdate(DocumentEvent e) {
firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}
});
}
JCheckBox getHashCheckBox() {
return hashCheckBox;
}
JTextField getSearchTextField() {
return searchTextField;
}
void setComponentsEnabled() {
boolean enabled = hashCheckBox.isSelected();
this.searchTextField.setEnabled(enabled);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
rightClickMenu = new javax.swing.JPopupMenu();
cutMenuItem = new javax.swing.JMenuItem();
copyMenuItem = new javax.swing.JMenuItem();
pasteMenuItem = new javax.swing.JMenuItem();
selectAllMenuItem = new javax.swing.JMenuItem();
hashCheckBox = new javax.swing.JCheckBox();
searchTextField = new javax.swing.JTextField();
cutMenuItem.setText(org.openide.util.NbBundle.getMessage(HashSearchPanel.class, "NameSearchPanel.cutMenuItem.text")); // NOI18N
rightClickMenu.add(cutMenuItem);
copyMenuItem.setText(org.openide.util.NbBundle.getMessage(HashSearchPanel.class, "NameSearchPanel.copyMenuItem.text")); // NOI18N
rightClickMenu.add(copyMenuItem);
pasteMenuItem.setText(org.openide.util.NbBundle.getMessage(HashSearchPanel.class, "NameSearchPanel.pasteMenuItem.text")); // NOI18N
rightClickMenu.add(pasteMenuItem);
selectAllMenuItem.setText(org.openide.util.NbBundle.getMessage(HashSearchPanel.class, "NameSearchPanel.selectAllMenuItem.text")); // NOI18N
rightClickMenu.add(selectAllMenuItem);
hashCheckBox.setFont(hashCheckBox.getFont().deriveFont(hashCheckBox.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
hashCheckBox.setText(org.openide.util.NbBundle.getMessage(HashSearchPanel.class, "HashSearchPanel.md5CheckBox.text")); // NOI18N
hashCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
hashCheckBoxActionPerformed(evt);
}
});
searchTextField.setFont(searchTextField.getFont().deriveFont(searchTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(hashCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(searchTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 247, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(hashCheckBox)
.addComponent(searchTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
);
}// </editor-fold>//GEN-END:initComponents
private void hashCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_hashCheckBoxActionPerformed
setComponentsEnabled();
firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_hashCheckBoxActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JMenuItem copyMenuItem;
private javax.swing.JMenuItem cutMenuItem;
private javax.swing.JCheckBox hashCheckBox;
private javax.swing.JMenuItem pasteMenuItem;
private javax.swing.JPopupMenu rightClickMenu;
private javax.swing.JTextField searchTextField;
private javax.swing.JMenuItem selectAllMenuItem;
// End of variables declaration//GEN-END:variables
void addActionListener(ActionListener l) {
searchTextField.addActionListener(l);
}
}

View File

@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -229,7 +230,7 @@ public class IngestManager {
* opened/closed) events.
*/
private void subscribeToCaseEvents() {
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), (PropertyChangeEvent event) -> {
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent event) -> {
if (event.getNewValue() != null) {
handleCaseOpened();
} else {

View File

@ -25,6 +25,7 @@ import java.awt.Font;
import java.awt.Graphics;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.EnumSet;
import javax.swing.JButton;
import org.openide.util.NbBundle;
import org.openide.windows.Mode;
@ -128,7 +129,7 @@ class IngestMessagesToolbar extends javax.swing.JPanel {
}
});
Case.addPropertyChangeListener((PropertyChangeEvent evt) -> {
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent evt) -> {
if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
setEnabled(evt.getNewValue() != null && RuntimeProperties.runningWithGUI());
}

View File

@ -23,6 +23,7 @@ import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.io.File;
import java.io.IOException;
import java.util.EnumSet;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.SimpleFormatter;
@ -121,7 +122,7 @@ public final class IngestMonitor {
MonitorTimerAction() {
findRootDirectoryForCurrentCase();
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), (PropertyChangeEvent evt) -> {
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent evt) -> {
if (evt instanceof AutopsyEvent) {
AutopsyEvent event = (AutopsyEvent) evt;
if (AutopsyEvent.SourceType.LOCAL == event.getSourceType() && event.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {

View File

@ -23,7 +23,7 @@ import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.EnumSet;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
@ -43,14 +43,10 @@ class HashDbPanelSearchAction extends CallableSystemAction {
HashDbPanelSearchAction() {
super();
setEnabled(Case.isCaseOpen());
Case.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent evt) -> {
if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
setEnabled(evt.getNewValue() != null);
}
}
});
}

View File

@ -27,6 +27,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.text.MessageFormat;
import java.util.EnumSet;
import java.util.Map;
import javax.swing.ImageIcon;
import javax.swing.JButton;
@ -81,7 +82,7 @@ public final class ReportWizardAction extends CallableSystemAction implements Pr
public ReportWizardAction() {
setEnabled(false);
Case.addPropertyChangeListener((PropertyChangeEvent evt) -> {
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), (PropertyChangeEvent evt) -> {
if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
Case newCase = (Case) evt.getNewValue();
setEnabled(newCase != null && RuntimeProperties.runningWithGUI());

View File

@ -24,7 +24,7 @@
Note there is no namespace collision with ver 3 -->
<dependency conf="autopsy_core->*" org="commons-lang" name="commons-lang" rev="2.6"/>
<dependency conf="autopsy_core->*" org="commons-logging" name="commons-logging" rev="1.1.2"/>
<dependency conf="autopsy_core->*" org="commons-io" name="commons-io" rev="2.4"/>
<dependency conf="autopsy_core->*" org="commons-io" name="commons-io" rev="2.5"/>
<dependency conf="autopsy_core->*" org="log4j" name="log4j" rev="1.2.17"/>
<!-- <dependency conf="autopsy_core->*" org="org.jdom" name="jdom" rev="1.1.3"/> -->

View File

@ -10,6 +10,7 @@ file.reference.commons-codec-1.10.jar=release/modules/ext/commons-codec-1.10.jar
file.reference.commons-collections4-4.1.jar=release/modules/ext/commons-collections4-4.1.jar
file.reference.commons-csv-1.4.jar=release/modules/ext/commons-csv-1.4.jar
file.reference.commons-io-2.4.jar=release/modules/ext/commons-io-2.4.jar
file.reference.commons-io-2.5.jar=release/modules/ext/commons-io-2.5.jar
file.reference.commons-lang-2.6.jar=release/modules/ext/commons-lang-2.6.jar
file.reference.commons-lang3-3.0-javadoc.jar=release/modules/ext/commons-lang3-3.0-javadoc.jar
file.reference.commons-lang3-3.0-sources.jar=release/modules/ext/commons-lang3-3.0-sources.jar
@ -74,6 +75,7 @@ file.reference.xmlbeans-2.6.0.jar=release/modules/ext/xmlbeans-2.6.0.jar
javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial
javadoc.reference.commons-csv-1.4.jar=release/modules/ext/commons-csv-1.4-javadoc.jar
javadoc.reference.commons-io-2.5.jar=release/modules/ext/commons-io-2.5-javadoc.jar
javadoc.reference.compiler-0.9.1.jar=release/modules/ext/compiler-0.9.1-javadoc.jar
javadoc.reference.controlsfx-8.40.11.jar=release/modules/ext/controlsfx-8.40.11-javadoc.jar
javadoc.reference.guava-19.0.jar=release/modules/ext/guava-19.0-javadoc.jar
@ -82,6 +84,7 @@ javadoc.reference.jfxtras-controls-8.0-r4.jar=release/modules/ext/jfxtras-contro
javadoc.reference.jfxtras-fxml-8.0-r4.jar=release/modules/ext/jfxtras-fxml-8.0-r4-javadoc.jar
nbm.needs.restart=true
source.reference.commons-csv-1.4.jar=release/modules/ext/commons-csv-1.4-sources.jar
source.reference.commons-io-2.5.jar=release/modules/ext/commons-io-2.5-sources.jar
source.reference.compiler-0.9.1.jar=release/modules/ext/compiler-0.9.1-sources.jar
source.reference.controlsfx-8.40.11.jar=release/modules/ext/controlsfx-8.40.11-sources.jar
source.reference.guava-19.0.jar=release/modules/ext/guava-19.0-sources.jar

View File

@ -699,18 +699,10 @@
<runtime-relative-path>ext/sigar-1.6.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sigar-1.6.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xmlbeans-2.6.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xmlbeans-2.6.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jna-3.4.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jna-3.4.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-ooxml-schemas-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-ooxml-schemas-3.15.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/gson-1.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/gson-1.4.jar</binary-origin>
@ -731,6 +723,10 @@
<runtime-relative-path>ext/imgscalr-lib-4.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/imgscalr-lib-4.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xmlbeans-2.6.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xmlbeans-2.6.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/common-io-3.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/common-io-3.2.jar</binary-origin>
@ -764,12 +760,12 @@
<binary-origin>release/modules/ext/joda-time-2.4-javadoc.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jcalendarbutton-1.4.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jcalendarbutton-1.4.6.jar</binary-origin>
<runtime-relative-path>ext/poi-excelant-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-excelant-3.15.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-ooxml-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-ooxml-3.15.jar</binary-origin>
<runtime-relative-path>ext/jcalendarbutton-1.4.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jcalendarbutton-1.4.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/imageio-psd-3.2.jar</runtime-relative-path>
@ -779,18 +775,10 @@
<runtime-relative-path>ext/stax-api-1.0.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/stax-api-1.0.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-collections4-4.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-collections4-4.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/servlet-api-2.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/servlet-api-2.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-excelant-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-excelant-3.15.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/imageio-pcx-3.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/imageio-pcx-3.2.jar</binary-origin>
@ -827,10 +815,6 @@
<runtime-relative-path>ext/geronimo-jms_1.1_spec-1.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/geronimo-jms_1.1_spec-1.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-scratchpad-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-scratchpad-3.15.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/joda-time-2.4-sources.jar</runtime-relative-path>
<binary-origin>release/modules/ext/joda-time-2.4-sources.jar</binary-origin>
@ -839,14 +823,26 @@
<runtime-relative-path>ext/jfxtras-fxml-8.0-r4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jfxtras-fxml-8.0-r4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-ooxml-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-ooxml-3.15.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/joda-time-2.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/joda-time-2.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-collections4-4.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-collections4-4.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-logging-1.1.2-javadoc.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-logging-1.1.2-javadoc.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-codec-1.10.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-codec-1.10.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/slf4j-simple-1.6.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/slf4j-simple-1.6.1.jar</binary-origin>
@ -855,6 +851,18 @@
<runtime-relative-path>ext/guava-19.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/guava-19.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-io-2.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-io-2.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-ooxml-schemas-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-ooxml-schemas-3.15.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-scratchpad-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-scratchpad-3.15.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/imageio-bmp-3.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/imageio-bmp-3.2.jar</binary-origin>
@ -879,10 +887,6 @@
<runtime-relative-path>ext/ant-1.8.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/ant-1.8.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-codec-1.10.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-codec-1.10.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/javassist-3.12.1.GA.jar</runtime-relative-path>
<binary-origin>release/modules/ext/javassist-3.12.1.GA.jar</binary-origin>
@ -895,14 +899,6 @@
<runtime-relative-path>ext/commons-logging-1.1.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-logging-1.1.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-io-2.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-io-2.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-3.15.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/controlsfx-8.40.11.jar</runtime-relative-path>
<binary-origin>release/modules/ext/controlsfx-8.40.11.jar</binary-origin>
@ -915,6 +911,10 @@
<runtime-relative-path>ext/javaee-api-5.0-2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/javaee-api-5.0-2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/poi-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-3.15.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/common-image-3.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/common-image-3.2.jar</binary-origin>

View File

@ -2646,8 +2646,6 @@ public final class AutoIngestManager extends Observable implements PropertyChang
* back into hostNamesToRunningJobs as a result of
* processing the job status update.
*/
SYS_LOGGER.log(Level.WARNING, "Auto ingest node {0} timed out while processing folder {1}",
new Object[]{job.getNodeName(), job.getManifest().getFilePath().toString()});
hostNamesToRunningJobs.remove(job.getNodeName());
setChanged();
notifyObservers(Event.JOB_COMPLETED);

View File

@ -35,7 +35,7 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil;
*/
final class AutoIngestSystemLogger {
private static final int LOG_SIZE = 10000000; // In bytes, zero is unlimited, set to roughly 10mb currently
private static final int LOG_SIZE = 50000000; // In bytes, zero is unlimited, set to roughly 10mb currently
private static final int LOG_FILE_COUNT = 10;
private static final Logger LOGGER = Logger.getLogger("AutoIngest"); //NON-NLS
private static final String NEWLINE = System.lineSeparator();

View File

@ -23,6 +23,7 @@ import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.EnumSet;
import java.util.logging.Level;
import javax.swing.SwingUtilities;
import javax.swing.event.PopupMenuEvent;
@ -76,7 +77,7 @@ class DropdownToolbar extends javax.swing.JPanel {
private void customizeComponents() {
searchSettingsChangeListener = new SearchSettingsChangeListener();
KeywordSearch.getServer().addServerActionListener(searchSettingsChangeListener);
Case.addPropertyChangeListener(searchSettingsChangeListener);
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), searchSettingsChangeListener);
DropdownListSearchPanel listsPanel = DropdownListSearchPanel.getDefault();
listsPanel.addSearchButtonActionListener((ActionEvent e) -> {

View File

@ -1,63 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.keywordsearch;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
/**
* result of writing keyword search result to blackboard (cached artifact and
* attributes) This is mainly to cache the attributes, so that we don't query
* the DB to get them back again.
*/
class KeywordCachedArtifact {
private BlackboardArtifact artifact;
private Map<Integer, BlackboardAttribute> attributes;
KeywordCachedArtifact(BlackboardArtifact artifact) {
this.artifact = artifact;
attributes = new HashMap<Integer, BlackboardAttribute>();
}
BlackboardArtifact getArtifact() {
return artifact;
}
Collection<BlackboardAttribute> getAttributes() {
return attributes.values();
}
BlackboardAttribute getAttribute(Integer attrTypeID) {
return attributes.get(attrTypeID);
}
void add(BlackboardAttribute attribute) {
attributes.put(attribute.getAttributeType().getTypeID(), attribute);
}
void add(Collection<BlackboardAttribute> attributes) {
for (BlackboardAttribute attr : attributes) {
this.attributes.put(attr.getAttributeType().getTypeID(), attr);
}
}
}

View File

@ -18,17 +18,18 @@
*/
package org.sleuthkit.autopsy.keywordsearch;
import java.util.Comparator;
import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Stores the fact that file or an artifact associated with a file had a keyword
* hit. All instances make both the document id of the Solr document where the
* keyword was found and the file available to clients. Artifact keyword hits
* also make the artifact available to clients.
* keyword was found and the object Id available to clients. Artifact keyword
* hits also make the artifact available to clients.
*/
class KeywordHit implements Comparable<KeywordHit> {
@ -36,7 +37,7 @@ class KeywordHit implements Comparable<KeywordHit> {
private final long solrObjectId;
private final int chunkId;
private final String snippet;
private final Content content;
private final long contentID;
private final BlackboardArtifact artifact;
private final String hit;
@ -44,14 +45,9 @@ class KeywordHit implements Comparable<KeywordHit> {
return hit;
}
KeywordHit(String solrDocumentId, String snippet) throws TskCoreException {
this(solrDocumentId, snippet, null);
}
KeywordHit(String solrDocumentId, String snippet, String hit) throws TskCoreException {
/**
* Store the Solr document id.
*/
this.snippet = StringUtils.stripToEmpty(snippet);
this.hit = hit;
this.solrDocumentId = solrDocumentId;
/**
@ -72,27 +68,19 @@ class KeywordHit implements Comparable<KeywordHit> {
this.chunkId = 0;
}
/**
* Look up the file associated with the keyword hit. If the high order
* bit of the object id is set, the hit was for an artifact. In this
* case, look up the artifact as well.
/*
* If the high order bit of the object id is set (ie, it is negative),
* the hit was in an artifact, look up the artifact.
*/
SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase();
long fileId;
if (this.solrObjectId < 0) {
SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase();
this.artifact = caseDb.getBlackboardArtifact(this.solrObjectId);
fileId = artifact.getObjectID();
contentID = artifact.getObjectID();
} else {
//else the object id is for content.
this.artifact = null;
fileId = this.solrObjectId;
contentID = this.solrObjectId;
}
this.content = caseDb.getContentById(fileId);
/**
* Store the text snippet.
*/
this.snippet = snippet;
this.hit = hit;
}
String getSolrDocumentId() {
@ -103,24 +91,20 @@ class KeywordHit implements Comparable<KeywordHit> {
return this.solrObjectId;
}
boolean hasChunkId() {
return this.chunkId != 0;
}
int getChunkId() {
return this.chunkId;
}
boolean hasSnippet() {
return !this.snippet.isEmpty();
return StringUtils.isNotBlank(this.snippet);
}
String getSnippet() {
return this.snippet;
}
Content getContent() {
return this.content;
long getContentID() {
return this.contentID;
}
/**
@ -151,7 +135,7 @@ class KeywordHit implements Comparable<KeywordHit> {
return false;
}
final KeywordHit other = (KeywordHit) obj;
return (this.solrObjectId == other.solrObjectId && this.chunkId == other.chunkId);
return this.compareTo(other) == 0;
}
@Override
@ -163,21 +147,8 @@ class KeywordHit implements Comparable<KeywordHit> {
@Override
public int compareTo(KeywordHit o) {
if (this.solrObjectId < o.solrObjectId) {
// Out object id is less than the other object id
return -1;
} else if (this.solrObjectId == o.solrObjectId) {
// Hits have same object id
if (this.chunkId < o.chunkId) {
// Our chunk id is lower than the other chunk id
return -1;
} else {
// Our chunk id is either greater than or equal to the other chunk id
return this.chunkId == o.chunkId ? 0 : 1;
}
} else {
// Our object id is greater than the other object id
return 1;
}
return Comparator.comparing(KeywordHit::getSolrObjectId)
.thenComparing(KeywordHit::getChunkId)
.compare(this, o);
}
}

View File

@ -18,6 +18,9 @@
*/
package org.sleuthkit.autopsy.keywordsearch;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.Content;
/**
* Interface for kewyord search queries.
*/
@ -36,9 +39,11 @@ interface KeywordSearchQuery {
* execute query and return results without publishing them return results
* for all matching terms
*
* @throws KeywordSearchModuleException error while executing Solr term query
* @throws NoOpenCoreException if query failed due to server error, this
* could be a notification to stop processing
* @throws KeywordSearchModuleException error while executing Solr term
* query
* @throws NoOpenCoreException if query failed due to server error,
* this could be a notification to stop
* processing
* @return
*/
QueryResults performQuery() throws KeywordSearchModuleException, NoOpenCoreException;
@ -61,8 +66,6 @@ interface KeywordSearchQuery {
/**
* Modify the query string to be searched as a substring instead of a whole
* word
*
* @param isSubstring
*/
void setSubstringQuery();
@ -97,6 +100,21 @@ interface KeywordSearchQuery {
*/
String getEscapedQueryString();
KeywordCachedArtifact writeSingleFileHitsToBlackBoard(Keyword keyword, KeywordHit hit, String snippet, String listName);
/**
* Converts the keyword hits for a given search term into artifacts.
*
* @param content The Content object associated with the hit.
* @param foundKeyword The keyword that was found by the search, this may be
* different than the Keyword that was searched if, for
* example, it was a RegexQuery.
* @param hit The keyword hit.
* @param snippet The document snippet that contains the hit.
* @param listName The name of the keyword list that contained the
* keyword for which the hit was found.
*
*
* @return The newly created artifact or Null if there was a problem
* creating it.
*/
BlackboardArtifact writeSingleFileHitsToBlackBoard(Content content, Keyword foundKeyword, KeywordHit hit, String snippet, String listName);
}

View File

@ -18,13 +18,10 @@
*/
package org.sleuthkit.autopsy.keywordsearch;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.TreeMultimap;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@ -41,6 +38,7 @@ import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode;
@ -50,12 +48,13 @@ import org.sleuthkit.autopsy.datamodel.KeyValue;
import org.sleuthkit.autopsy.datamodel.KeyValueNode;
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchResultFactory.KeyValueQueryContent;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Node factory that performs the keyword search and creates children nodes for
@ -69,8 +68,8 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
private static final Logger logger = Logger.getLogger(KeywordSearchResultFactory.class.getName());
//common properties (superset of all Node properties) to be displayed as columns
static final List<String> COMMON_PROPERTIES
= Stream.concat(
static final List<String> COMMON_PROPERTIES =
Stream.concat(
Stream.of(
TSK_KEYWORD,
TSK_KEYWORD_REGEXP,
@ -91,7 +90,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
* properties are displayed as columns (since we are doing lazy child Node
* load we need to preinitialize properties when sending parent Node)
*
* @param toSet property set map for a Node
* @param toPopulate property set map for a Node
*/
@Override
protected boolean createKeys(List<KeyValueQueryContent> toPopulate) {
@ -144,6 +143,13 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
MessageNotifyUtil.Notify.error(Bundle.KeywordSearchResultFactory_query_exception_msg() + queryRequest.getQueryString(), ex.getCause().getMessage());
return false;
}
SleuthkitCase tskCase = null;
try {
tskCase = Case.getCurrentCase().getSleuthkitCase();
} catch (IllegalStateException ex) {
logger.log(Level.SEVERE, "There was no case open.", ex); //NON-NLS
return false;
}
int hitNumber = 0;
List<KeyValueQueryContent> tempList = new ArrayList<>();
@ -153,8 +159,20 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
* Get file properties.
*/
Map<String, Object> properties = new LinkedHashMap<>();
Content content = hit.getContent();
String contentName = content.getName();
Content content = null;
String contentName = "";
try {
content = tskCase.getContentById(hit.getContentID());
if (content == null) {
logger.log(Level.SEVERE, "There was a error getting content by id."); //NON-NLS
return false;
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "There was a error getting content by id.", ex); //NON-NLS
return false;
}
contentName = content.getName();
if (content instanceof AbstractFile) {
AbstractFsContentNode.fillPropertyMap(properties, (AbstractFile) content);
} else {
@ -222,6 +240,7 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
//wrap in KeywordSearchFilterNode for the markup content, might need to override FilterNode for more customization
return new KeywordSearchFilterNode(hits, kvNode);
}
/**
@ -241,9 +260,10 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
* practice
*
* @param name File name that has hit.
* @param map Contains content metadata, snippets, etc. (property
* map)
* @param map Contains content metadata, snippets, etc.
* (property map)
* @param id User incremented ID
* @param solrObjectId
* @param content File that had the hit.
* @param query Query used in search
* @param hits Full set of search results (for all files! @@@)
@ -278,13 +298,12 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
* worker for writing results to bb, with progress bar, cancellation, and
* central registry of workers to be stopped when case is closed
*/
static class BlackboardResultWriter extends SwingWorker<Object, Void> {
static class BlackboardResultWriter extends SwingWorker<Void, Void> {
private static final List<BlackboardResultWriter> writers = new ArrayList<>();
private ProgressHandle progress;
private final KeywordSearchQuery query;
private final QueryResults hits;
private Collection<BlackboardArtifact> newArtifacts = new ArrayList<>();
private static final int QUERY_DISPLAY_LEN = 40;
BlackboardResultWriter(QueryResults hits, String listName) {
@ -298,13 +317,13 @@ class KeywordSearchResultFactory extends ChildFactory<KeyValueQueryContent> {
}
@Override
protected Object doInBackground() throws Exception {
protected Void doInBackground() throws Exception {
registerWriter(this); //register (synchronized on class) outside of writerLock to prevent deadlock
final String queryStr = query.getQueryString();
final String queryDisp = queryStr.length() > QUERY_DISPLAY_LEN ? queryStr.substring(0, QUERY_DISPLAY_LEN - 1) + " ..." : queryStr;
try {
progress = ProgressHandle.createHandle(NbBundle.getMessage(this.getClass(), "KeywordSearchResultFactory.progress.saving", queryDisp), () -> BlackboardResultWriter.this.cancel(true));
newArtifacts = hits.writeAllHitsToBlackBoard(progress, null, this, false);
hits.writeAllHitsToBlackBoard(progress, null, this, false);
} finally {
finalizeWorker();
}

View File

@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
@ -40,6 +39,7 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskException;
@ -192,15 +192,13 @@ class LuceneQuery implements KeywordSearchQuery {
}
@Override
public KeywordCachedArtifact writeSingleFileHitsToBlackBoard(Keyword foundKeyword, KeywordHit hit, String snippet, String listName) {
public BlackboardArtifact writeSingleFileHitsToBlackBoard(Content content, Keyword foundKeyword, KeywordHit hit, String snippet, String listName) {
final String MODULE_NAME = KeywordSearchModuleFactory.getModuleName();
Collection<BlackboardAttribute> attributes = new ArrayList<>();
BlackboardArtifact bba;
KeywordCachedArtifact writeResult;
try {
bba = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
writeResult = new KeywordCachedArtifact(bba);
bba = content.newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
} catch (TskCoreException e) {
logger.log(Level.WARNING, "Error adding bb artifact for keyword hit", e); //NON-NLS
return null;
@ -233,8 +231,7 @@ class LuceneQuery implements KeywordSearchQuery {
try {
bba.addAttributes(attributes); //write out to bb
writeResult.add(attributes);
return writeResult;
return bba;
} catch (TskCoreException e) {
logger.log(Level.WARNING, "Error adding bb attributes to artifact", e); //NON-NLS
return null;

View File

@ -31,6 +31,7 @@ import org.apache.commons.lang.StringUtils;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.aggregate.ProgressContributor;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.EscapeUtil;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestMessage;
@ -40,6 +41,8 @@ import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Stores the results from running a Solr query (which could contain multiple
@ -60,8 +63,6 @@ class QueryResults {
*/
private final Map<Keyword, List<KeywordHit>> results = new HashMap<>();
QueryResults(KeywordSearchQuery query) {
this.keywordSearchQuery = query;
}
@ -70,8 +71,6 @@ class QueryResults {
results.put(keyword, hits);
}
KeywordSearchQuery getQuery() {
return keywordSearchQuery;
}
@ -99,7 +98,7 @@ class QueryResults {
*
* @return The artifacts that were created.
*/
Collection<BlackboardArtifact> writeAllHitsToBlackBoard(ProgressHandle progress, ProgressContributor subProgress, SwingWorker<Object, Void> worker, boolean notifyInbox) {
Collection<BlackboardArtifact> writeAllHitsToBlackBoard(ProgressHandle progress, ProgressContributor subProgress, SwingWorker<?, ?> worker, boolean notifyInbox) {
final Collection<BlackboardArtifact> newArtifacts = new ArrayList<>();
if (progress != null) {
progress.start(getKeywords().size());
@ -145,14 +144,26 @@ class QueryResults {
continue;
}
}
KeywordCachedArtifact writeResult = keywordSearchQuery.writeSingleFileHitsToBlackBoard(keyword, hit, snippet, keywordSearchQuery.getKeywordList().getName());
Content content = null;
try {
SleuthkitCase tskCase = Case.getCurrentCase().getSleuthkitCase();
content = tskCase.getContentById(hit.getContentID());
} catch (TskCoreException | IllegalStateException tskCoreException) {
logger.log(Level.SEVERE, "Error adding artifact for keyword hit to blackboard", tskCoreException); //NON-NLS
return null;
}
BlackboardArtifact writeResult = keywordSearchQuery.writeSingleFileHitsToBlackBoard(content, keyword, hit, snippet, keywordSearchQuery.getKeywordList().getName());
if (writeResult != null) {
newArtifacts.add(writeResult.getArtifact());
newArtifacts.add(writeResult);
if (notifyInbox) {
writeSingleFileInboxMessage(writeResult, hit.getContent());
try {
writeSingleFileInboxMessage(writeResult, content);
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error posting message to Ingest Inbox", ex); //NON-NLS
}
}
} else {
logger.log(Level.WARNING, "BB artifact for keyword hit not written, file: {0}, hit: {1}", new Object[]{hit.getContent(), keyword.toString()}); //NON-NLS
logger.log(Level.WARNING, "BB artifact for keyword hit not written, file: {0}, hit: {1}", new Object[]{content, keyword.toString()}); //NON-NLS
}
}
++unitProgress;
@ -181,7 +192,6 @@ class QueryResults {
* SolrObjectID-ChunkID pairs.
*/
private Collection<KeywordHit> getOneHitPerObject(Keyword keyword) {
HashMap<Long, KeywordHit> hits = new HashMap<>();
// create a list of KeywordHits. KeywordHits with lowest chunkID is added the the list.
@ -196,12 +206,16 @@ class QueryResults {
}
/**
* Generate an ingest inbox message for given keyword in given file
* Generate and post an ingest inbox message for the given keyword in the
* given content.
*
* @param written
* @param hitFile
* @param artifact The keyword hit artifact.
* @param hitContent The content that the hit is in.
*
* @throws TskCoreException If there is a problem generating or posting the
* inbox message.
*/
private void writeSingleFileInboxMessage(KeywordCachedArtifact written, Content hitContent) {
private void writeSingleFileInboxMessage(BlackboardArtifact artifact, Content hitContent) throws TskCoreException {
StringBuilder subjectSb = new StringBuilder();
StringBuilder detailsSb = new StringBuilder();
@ -210,24 +224,24 @@ class QueryResults {
} else {
subjectSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.kwHitLbl"));
}
String uniqueKey = null;
BlackboardAttribute attr = written.getAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID());
BlackboardAttribute attr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD));
if (attr != null) {
final String keyword = attr.getValueString();
subjectSb.append(keyword);
uniqueKey = keyword.toLowerCase();
}
//details
detailsSb.append("<table border='0' cellpadding='4' width='280'>"); //NON-NLS
//hit
detailsSb.append("<tr>"); //NON-NLS
detailsSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.kwHitThLbl"));
detailsSb.append("<td>").append(EscapeUtil.escapeHtml(attr.getValueString())).append("</td>"); //NON-NLS
detailsSb.append("<td>").append(EscapeUtil.escapeHtml(keyword)).append("</td>"); //NON-NLS
detailsSb.append("</tr>"); //NON-NLS
}
//preview
attr = written.getAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getTypeID());
attr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW));
if (attr != null) {
detailsSb.append("<tr>"); //NON-NLS
detailsSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.previewThLbl"));
@ -247,16 +261,17 @@ class QueryResults {
detailsSb.append("</tr>"); //NON-NLS
//list
attr = written.getAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
attr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
if (attr != null) {
detailsSb.append("<tr>"); //NON-NLS
detailsSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.listThLbl"));
detailsSb.append("<td>").append(attr.getValueString()).append("</td>"); //NON-NLS
detailsSb.append("</tr>"); //NON-NLS
}
//regex
if (!keywordSearchQuery.isLiteral()) {
attr = written.getAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID());
attr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP));
if (attr != null) {
detailsSb.append("<tr>"); //NON-NLS
detailsSb.append(NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.regExThLbl"));
@ -264,9 +279,9 @@ class QueryResults {
detailsSb.append("</tr>"); //NON-NLS
}
}
detailsSb.append("</table>"); //NON-NLS
IngestServices.getInstance().postMessage(IngestMessage.createDataMessage(MODULE_NAME, subjectSb.toString(), detailsSb.toString(), uniqueKey, written.getArtifact()));
IngestServices.getInstance().postMessage(IngestMessage.createDataMessage(MODULE_NAME, subjectSb.toString(), detailsSb.toString(), uniqueKey, artifact));
}
}

View File

@ -19,15 +19,11 @@
package org.sleuthkit.autopsy.keywordsearch;
import com.google.common.base.CharMatcher;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -52,6 +48,7 @@ import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
@ -84,8 +81,6 @@ final class RegexQuery implements KeywordSearchQuery {
private final int MIN_EMAIL_ADDR_LENGTH = 8;
private final ListMultimap<Keyword, KeywordHit> hitsMultiMap = ArrayListMultimap.create();
// Lucene regular expressions do not support the following Java predefined
// and POSIX character classes. There are other valid Java character classes
// that are not supported by Lucene but we do not check for all of them.
@ -188,8 +183,9 @@ final class RegexQuery implements KeywordSearchQuery {
solrQuery.setSort(SortClause.asc(Server.Schema.ID.toString()));
String cursorMark = CursorMarkParams.CURSOR_MARK_START;
SolrDocumentList resultList ;
SolrDocumentList resultList;
boolean allResultsProcessed = false;
QueryResults results = new QueryResults(this);
while (!allResultsProcessed) {
try {
@ -201,7 +197,13 @@ final class RegexQuery implements KeywordSearchQuery {
try {
List<KeywordHit> keywordHits = createKeywordHits(resultDoc);
for (KeywordHit hit : keywordHits) {
hitsMultiMap.put(new Keyword(hit.getHit(), true, true, originalKeyword.getListName(), originalKeyword.getOriginalTerm()), hit);
Keyword keywordInstance = new Keyword(hit.getHit(), true, true, originalKeyword.getListName(), originalKeyword.getOriginalTerm());
List<KeywordHit> hitsForKeyword = results.getResults(keywordInstance);
if (hitsForKeyword == null) {
hitsForKeyword = new ArrayList<>();
results.addResult(keywordInstance, hitsForKeyword);
}
hitsForKeyword.add(hit);
}
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error creating keyword hits", ex); //NON-NLS
@ -218,10 +220,7 @@ final class RegexQuery implements KeywordSearchQuery {
MessageNotifyUtil.Notify.error(NbBundle.getMessage(Server.class, "Server.query.exception.msg", keywordString), ex.getCause().getMessage());
}
}
QueryResults results = new QueryResults(this);
for (Keyword k : hitsMultiMap.keySet()) {
results.addResult(k, hitsMultiMap.get(k));
}
return results;
}
@ -284,8 +283,8 @@ final class RegexQuery implements KeywordSearchQuery {
}
/*
* If searching for credit card account numbers, do a Luhn check
* on the term and discard it if it does not pass.
* If searching for credit card account numbers, do a Luhn
* check on the term and discard it if it does not pass.
*/
if (originalKeyword.getArtifactAttributeType() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CARD_NUMBER) {
Matcher ccnMatcher = CREDIT_CARD_NUM_PATTERN.matcher(hit);
@ -316,10 +315,14 @@ final class RegexQuery implements KeywordSearchQuery {
} catch (TskCoreException ex) {
throw ex;
} catch (Throwable error) {
/* NOTE: Matcher.find() is known to throw StackOverflowError in rare cases (see JIRA-2700).
StackOverflowError is an error, not an exception, and therefore needs to be caught
as a Throwable. When this occurs we should re-throw the error as TskCoreException so that it is
logged by the calling method and move on to the next Solr document. */
/*
* NOTE: Matcher.find() is known to throw StackOverflowError in rare
* cases (see JIRA-2700). StackOverflowError is an error, not an
* exception, and therefore needs to be caught as a Throwable. When
* this occurs we should re-throw the error as TskCoreException so
* that it is logged by the calling method and move on to the next
* Solr document.
*/
throw new TskCoreException("Failed to create keyword hits for Solr document id " + docId + " due to " + error.getMessage());
}
return hits;
@ -370,50 +373,15 @@ final class RegexQuery implements KeywordSearchQuery {
return escapedQuery;
}
/**
* Get a unique, comma separated list of document ids that match the given
* hit for the same object.
*
* @param keyword The keyword object that resulted in one or more hits.
* @param hit The specific hit for which we want to identify all other
* chunks that match the keyword
*
* @return A comma separated list of unique document ids.
*/
private String getDocumentIds(Keyword keyword, KeywordHit hit) {
Set<String> documentIds = new HashSet<>();
for (KeywordHit h : hitsMultiMap.get(keyword)) {
// Add the document id only if it is for the same object as the
// given hit and we haven't already seen it.
if (h.getSolrObjectId() == hit.getSolrObjectId() && !documentIds.contains(h.getSolrDocumentId())) {
documentIds.add(h.getSolrDocumentId());
}
}
return StringUtils.join(documentIds, ",");
}
/**
* Converts the keyword hits for a given search term into artifacts.
*
* @param foundKeyword The keyword that was found by the regex search.
* @param hit The keyword hit.
* @param snippet The document snippet that contains the hit
* @param listName The name of the keyword list that contained the
* keyword for which the hit was found.
*
*
*
* @return An object that wraps an artifact and a mapping by id of its
* attributes.
*/
// TODO: Are we actually making meaningful use of the KeywordCachedArtifact
// class?
@Override
public KeywordCachedArtifact writeSingleFileHitsToBlackBoard(Keyword foundKeyword, KeywordHit hit, String snippet, String listName) {
public BlackboardArtifact writeSingleFileHitsToBlackBoard(Content content, Keyword foundKeyword, KeywordHit hit, String snippet, String listName) {
final String MODULE_NAME = KeywordSearchModuleFactory.getModuleName();
if (content == null) {
LOGGER.log(Level.WARNING, "Error adding artifact for keyword hit to blackboard"); //NON-NLS
return null;
}
/*
* Create either a "plain vanilla" keyword hit artifact with keyword and
* regex attributes, or a credit card account artifact with attributes
@ -426,8 +394,7 @@ final class RegexQuery implements KeywordSearchQuery {
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, foundKeyword.getSearchTerm()));
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP, MODULE_NAME, getQueryString()));
try {
newArtifact = hit.getContent().newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT);
newArtifact = content.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT);
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error adding artifact for keyword hit to blackboard", ex); //NON-NLS
return null;
@ -452,7 +419,7 @@ final class RegexQuery implements KeywordSearchQuery {
if (hit.isArtifactHit()) {
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for artifact keyword hit: term = %s, snippet = '%s', artifact id = %d", foundKeyword.getSearchTerm(), hit.getSnippet(), hit.getArtifact().getArtifactID())); //NON-NLS
} else {
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", foundKeyword.getSearchTerm(), hit.getSnippet(), hit.getContent().getId())); //NON-NLS
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", foundKeyword.getSearchTerm(), hit.getSnippet(), hit.getContentID())); //NON-NLS
}
return null;
}
@ -488,8 +455,8 @@ final class RegexQuery implements KeywordSearchQuery {
* document id to support showing just the chunk that contained the
* hit.
*/
if (hit.getContent() instanceof AbstractFile) {
AbstractFile file = (AbstractFile) hit.getContent();
if (content instanceof AbstractFile) {
AbstractFile file = (AbstractFile) content;
if (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS
|| file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) {
attributes.add(new BlackboardAttribute(KEYWORD_SEARCH_DOCUMENT_ID, MODULE_NAME, hit.getSolrDocumentId()));
@ -500,7 +467,7 @@ final class RegexQuery implements KeywordSearchQuery {
* Create an account artifact.
*/
try {
newArtifact = hit.getContent().newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT);
newArtifact = content.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT);
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error adding artifact for account to blackboard", ex); //NON-NLS
return null;
@ -521,9 +488,7 @@ final class RegexQuery implements KeywordSearchQuery {
try {
newArtifact.addAttributes(attributes);
KeywordCachedArtifact writeResult = new KeywordCachedArtifact(newArtifact);
writeResult.add(attributes);
return writeResult;
return newArtifact;
} catch (TskCoreException e) {
LOGGER.log(Level.SEVERE, "Error adding bb attributes for terms search artifact", e); //NON-NLS
return null;
@ -570,6 +535,7 @@ final class RegexQuery implements KeywordSearchQuery {
* @param groupName The group name of the regular expression that was
* used to parse the attribute data.
* @param matcher A matcher for the snippet.
*/
static private void addAttributeIfNotAlreadyCaptured(Map<BlackboardAttribute.Type, BlackboardAttribute> attributeMap, BlackboardAttribute.ATTRIBUTE_TYPE attrType, String groupName, Matcher matcher) {
BlackboardAttribute.Type type = new BlackboardAttribute.Type(attrType);

View File

@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.keywordsearch;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@ -46,7 +45,6 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.StopWatch;
import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.datamodel.BlackboardArtifact;
/**
* Singleton keyword search manager: Launches search threads for each job and
@ -482,8 +480,6 @@ public final class SearchRunner {
if (!newResults.getKeywords().isEmpty()) {
// Write results to BB
//new artifacts created, to report to listeners
Collection<BlackboardArtifact> newArtifacts = new ArrayList<>();
//scale progress bar more more granular, per result sub-progress, within per keyword
int totalUnits = newResults.getKeywords().size();
@ -496,7 +492,7 @@ public final class SearchRunner {
subProgresses[keywordsSearched].progress(keywordList.getName() + ": " + queryDisplayStr, unitProgress);
// Create blackboard artifacts
newArtifacts = newResults.writeAllHitsToBlackBoard(null, subProgresses[keywordsSearched], this, keywordList.getIngestMessages());
newResults.writeAllHitsToBlackBoard(null, subProgresses[keywordsSearched], this, keywordList.getIngestMessages());
} //if has results

View File

@ -824,7 +824,7 @@ public class Server {
return new Core(coreName, theCase.getCaseType(), index);
} catch (SolrServerException | SolrException | IOException ex) {
} catch (Exception ex) {
throw new KeywordSearchModuleException(NbBundle.getMessage(this.getClass(), "Server.openCore.exception.cantOpen.msg"), ex);
}
}
@ -1232,6 +1232,8 @@ public class Server {
// core in it, and is only good for core-specific operations
private final HttpSolrServer solrCore;
private final int QUERY_TIMEOUT_MILLISECONDS = 86400000; // 24 Hours = 86,400,000 Milliseconds
private Core(String name, CaseType caseType, Index index) {
this.name = name;
this.caseType = caseType;
@ -1240,7 +1242,8 @@ public class Server {
this.solrCore = new HttpSolrServer(currentSolrServer.getBaseURL() + "/" + name); //NON-NLS
//TODO test these settings
//solrCore.setSoTimeout(1000 * 60); // socket read timeout, make large enough so can index larger files
// socket read timeout, make large enough so can index larger files
solrCore.setSoTimeout(QUERY_TIMEOUT_MILLISECONDS);
//solrCore.setConnectionTimeout(1000);
solrCore.setDefaultMaxConnectionsPerHost(2);
solrCore.setMaxTotalConnections(5);

View File

@ -42,6 +42,7 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
@ -318,24 +319,9 @@ final class TermsComponentQuery implements KeywordSearchQuery {
return results;
}
/**
* Converts the keyword hits for a given search term into artifacts.
*
* @param foundKeyword The keyword that was found by the search.
* @param hit The keyword hit.
* @param snippet The document snippet that contains the hit
* @param listName The name of the keyword list that contained the keyword
* for which the hit was found.
*
*
*
* @return An object that wraps an artifact and a mapping by id of its
* attributes.
*/
// TODO: Are we actually making meaningful use of the KeywordCachedArtifact
// class?
@Override
public KeywordCachedArtifact writeSingleFileHitsToBlackBoard(Keyword foundKeyword, KeywordHit hit, String snippet, String listName) {
public BlackboardArtifact writeSingleFileHitsToBlackBoard(Content content, Keyword foundKeyword, KeywordHit hit, String snippet, String listName) {
/*
* Create either a "plain vanilla" keyword hit artifact with keyword and
* regex attributes, or a credit card account artifact with attributes
@ -349,7 +335,7 @@ final class TermsComponentQuery implements KeywordSearchQuery {
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP, MODULE_NAME, originalKeyword.getSearchTerm()));
try {
newArtifact = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
newArtifact = content.newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error adding artifact for keyword hit to blackboard", ex); //NON-NLS
@ -375,7 +361,7 @@ final class TermsComponentQuery implements KeywordSearchQuery {
if (hit.isArtifactHit()) {
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for artifact keyword hit: term = %s, snippet = '%s', artifact id = %d", searchTerm, hit.getSnippet(), hit.getArtifact().getArtifactID())); //NON-NLS
} else {
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", searchTerm, hit.getSnippet(), hit.getContent().getId())); //NON-NLS
LOGGER.log(Level.SEVERE, String.format("Failed to parse credit card account number for content keyword hit: term = %s, snippet = '%s', object id = %d", searchTerm, hit.getSnippet(), hit.getContentID())); //NON-NLS
}
return null;
}
@ -411,8 +397,8 @@ final class TermsComponentQuery implements KeywordSearchQuery {
* document id to support showing just the chunk that contained the
* hit.
*/
if (hit.getContent() instanceof AbstractFile) {
AbstractFile file = (AbstractFile) hit.getContent();
if (content instanceof AbstractFile) {
AbstractFile file = (AbstractFile)content;
if (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS
|| file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) {
attributes.add(new BlackboardAttribute(KEYWORD_SEARCH_DOCUMENT_ID, MODULE_NAME, hit.getSolrDocumentId()));
@ -423,7 +409,7 @@ final class TermsComponentQuery implements KeywordSearchQuery {
* Create an account artifact.
*/
try {
newArtifact = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_ACCOUNT);
newArtifact = content.newArtifact(ARTIFACT_TYPE.TSK_ACCOUNT);
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, "Error adding artifact for account to blackboard", ex); //NON-NLS
return null;
@ -445,9 +431,7 @@ final class TermsComponentQuery implements KeywordSearchQuery {
try {
newArtifact.addAttributes(attributes);
KeywordCachedArtifact writeResult = new KeywordCachedArtifact(newArtifact);
writeResult.add(attributes);
return writeResult;
return newArtifact;
} catch (TskCoreException e) {
LOGGER.log(Level.SEVERE, "Error adding bb attributes for terms search artifact", e); //NON-NLS
return null;

View File

@ -170,7 +170,7 @@
<!-- Update configuration file to include jre -->
<property name="inst.property.file" value="${inst-path}/etc/${app.name}.conf" />
<!-- Sets max heap size to be ${jvm.max.mem} which is set in the run-ai-(32/64) target -->
<var name="jvm.args" value="&quot;--branding ${app.name} -J-Xms24m -J-Xmx${jvm.max.mem}m -J-XX:MaxPermSize=128M -J-Xverify:none &quot;" />
<var name="jvm.args" value="&quot;--branding ${app.name} -J-Xms24m -J-Xmx${jvm.max.mem}m -J-XX:MaxPermSize=128M -J-Xverify:none -J-XX:+UseG1GC -J-XX:+UseStringDeduplication &quot;" />
<propertyfile file="${inst.property.file}">
<!-- Note: can be higher on 64 bit systems, should be in sync with project.properties -->
<entry key="default_options" value="@JVM_OPTIONS" />

View File

@ -92,7 +92,7 @@
<property name="app.property.file" value="${zip-tmp}/${app.name}/etc/${app.name}.conf" />
<!-- for Japanese localized version add option: -Duser.language=ja -->
<property name="jvm.options" value="&quot;--branding ${app.name} -J-Xms24m -J-XX:MaxPermSize=128M -J-Xverify:none -J-Xdock:name=${app.title}&quot;" />
<property name="jvm.options" value="&quot;--branding ${app.name} -J-Xms24m -J-XX:MaxPermSize=128M -J-Xverify:none -J-XX:+UseG1GC -J-XX:+UseStringDeduplication -J-Xdock:name=${app.title}&quot;" />
<propertyfile file="${app.property.file}">
<!-- Note: can be higher on 64 bit systems, should be in sync with project.properties -->
<entry key="default_options" value="@JVM_OPTIONS" />

View File

@ -4,7 +4,7 @@ app.title=Autopsy
### lowercase version of above
app.name=${branding.token}
### if left unset, version will default to today's date
app.version=4.4.1
app.version=4.4.2
### build.type must be one of: DEVELOPMENT, RELEASE
#build.type=RELEASE
build.type=DEVELOPMENT
@ -16,7 +16,7 @@ update_versions=false
#custom JVM options
#Note: can be higher on 64 bit systems, should be in sync with build.xml
# for Japanese version add: -J-Duser.language=ja
run.args.extra=-J-Xms24m -J-XX:MaxPermSize=128M -J-Xverify:none
run.args.extra=-J-Xms24m -J-XX:MaxPermSize=128M -J-Xverify:none -J-XX:+UseG1GC -J-XX:+UseStringDeduplication
auxiliary.org-netbeans-modules-apisupport-installer.license-type=apache.v2
auxiliary.org-netbeans-modules-apisupport-installer.os-linux=false
auxiliary.org-netbeans-modules-apisupport-installer.os-macosx=false