mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
3849 resolve merge conflict with develop
This commit is contained in:
commit
388e127190
@ -98,6 +98,11 @@ import org.sleuthkit.autopsy.casemodule.events.PersonsAddedEvent;
|
|||||||
import org.sleuthkit.autopsy.casemodule.events.PersonsUpdatedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.PersonsUpdatedEvent;
|
||||||
import org.sleuthkit.autopsy.casemodule.events.PersonsDeletedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.PersonsDeletedEvent;
|
||||||
import org.sleuthkit.autopsy.casemodule.events.ReportAddedEvent;
|
import org.sleuthkit.autopsy.casemodule.events.ReportAddedEvent;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.events.TagNamesEvent.TagNamesAddedEvent;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.events.TagNamesEvent.TagNamesDeletedEvent;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.events.TagNamesEvent.TagNamesUpdatedEvent;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.events.TagSetsEvent.TagSetsAddedEvent;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.events.TagSetsEvent.TagSetsDeletedEvent;
|
||||||
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData.CaseNodeDataException;
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData.CaseNodeDataException;
|
||||||
import org.sleuthkit.autopsy.casemodule.multiusercases.CoordinationServiceUtils;
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CoordinationServiceUtils;
|
||||||
import org.sleuthkit.autopsy.casemodule.services.Services;
|
import org.sleuthkit.autopsy.casemodule.services.Services;
|
||||||
@ -484,7 +489,32 @@ public class Case {
|
|||||||
/**
|
/**
|
||||||
* One or more hosts have been removed from a person.
|
* One or more hosts have been removed from a person.
|
||||||
*/
|
*/
|
||||||
HOSTS_REMOVED_FROM_PERSON;
|
HOSTS_REMOVED_FROM_PERSON,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One or more TagNames have been added.
|
||||||
|
*/
|
||||||
|
TAG_NAMES_ADDED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One or more TagNames have been updated.
|
||||||
|
*/
|
||||||
|
TAG_NAMES_UPDATED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One or more TagNames have been deleted.
|
||||||
|
*/
|
||||||
|
TAG_NAMES_DELETED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One or more TagSets have been added.
|
||||||
|
*/
|
||||||
|
TAG_SETS_ADDED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One or more TagSets have been removed.
|
||||||
|
*/
|
||||||
|
TAG_SETS_DELETED;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -609,6 +639,30 @@ public class Case {
|
|||||||
eventPublisher.publish(new HostsRemovedFromPersonEvent(event.getPerson(), event.getHostIds()));
|
eventPublisher.publish(new HostsRemovedFromPersonEvent(event.getPerson(), event.getHostIds()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void publicTagNamesAdded(TskEvent.TagNamesAddedTskEvent event) {
|
||||||
|
eventPublisher.publish(new TagNamesAddedEvent(event.getTagNames()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void publicTagNamesUpdated(TskEvent.TagNamesUpdatedTskEvent event) {
|
||||||
|
eventPublisher.publish(new TagNamesUpdatedEvent(event.getTagNames()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void publicTagNamesDeleted(TskEvent.TagNamesDeletedTskEvent event) {
|
||||||
|
eventPublisher.publish(new TagNamesDeletedEvent(event.getTagNameIds()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void publicTagSetsAdded(TskEvent.TagSetsAddedTskEvent event) {
|
||||||
|
eventPublisher.publish(new TagSetsAddedEvent(event.getTagSets()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void publicTagSetsDeleted(TskEvent.TagSetsDeletedTskEvent event) {
|
||||||
|
eventPublisher.publish(new TagSetsDeletedEvent(event.getTagSetIds()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
126
Core/src/org/sleuthkit/autopsy/casemodule/events/TagNamesEvent.java
Executable file
126
Core/src/org/sleuthkit/autopsy/casemodule/events/TagNamesEvent.java
Executable file
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2021 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.casemodule.events;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.TagName;
|
||||||
|
import org.sleuthkit.datamodel.TaggingManager;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A base class for TagName added and update events.
|
||||||
|
*/
|
||||||
|
public class TagNamesEvent extends TskDataModelChangedEvent<TagName, TagName> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the base event for TagNames that have been added or updated.
|
||||||
|
*
|
||||||
|
* @param eventName The name of the event.
|
||||||
|
* @param tagNames The TagNames that have been modified.
|
||||||
|
*/
|
||||||
|
private TagNamesEvent(String eventName, List<TagName> tagNames) {
|
||||||
|
super(eventName, null, null, tagNames, TagName::getId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of the added or modified TagNames.
|
||||||
|
*
|
||||||
|
* @return The event list of TagNames.
|
||||||
|
*/
|
||||||
|
public List<TagName> getTagNames() {
|
||||||
|
return getNewValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<TagName> getNewValueObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
|
||||||
|
List<TagName> tagNames = new ArrayList<>();
|
||||||
|
TaggingManager taggingMrg = caseDb.getTaggingManager();
|
||||||
|
for (Long id : ids) {
|
||||||
|
tagNames.add(taggingMrg.getTagName(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
return tagNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application events published when TagNames have been Added from the
|
||||||
|
* Sleuth Kit data model for a case.
|
||||||
|
*/
|
||||||
|
public static class TagNamesAddedEvent extends TagNamesEvent {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an application event published when TagNames have been
|
||||||
|
* added to the Sleuth Kit data model.
|
||||||
|
*
|
||||||
|
* @param tagNames The TagNames that have been added.
|
||||||
|
*/
|
||||||
|
public TagNamesAddedEvent(List<TagName> tagNames) {
|
||||||
|
super(Case.Events.TAG_NAMES_ADDED.name(), tagNames);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application events published when TagNames have been updated from the
|
||||||
|
* Sleuth Kit data model for a case.
|
||||||
|
*/
|
||||||
|
public static class TagNamesUpdatedEvent extends TagNamesEvent {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an application event published when TagNames have been
|
||||||
|
* updated in the Sleuth Kit data model.
|
||||||
|
*
|
||||||
|
* @param tagNames The TagNames that have been updated.
|
||||||
|
*/
|
||||||
|
public TagNamesUpdatedEvent(List<TagName> tagNames) {
|
||||||
|
super(Case.Events.TAG_NAMES_UPDATED.name(), tagNames);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application events published when TagNames have been deleted from the
|
||||||
|
* Sleuth Kit data model for a case.
|
||||||
|
*/
|
||||||
|
public static class TagNamesDeletedEvent extends TskDataModelObjectsDeletedEvent {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an application event published when the TagNames have been
|
||||||
|
* deleted from the Sleuth Kit data model for a case.
|
||||||
|
*
|
||||||
|
* @param tagNameIds The IDs of the TagNames that have been deleted.
|
||||||
|
*/
|
||||||
|
public TagNamesDeletedEvent(List<Long> tagNameIds) {
|
||||||
|
super(Case.Events.TAG_NAMES_DELETED.name(), tagNameIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Long> getTagNameIds() {
|
||||||
|
return getOldValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
103
Core/src/org/sleuthkit/autopsy/casemodule/events/TagSetsEvent.java
Executable file
103
Core/src/org/sleuthkit/autopsy/casemodule/events/TagSetsEvent.java
Executable file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2021 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.casemodule.events;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
|
import org.sleuthkit.datamodel.TagSet;
|
||||||
|
import org.sleuthkit.datamodel.TaggingManager;
|
||||||
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A base class for TagSet added and update events.
|
||||||
|
*/
|
||||||
|
public class TagSetsEvent extends TskDataModelChangedEvent<TagSet, TagSet> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new TagSetEvent.
|
||||||
|
*
|
||||||
|
* @param eventName
|
||||||
|
* @param tagSets
|
||||||
|
*/
|
||||||
|
private TagSetsEvent(String eventName, List<TagSet> tagSets) {
|
||||||
|
super(eventName, null, null, tagSets, TagSet::getId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of the TagSet objects that were added or modified for this
|
||||||
|
* event.
|
||||||
|
*
|
||||||
|
* @return A list of TagSet objects.
|
||||||
|
*/
|
||||||
|
public List<TagSet> getTagSets() {
|
||||||
|
return this.getNewValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<TagSet> getNewValueObjects(SleuthkitCase caseDb, List<Long> ids) throws TskCoreException {
|
||||||
|
List<TagSet> tagSets = new ArrayList<>();
|
||||||
|
TaggingManager taggingMrg = caseDb.getTaggingManager();
|
||||||
|
for (Long id : ids) {
|
||||||
|
tagSets.add(taggingMrg.getTagSet(id));
|
||||||
|
}
|
||||||
|
return tagSets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application events published when TagSets have been Added from the Sleuth
|
||||||
|
* Kit data model for a case.
|
||||||
|
*/
|
||||||
|
public static class TagSetsAddedEvent extends TagSetsEvent {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an application event published when TagSetss have been
|
||||||
|
* added to the Sleuth Kit data model.
|
||||||
|
*
|
||||||
|
* @param tagSets The TagSets that have been added.
|
||||||
|
*/
|
||||||
|
public TagSetsAddedEvent(List<TagSet> tagSets) {
|
||||||
|
super(Case.Events.TAG_SETS_ADDED.name(), tagSets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application events published when TagSets have been deleted from the
|
||||||
|
* Sleuth Kit data model for a case.
|
||||||
|
*/
|
||||||
|
public static class TagSetsDeletedEvent extends TskDataModelObjectsDeletedEvent {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an application event published when the TagSets have been
|
||||||
|
* deleted from the Sleuth Kit data model for a case.
|
||||||
|
*
|
||||||
|
* @param tagNameIds The IDs of the TagNames that have been deleted.
|
||||||
|
*/
|
||||||
|
public TagSetsDeletedEvent(List<Long> tagNameIds) {
|
||||||
|
super(Case.Events.TAG_SETS_DELETED.name(), tagNameIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -236,7 +236,7 @@ final public class TagNameDefinition implements Comparable<TagNameDefinition> {
|
|||||||
TagName saveToCase(SleuthkitCase caseDb) {
|
TagName saveToCase(SleuthkitCase caseDb) {
|
||||||
TagName tagName = null;
|
TagName tagName = null;
|
||||||
try {
|
try {
|
||||||
tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatus);
|
tagName = caseDb.getTaggingManager().addOrUpdateTagName(displayName, description, color, knownStatus);
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error saving tag name definition", ex);
|
LOGGER.log(Level.SEVERE, "Error saving tag name definition", ex);
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.casemodule.services;
|
package org.sleuthkit.autopsy.casemodule.services;
|
||||||
|
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -29,8 +32,11 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.util.WeakListeners;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.events.TagNamesEvent;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.events.TagNamesEvent.TagNamesDeletedEvent;
|
||||||
import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager;
|
import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewerTagManager;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
@ -61,6 +67,37 @@ public class TagsManager implements Closeable {
|
|||||||
|
|
||||||
private static final Object lock = new Object();
|
private static final Object lock = new Object();
|
||||||
|
|
||||||
|
private final Map<String, TagName> allTagNameMap = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
|
private final PropertyChangeListener listener = new PropertyChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
|
if (evt.getPropertyName().equals(Case.Events.TAG_NAMES_ADDED.name())
|
||||||
|
|| evt.getPropertyName().equals(Case.Events.TAG_NAMES_UPDATED.name())) {
|
||||||
|
TagNamesEvent tagEvent = (TagNamesEvent) evt;
|
||||||
|
List<TagName> addTagNames = tagEvent.getTagNames();
|
||||||
|
for (TagName tag : addTagNames) {
|
||||||
|
allTagNameMap.put(tag.getDisplayName(), tag);
|
||||||
|
}
|
||||||
|
} else if (evt.getPropertyName().equals(Case.Events.TAG_NAMES_DELETED.name())) {
|
||||||
|
TagNamesDeletedEvent tagEvent = (TagNamesDeletedEvent) evt;
|
||||||
|
List<Long> deletedIds = tagEvent.getTagNameIds();
|
||||||
|
List<String> keysToRemove = new ArrayList<>();
|
||||||
|
for (TagName tagName : getAllTagNames()) {
|
||||||
|
if (deletedIds.contains(tagName.getId())) {
|
||||||
|
keysToRemove.add(tagName.getDisplayName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String key : keysToRemove) {
|
||||||
|
allTagNameMap.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final PropertyChangeListener weakListener = WeakListeners.propertyChange(listener, null);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
|
||||||
//Create the contentviewer tags table if the current case does not
|
//Create the contentviewer tags table if the current case does not
|
||||||
@ -177,8 +214,6 @@ public class TagsManager implements Closeable {
|
|||||||
/*
|
/*
|
||||||
* No current case, nothing more to add to the set.
|
* No current case, nothing more to add to the set.
|
||||||
*/
|
*/
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
LOGGER.log(Level.SEVERE, "Failed to get list of TagNames from TagsManager.", ex);
|
|
||||||
}
|
}
|
||||||
return tagDisplayNames;
|
return tagDisplayNames;
|
||||||
}
|
}
|
||||||
@ -268,14 +303,14 @@ public class TagsManager implements Closeable {
|
|||||||
|
|
||||||
// add the standard tag names
|
// add the standard tag names
|
||||||
for (TagNameDefinition def : TagNameDefinition.getStandardTagNameDefinitions()) {
|
for (TagNameDefinition def : TagNameDefinition.getStandardTagNameDefinitions()) {
|
||||||
caseDb.addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus());
|
taggingMgr.addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
//Assume new case and add all tag sets
|
//Assume new case and add all tag sets
|
||||||
for (TagSetDefinition setDef : TagSetDefinition.readTagSetDefinitions()) {
|
for (TagSetDefinition setDef : TagSetDefinition.readTagSetDefinitions()) {
|
||||||
List<TagName> tagNamesInSet = new ArrayList<>();
|
List<TagName> tagNamesInSet = new ArrayList<>();
|
||||||
for (TagNameDefinition tagNameDef : setDef.getTagNameDefinitions()) {
|
for (TagNameDefinition tagNameDef : setDef.getTagNameDefinitions()) {
|
||||||
tagNamesInSet.add(caseDb.addOrUpdateTagName(tagNameDef.getDisplayName(), tagNameDef.getDescription(), tagNameDef.getColor(), tagNameDef.getKnownStatus()));
|
tagNamesInSet.add(taggingMgr.addOrUpdateTagName(tagNameDef.getDisplayName(), tagNameDef.getDescription(), tagNameDef.getColor(), tagNameDef.getKnownStatus()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tagNamesInSet.isEmpty()) {
|
if (!tagNamesInSet.isEmpty()) {
|
||||||
@ -283,6 +318,11 @@ public class TagsManager implements Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(TagName tagName: caseDb.getAllTagNames()) {
|
||||||
|
allTagNameMap.put(tagName.getDisplayName(), tagName);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
LOGGER.log(Level.SEVERE, "Error updating standard tag name and tag set definitions", ex);
|
LOGGER.log(Level.SEVERE, "Error updating standard tag name and tag set definitions", ex);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
@ -292,6 +332,10 @@ public class TagsManager implements Closeable {
|
|||||||
for (TagNameDefinition tagName : TagNameDefinition.getTagNameDefinitions()) {
|
for (TagNameDefinition tagName : TagNameDefinition.getTagNameDefinitions()) {
|
||||||
tagName.saveToCase(caseDb);
|
tagName.saveToCase(caseDb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_UPDATED), weakListener);
|
||||||
|
Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_ADDED), weakListener);
|
||||||
|
Case.addEventTypeSubscriber(Collections.singleton(Case.Events.TAG_NAMES_DELETED), weakListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -337,11 +381,12 @@ public class TagsManager implements Closeable {
|
|||||||
* Gets a list of all tag names currently in the case database.
|
* Gets a list of all tag names currently in the case database.
|
||||||
*
|
*
|
||||||
* @return A list, possibly empty, of TagName objects.
|
* @return A list, possibly empty, of TagName objects.
|
||||||
*
|
|
||||||
* @throws TskCoreException If there is an error querying the case database.
|
|
||||||
*/
|
*/
|
||||||
public List<TagName> getAllTagNames() throws TskCoreException {
|
public synchronized List<TagName> getAllTagNames() {
|
||||||
return caseDb.getAllTagNames();
|
|
||||||
|
List<TagName> tagNames = new ArrayList<>();
|
||||||
|
tagNames.addAll(allTagNameMap.values());
|
||||||
|
return tagNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -439,7 +484,7 @@ public class TagsManager implements Closeable {
|
|||||||
*/
|
*/
|
||||||
public Map<String, TagName> getDisplayNamesToTagNamesMap() throws TskCoreException {
|
public Map<String, TagName> getDisplayNamesToTagNamesMap() throws TskCoreException {
|
||||||
Map<String, TagName> tagNames = new HashMap<>();
|
Map<String, TagName> tagNames = new HashMap<>();
|
||||||
for (TagName tagName : caseDb.getAllTagNames()) {
|
for (TagName tagName : getAllTagNames()) {
|
||||||
tagNames.put(tagName.getDisplayName(), tagName);
|
tagNames.put(tagName.getDisplayName(), tagName);
|
||||||
}
|
}
|
||||||
return tagNames;
|
return tagNames;
|
||||||
@ -521,13 +566,13 @@ public class TagsManager implements Closeable {
|
|||||||
public TagName addTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus) throws TagNameAlreadyExistsException, TskCoreException {
|
public TagName addTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus) throws TagNameAlreadyExistsException, TskCoreException {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
try {
|
try {
|
||||||
TagName tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatus);
|
TagName tagName = caseDb.getTaggingManager().addOrUpdateTagName(displayName, description, color, knownStatus);
|
||||||
Set<TagNameDefinition> customTypes = TagNameDefinition.getTagNameDefinitions();
|
Set<TagNameDefinition> customTypes = TagNameDefinition.getTagNameDefinitions();
|
||||||
customTypes.add(new TagNameDefinition(displayName, description, color, knownStatus));
|
customTypes.add(new TagNameDefinition(displayName, description, color, knownStatus));
|
||||||
TagNameDefinition.setTagNameDefinitions(customTypes);
|
TagNameDefinition.setTagNameDefinitions(customTypes);
|
||||||
return tagName;
|
return tagName;
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
List<TagName> existingTagNames = caseDb.getAllTagNames();
|
List<TagName> existingTagNames = getAllTagNames();
|
||||||
for (TagName tagName : existingTagNames) {
|
for (TagName tagName : existingTagNames) {
|
||||||
if (tagName.getDisplayName().equals(displayName)) {
|
if (tagName.getDisplayName().equals(displayName)) {
|
||||||
throw new TagNameAlreadyExistsException();
|
throw new TagNameAlreadyExistsException();
|
||||||
@ -1039,5 +1084,4 @@ public class TagsManager implements Closeable {
|
|||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ CommandLineIngestSettingPanel_empty_report_name_mgs=Report profile name was empt
|
|||||||
CommandLineIngestSettingPanel_existing_report_name_mgs=Report profile name was already exists, no profile created.
|
CommandLineIngestSettingPanel_existing_report_name_mgs=Report profile name was already exists, no profile created.
|
||||||
CommandListIngestSettingsPanel_Default_Report_DisplayName=Default
|
CommandListIngestSettingsPanel_Default_Report_DisplayName=Default
|
||||||
CommandListIngestSettingsPanel_Make_Config=Make new profile...
|
CommandListIngestSettingsPanel_Make_Config=Make new profile...
|
||||||
CommandListIngestSettingsPanel_Report_Name_Msg=Please supply a report profile name:
|
CommandListIngestSettingsPanel_Report_Name_Msg=Please supply a report profile name (commas not allowed):
|
||||||
OpenIDE-Module-Name=CommandLineAutopsy
|
OpenIDE-Module-Name=CommandLineAutopsy
|
||||||
OptionsCategory_Keywords_Command_Line_Ingest_Settings=Command Line Ingest Settings
|
OptionsCategory_Keywords_Command_Line_Ingest_Settings=Command Line Ingest Settings
|
||||||
OptionsCategory_Keywords_General=Options
|
OptionsCategory_Keywords_General=Options
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2019-2020 Basis Technology Corp.
|
* Copyright 2019-2021 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -280,7 +280,7 @@ public class CommandLineIngestSettingsPanel extends javax.swing.JPanel {
|
|||||||
add(nodePanel, java.awt.BorderLayout.CENTER);
|
add(nodePanel, java.awt.BorderLayout.CENTER);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
@Messages({
|
@Messages({
|
||||||
"CommandListIngestSettingsPanel_Report_Name_Msg=Please supply a report profile name:",
|
"CommandListIngestSettingsPanel_Report_Name_Msg=Please supply a report profile name (commas not allowed):",
|
||||||
"CommandLineIngestSettingPanel_empty_report_name_mgs=Report profile name was empty, no profile created.",
|
"CommandLineIngestSettingPanel_empty_report_name_mgs=Report profile name was empty, no profile created.",
|
||||||
"CommandLineIngestSettingPanel_existing_report_name_mgs=Report profile name was already exists, no profile created."
|
"CommandLineIngestSettingPanel_existing_report_name_mgs=Report profile name was already exists, no profile created."
|
||||||
})
|
})
|
||||||
@ -289,6 +289,10 @@ public class CommandLineIngestSettingsPanel extends javax.swing.JPanel {
|
|||||||
if (reportName.equals(Bundle.CommandListIngestSettingsPanel_Make_Config())) {
|
if (reportName.equals(Bundle.CommandListIngestSettingsPanel_Make_Config())) {
|
||||||
reportName = JOptionPane.showInputDialog(this, Bundle.CommandListIngestSettingsPanel_Report_Name_Msg());
|
reportName = JOptionPane.showInputDialog(this, Bundle.CommandListIngestSettingsPanel_Report_Name_Msg());
|
||||||
|
|
||||||
|
// sanitize report name. Remove all commas because in CommandLineOptionProcessor we use commas
|
||||||
|
// to separate multiple report names
|
||||||
|
reportName = reportName.replaceAll(",", "");
|
||||||
|
|
||||||
// User hit cancel
|
// User hit cancel
|
||||||
if (reportName == null) {
|
if (reportName == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2019-2020 Basis Technology Corp.
|
* Copyright 2019-2021 Basis Technology Corp.
|
||||||
* Contact: carrier <at> sleuthkit <dot> org
|
* Contact: carrier <at> sleuthkit <dot> org
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -20,12 +20,15 @@ package org.sleuthkit.autopsy.commandlineingest;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.netbeans.api.sendopts.CommandException;
|
import org.netbeans.api.sendopts.CommandException;
|
||||||
import org.netbeans.spi.sendopts.Env;
|
import org.netbeans.spi.sendopts.Env;
|
||||||
@ -291,7 +294,6 @@ public class CommandLineOptionProcessor extends OptionProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add "GENERATE_REPORTS" command, if present
|
// Add "GENERATE_REPORTS" command, if present
|
||||||
String reportProfile = null;
|
|
||||||
if (values.containsKey(generateReportsOption)) {
|
if (values.containsKey(generateReportsOption)) {
|
||||||
|
|
||||||
// 'caseDir' must only be specified if the case is not being created during the current run
|
// 'caseDir' must only be specified if the case is not being created during the current run
|
||||||
@ -300,24 +302,34 @@ public class CommandLineOptionProcessor extends OptionProcessor {
|
|||||||
handleError("'caseDir' argument is empty");
|
handleError("'caseDir' argument is empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> reportProfiles;
|
||||||
argDirs = values.get(generateReportsOption);
|
argDirs = values.get(generateReportsOption);
|
||||||
if (argDirs.length > 0) {
|
if (argDirs.length > 0) {
|
||||||
reportProfile = argDirs[0];
|
// use custom report configuration(s)
|
||||||
|
reportProfiles = Stream.of(argDirs[0].split(","))
|
||||||
|
.map(String::trim)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (reportProfiles == null || reportProfiles.isEmpty()) {
|
||||||
|
handleError("'generateReports' argument is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String reportProfile : reportProfiles) {
|
||||||
|
if (reportProfile.isEmpty()) {
|
||||||
|
handleError("Empty report profile name");
|
||||||
|
}
|
||||||
|
CommandLineCommand newCommand = new CommandLineCommand(CommandLineCommand.CommandType.GENERATE_REPORTS);
|
||||||
|
newCommand.addInputValue(CommandLineCommand.InputType.CASE_FOLDER_PATH.name(), caseDir);
|
||||||
|
newCommand.addInputValue(CommandLineCommand.InputType.REPORT_PROFILE_NAME.name(), reportProfile);
|
||||||
|
commands.add(newCommand);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// use default report configuration
|
||||||
|
CommandLineCommand newCommand = new CommandLineCommand(CommandLineCommand.CommandType.GENERATE_REPORTS);
|
||||||
|
newCommand.addInputValue(CommandLineCommand.InputType.CASE_FOLDER_PATH.name(), caseDir);
|
||||||
|
commands.add(newCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user doesn't supply an options for generateReports the
|
|
||||||
// argsDirs length will be 0, so if reportProfile is empty
|
|
||||||
// something is not right.
|
|
||||||
if (reportProfile != null && reportProfile.isEmpty()) {
|
|
||||||
handleError("'generateReports' argument is empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandLineCommand newCommand = new CommandLineCommand(CommandLineCommand.CommandType.GENERATE_REPORTS);
|
|
||||||
newCommand.addInputValue(CommandLineCommand.InputType.CASE_FOLDER_PATH.name(), caseDir);
|
|
||||||
if (reportProfile != null) {
|
|
||||||
newCommand.addInputValue(CommandLineCommand.InputType.REPORT_PROFILE_NAME.name(), reportProfile);
|
|
||||||
}
|
|
||||||
commands.add(newCommand);
|
|
||||||
runFromCommandLine = true;
|
runFromCommandLine = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ public class OsAccountViewer extends javax.swing.JPanel implements DataContentVi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int isPreferred(Node node) {
|
public int isPreferred(Node node) {
|
||||||
return 5;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
DataSourceFilter.errorMessage.emptyDataSource=At least one data source must be selected.
|
DataSourceFilter.errorMessage.emptyDataSource=At least one data source must be selected.
|
||||||
DateSearchFilter.errorMessage.endDateBeforeStartDate=The end date should be after the start date.
|
DateSearchFilter.errorMessage.endDateBeforeStartDate=The end date should be after the start date.
|
||||||
DateSearchFilter.errorMessage.noCheckboxSelected=At least one date type checkbox must be selected.
|
DateSearchFilter.errorMessage.noCheckboxSelected=At least one date type checkbox must be selected.
|
||||||
|
FileSearchPanel.cancelledSearch.text=Search Was Cancelled
|
||||||
FileSearchPanel.emptyNode.display.text=No results found.
|
FileSearchPanel.emptyNode.display.text=No results found.
|
||||||
|
FileSearchPanel.searchingNode.display.text=Performing file search by attributes. Please wait.
|
||||||
|
FileSearchPanel.searchingPath.text=File Search In Progress
|
||||||
HashSearchFilter.errorMessage.emptyHash=Hash data is empty.
|
HashSearchFilter.errorMessage.emptyHash=Hash data is empty.
|
||||||
HashSearchFilter.errorMessage.wrongCharacter=MD5 contains invalid hex characters.
|
HashSearchFilter.errorMessage.wrongCharacter=MD5 contains invalid hex characters.
|
||||||
# {0} - hash data length
|
# {0} - hash data length
|
||||||
|
@ -29,15 +29,17 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.SwingWorker;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import org.openide.DialogDisplayer;
|
import org.openide.DialogDisplayer;
|
||||||
import org.openide.NotifyDescriptor;
|
import org.openide.NotifyDescriptor;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.windows.TopComponent;
|
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||||
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
||||||
@ -56,13 +58,14 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
|
||||||
class FileSearchPanel extends javax.swing.JPanel {
|
class FileSearchPanel extends javax.swing.JPanel {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(FileSearchPanel.class.getName());
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private final List<FileSearchFilter> filters = new ArrayList<>();
|
private final List<FileSearchFilter> filters = new ArrayList<>();
|
||||||
private static int resultWindowCount = 0; //keep track of result windows so they get unique names
|
private static int resultWindowCount = 0; //keep track of result windows so they get unique names
|
||||||
private static final MimeTypeFilter mimeTypeFilter = new MimeTypeFilter();
|
private static final MimeTypeFilter mimeTypeFilter = new MimeTypeFilter();
|
||||||
private static final DataSourceFilter dataSourceFilter = new DataSourceFilter();
|
private static final DataSourceFilter dataSourceFilter = new DataSourceFilter();
|
||||||
private static final String EMPTY_WHERE_CLAUSE = NbBundle.getMessage(DateSearchFilter.class, "FileSearchPanel.emptyWhereClause.text");
|
private static final String EMPTY_WHERE_CLAUSE = NbBundle.getMessage(DateSearchFilter.class, "FileSearchPanel.emptyWhereClause.text");
|
||||||
|
private static SwingWorker<TableFilterNode, Void> searchWorker = null;
|
||||||
|
|
||||||
enum EVENT {
|
enum EVENT {
|
||||||
CHECKED
|
CHECKED
|
||||||
@ -176,56 +179,102 @@ class FileSearchPanel extends javax.swing.JPanel {
|
|||||||
* Action when the "Search" button is pressed.
|
* Action when the "Search" button is pressed.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages("FileSearchPanel.emptyNode.display.text=No results found.")
|
@NbBundle.Messages({"FileSearchPanel.emptyNode.display.text=No results found.",
|
||||||
|
"FileSearchPanel.searchingNode.display.text=Performing file search by attributes. Please wait.",
|
||||||
|
"FileSearchPanel.searchingPath.text=File Search In Progress",
|
||||||
|
"FileSearchPanel.cancelledSearch.text=Search Was Cancelled"})
|
||||||
private void search() {
|
private void search() {
|
||||||
// change the cursor to "waiting cursor" for this operation
|
if (searchWorker != null && searchWorker.isDone()) {
|
||||||
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
searchWorker.cancel(true);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
if (this.isValidSearch()) {
|
if (this.isValidSearch()) {
|
||||||
String title = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.title", ++resultWindowCount);
|
|
||||||
String pathText = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.pathText");
|
|
||||||
|
|
||||||
// try to get the number of matches first
|
// try to get the number of matches first
|
||||||
Case currentCase = Case.getCurrentCaseThrows(); // get the most updated case
|
Case currentCase = Case.getCurrentCaseThrows(); // get the most updated case
|
||||||
long totalMatches = 0;
|
Node emptyNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_searchingNode_display_text()), true);
|
||||||
List<AbstractFile> contentList = null;
|
String title = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.title", ++resultWindowCount);
|
||||||
try {
|
String pathText = Bundle.FileSearchPanel_searchingPath_text();
|
||||||
SleuthkitCase tskDb = currentCase.getSleuthkitCase();
|
final DataResultTopComponent searchResultWin = DataResultTopComponent.createInstance(title, pathText,
|
||||||
contentList = tskDb.findAllFilesWhere(this.getQuery());
|
emptyNode, 0);
|
||||||
|
|
||||||
} catch (TskCoreException ex) {
|
|
||||||
Logger logger = Logger.getLogger(this.getClass().getName());
|
|
||||||
logger.log(Level.WARNING, "Error while trying to get the number of matches.", ex); //NON-NLS
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contentList == null) {
|
|
||||||
contentList = Collections.<AbstractFile>emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchNode sn = new SearchNode(contentList);
|
|
||||||
TableFilterNode tableFilterNode = new TableFilterNode(sn, true, sn.getName());
|
|
||||||
final TopComponent searchResultWin;
|
|
||||||
if (contentList.isEmpty()) {
|
|
||||||
Node emptyNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_emptyNode_display_text()), true);
|
|
||||||
searchResultWin = DataResultTopComponent.createInstance(title, pathText,
|
|
||||||
emptyNode, 0);
|
|
||||||
} else {
|
|
||||||
searchResultWin = DataResultTopComponent.createInstance(title, pathText,
|
|
||||||
tableFilterNode, contentList.size());
|
|
||||||
}
|
|
||||||
searchResultWin.requestActive(); // make it the active top component
|
searchResultWin.requestActive(); // make it the active top component
|
||||||
|
searchResultWin.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||||
|
searchWorker = new SwingWorker<TableFilterNode, Void>() {
|
||||||
|
List<AbstractFile> contentList = null;
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* If total matches more than 1000, pop up a dialog box that say
|
protected TableFilterNode doInBackground() throws Exception {
|
||||||
* the performance maybe be slow and to increase the
|
try {
|
||||||
* performance, tell the users to refine their search.
|
SleuthkitCase tskDb = currentCase.getSleuthkitCase();
|
||||||
*/
|
contentList = tskDb.findAllFilesWhere(getQuery());
|
||||||
if (totalMatches > 10000) {
|
|
||||||
// show info
|
} catch (TskCoreException ex) {
|
||||||
String msg = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.msg", totalMatches);
|
Logger logger = Logger.getLogger(this.getClass().getName());
|
||||||
String details = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.details");
|
logger.log(Level.WARNING, "Error while trying to get the number of matches.", ex); //NON-NLS
|
||||||
MessageNotifyUtil.Notify.info(msg, details);
|
}
|
||||||
|
if (contentList == null) {
|
||||||
|
contentList = Collections.<AbstractFile>emptyList();
|
||||||
|
}
|
||||||
|
if (contentList.isEmpty()) {
|
||||||
|
return new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_emptyNode_display_text()), true);
|
||||||
|
}
|
||||||
|
SearchNode sn = new SearchNode(contentList);
|
||||||
|
return new TableFilterNode(sn, true, sn.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
String pathText = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.pathText");
|
||||||
|
try {
|
||||||
|
TableFilterNode tableFilterNode = get();
|
||||||
|
if (tableFilterNode == null) { //just incase this get() gets modified to return null or somehow can return null
|
||||||
|
tableFilterNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_emptyNode_display_text()), true);
|
||||||
|
}
|
||||||
|
if (searchResultWin != null && searchResultWin.isOpened()) {
|
||||||
|
searchResultWin.setNode(tableFilterNode);
|
||||||
|
searchResultWin.requestActive(); // make it the active top component
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* If total matches more than 1000, pop up a dialog
|
||||||
|
* box that say the performance maybe be slow and to
|
||||||
|
* increase the performance, tell the users to
|
||||||
|
* refine their search.
|
||||||
|
*/
|
||||||
|
if (contentList.size() > 10000) {
|
||||||
|
// show info
|
||||||
|
String msg = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.msg", contentList.size());
|
||||||
|
String details = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.details");
|
||||||
|
MessageNotifyUtil.Notify.info(msg, details);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException | ExecutionException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error while performing file search by attributes", ex);
|
||||||
|
} catch (CancellationException ex) {
|
||||||
|
if (searchResultWin != null && searchResultWin.isOpened()) {
|
||||||
|
Node emptyNode = new TableFilterNode(new EmptyNode(Bundle.FileSearchPanel_cancelledSearch_text()), true);
|
||||||
|
searchResultWin.setNode(emptyNode);
|
||||||
|
pathText = Bundle.FileSearchPanel_cancelledSearch_text();
|
||||||
|
}
|
||||||
|
logger.log(Level.INFO, "File search by attributes was cancelled", ex);
|
||||||
|
} finally {
|
||||||
|
if (searchResultWin != null && searchResultWin.isOpened()) {
|
||||||
|
searchResultWin.setPath(pathText);
|
||||||
|
searchResultWin.requestActive(); // make it the active top component
|
||||||
|
searchResultWin.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (searchResultWin != null && searchResultWin.isOpened()) {
|
||||||
|
searchResultWin.addPropertyChangeListener(new PropertyChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
|
if (evt.getPropertyName().equals("tcClosed") && !searchWorker.isDone() && evt.getOldValue() == null) {
|
||||||
|
searchWorker.cancel(true);
|
||||||
|
logger.log(Level.INFO, "User has closed the results window while search was in progress, search will be cancelled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
searchWorker.execute();
|
||||||
} else {
|
} else {
|
||||||
throw new FilterValidationException(
|
throw new FilterValidationException(
|
||||||
NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.exception.noFilterSelected.msg"));
|
NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.exception.noFilterSelected.msg"));
|
||||||
@ -234,8 +283,6 @@ class FileSearchPanel extends javax.swing.JPanel {
|
|||||||
NotifyDescriptor d = new NotifyDescriptor.Message(
|
NotifyDescriptor d = new NotifyDescriptor.Message(
|
||||||
NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.validationErr.msg", ex.getMessage()));
|
NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.validationErr.msg", ex.getMessage()));
|
||||||
DialogDisplayer.getDefault().notify(d);
|
DialogDisplayer.getDefault().notify(d);
|
||||||
} finally {
|
|
||||||
this.setCursor(null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ public final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewe
|
|||||||
JMenuItem[] getMenuItems() throws TskCoreException {
|
JMenuItem[] getMenuItems() throws TskCoreException {
|
||||||
List<JMenuItem> menuItems = new ArrayList<>();
|
List<JMenuItem> menuItems = new ArrayList<>();
|
||||||
BlackboardArtifact artifact = dataModelWaypoint.getArtifact();
|
BlackboardArtifact artifact = dataModelWaypoint.getArtifact();
|
||||||
Content content = artifact.getSleuthkitCase().getContentById(artifact.getObjectID());
|
Content content = dataModelWaypoint.getContent();
|
||||||
|
|
||||||
menuItems.addAll(getTimelineMenuItems(dataModelWaypoint.getArtifact()));
|
menuItems.addAll(getTimelineMenuItems(dataModelWaypoint.getArtifact()));
|
||||||
menuItems.addAll(getDataModelActionFactoryMenuItems(artifact, content));
|
menuItems.addAll(getDataModelActionFactoryMenuItems(artifact, content));
|
||||||
|
@ -28,6 +28,7 @@ import java.util.Set;
|
|||||||
import org.sleuthkit.datamodel.AbstractFile;
|
import org.sleuthkit.datamodel.AbstractFile;
|
||||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||||
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.TskCoreException;
|
import org.sleuthkit.datamodel.TskCoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,6 +45,7 @@ public class Waypoint {
|
|||||||
final private AbstractFile image;
|
final private AbstractFile image;
|
||||||
final private BlackboardArtifact artifact;
|
final private BlackboardArtifact artifact;
|
||||||
final private GeoPath parentGeoPath;
|
final private GeoPath parentGeoPath;
|
||||||
|
final private Content content;
|
||||||
|
|
||||||
final private List<Waypoint.Property> propertiesList;
|
final private List<Waypoint.Property> propertiesList;
|
||||||
|
|
||||||
@ -93,6 +95,11 @@ public class Waypoint {
|
|||||||
this.parentGeoPath = parentGeoPath;
|
this.parentGeoPath = parentGeoPath;
|
||||||
|
|
||||||
propertiesList = createGeolocationProperties(attributeMap);
|
propertiesList = createGeolocationProperties(attributeMap);
|
||||||
|
try {
|
||||||
|
content = artifact.getSleuthkitCase().getContentById(artifact.getObjectID());
|
||||||
|
} catch (TskCoreException ex) {
|
||||||
|
throw new GeoLocationDataException(String.format("Failed to get contend for artifact id (%d)", artifact.getId()), ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -249,6 +256,10 @@ public class Waypoint {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Content getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple property class for waypoint properties that a purely
|
* Simple property class for waypoint properties that a purely
|
||||||
* informational.
|
* informational.
|
||||||
|
@ -538,7 +538,10 @@ final class IngestJobPipeline {
|
|||||||
* @return True or false.
|
* @return True or false.
|
||||||
*/
|
*/
|
||||||
boolean hasFileIngestModules() {
|
boolean hasFileIngestModules() {
|
||||||
return (fileIngestPipelines.isEmpty() == false);
|
if (!fileIngestPipelines.isEmpty()) {
|
||||||
|
return !fileIngestPipelines.get(0).isEmpty();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -340,7 +340,7 @@ public class PortableCaseReportModule implements ReportModule {
|
|||||||
progressPanel.updateStatusLabel(Bundle.PortableCaseReportModule_generateReport_copyingTags());
|
progressPanel.updateStatusLabel(Bundle.PortableCaseReportModule_generateReport_copyingTags());
|
||||||
try {
|
try {
|
||||||
for (TagName tagName : tagNames) {
|
for (TagName tagName : tagNames) {
|
||||||
TagName newTagName = portableSkCase.addOrUpdateTagName(tagName.getDisplayName(), tagName.getDescription(), tagName.getColor(), tagName.getKnownStatus());
|
TagName newTagName = portableSkCase.getTaggingManager().addOrUpdateTagName(tagName.getDisplayName(), tagName.getDescription(), tagName.getColor(), tagName.getKnownStatus());
|
||||||
oldTagNameToNewTagName.put(tagName, newTagName);
|
oldTagNameToNewTagName.put(tagName, newTagName);
|
||||||
}
|
}
|
||||||
} catch (TskCoreException ex) {
|
} catch (TskCoreException ex) {
|
||||||
|
@ -149,7 +149,7 @@ public class ImageGalleryService implements AutopsyService {
|
|||||||
private void addProjetVicTagSet(Case currentCase) throws TskCoreException {
|
private void addProjetVicTagSet(Case currentCase) throws TskCoreException {
|
||||||
List<TagName> tagNames = new ArrayList<>();
|
List<TagName> tagNames = new ArrayList<>();
|
||||||
for (TagNameDefinition def : PROJECT_VIC_US_CATEGORIES) {
|
for (TagNameDefinition def : PROJECT_VIC_US_CATEGORIES) {
|
||||||
tagNames.add(currentCase.getSleuthkitCase().addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus()));
|
tagNames.add(currentCase.getSleuthkitCase().getTaggingManager().addOrUpdateTagName(def.getDisplayName(), def.getDescription(), def.getColor(), def.getKnownStatus()));
|
||||||
}
|
}
|
||||||
currentCase.getServices().getTagsManager().addTagSet(PROJECT_VIC_TAG_SET_NAME, tagNames);
|
currentCase.getServices().getTagsManager().addTagSet(PROJECT_VIC_TAG_SET_NAME, tagNames);
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ from java.lang import Class
|
|||||||
from java.lang import System
|
from java.lang import System
|
||||||
from java.sql import DriverManager, SQLException
|
from java.sql import DriverManager, SQLException
|
||||||
from java.util.logging import Level
|
from java.util.logging import Level
|
||||||
from java.util import ArrayList
|
from java.util import Arrays
|
||||||
from java.io import File
|
from java.io import File
|
||||||
from org.sleuthkit.datamodel import SleuthkitCase
|
from org.sleuthkit.datamodel import SleuthkitCase
|
||||||
from org.sleuthkit.datamodel import AbstractFile
|
from org.sleuthkit.datamodel import AbstractFile
|
||||||
@ -113,7 +113,7 @@ class ContactsDbIngestModule(DataSourceIngestModule):
|
|||||||
progressBar.switchToIndeterminate()
|
progressBar.switchToIndeterminate()
|
||||||
|
|
||||||
# Use blackboard class to index blackboard artifacts for keyword search
|
# Use blackboard class to index blackboard artifacts for keyword search
|
||||||
blackboard = Case.getCurrentCase().getServices().getBlackboard()
|
blackboard = Case.getCurrentCase().getSleuthkitCase().getBlackboard()
|
||||||
|
|
||||||
# Find files named contacts.db, regardless of parent path
|
# Find files named contacts.db, regardless of parent path
|
||||||
fileManager = Case.getCurrentCase().getServices().getFileManager()
|
fileManager = Case.getCurrentCase().getServices().getFileManager()
|
||||||
@ -162,30 +162,21 @@ class ContactsDbIngestModule(DataSourceIngestModule):
|
|||||||
|
|
||||||
|
|
||||||
# Make an artifact on the blackboard, TSK_CONTACT and give it attributes for each of the fields
|
# Make an artifact on the blackboard, TSK_CONTACT and give it attributes for each of the fields
|
||||||
art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT)
|
art = file.newDataArtifact(BlackboardArtifact.Type.TSK_CONTACT, Arrays.asList(
|
||||||
attributes = ArrayList()
|
BlackboardAttribute(BlackboardAttribute.Type.TSK_NAME_PERSON,
|
||||||
|
ContactsDbIngestModuleFactory.moduleName, name),
|
||||||
|
BlackboardAttribute(BlackboardAttribute.Type.TSK_EMAIL,
|
||||||
|
ContactsDbIngestModuleFactory.moduleName, email),
|
||||||
|
BlackboardAttribute(BlackboardAttribute.Type.TSK_PHONE_NUMBER,
|
||||||
|
ContactsDbIngestModuleFactory.moduleName, phone)
|
||||||
|
))
|
||||||
|
|
||||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME_PERSON.getTypeID(),
|
|
||||||
ContactsDbIngestModuleFactory.moduleName, name))
|
|
||||||
|
|
||||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL.getTypeID(),
|
|
||||||
ContactsDbIngestModuleFactory.moduleName, email))
|
|
||||||
|
|
||||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(),
|
|
||||||
ContactsDbIngestModuleFactory.moduleName, phone))
|
|
||||||
|
|
||||||
art.addAttributes(attributes)
|
|
||||||
try:
|
try:
|
||||||
# index the artifact for keyword search
|
# index the artifact for keyword search
|
||||||
blackboard.indexArtifact(art)
|
blackboard.postArtifact(art, ContactsDbIngestModuleFactory.moduleName)
|
||||||
except Blackboard.BlackboardException as e:
|
except Blackboard.BlackboardException as e:
|
||||||
self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName())
|
self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName())
|
||||||
|
|
||||||
# Fire an event to notify the UI and others that there are new artifacts
|
|
||||||
IngestServices.getInstance().fireModuleDataEvent(
|
|
||||||
ModuleDataEvent(ContactsDbIngestModuleFactory.moduleName,
|
|
||||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT, None))
|
|
||||||
|
|
||||||
# Clean up
|
# Clean up
|
||||||
stmt.close()
|
stmt.close()
|
||||||
dbConn.close()
|
dbConn.close()
|
||||||
|
@ -145,7 +145,7 @@ class RunExeIngestModule(DataSourceIngestModule):
|
|||||||
# Add each argument in its own line. I.e. "-f foo" would be two calls to .add()
|
# Add each argument in its own line. I.e. "-f foo" would be two calls to .add()
|
||||||
cmd.add(imagePaths[0])
|
cmd.add(imagePaths[0])
|
||||||
|
|
||||||
processBuilder = ProcessBuilder(cmd);
|
processBuilder = ProcessBuilder(cmd)
|
||||||
processBuilder.redirectOutput(reportFile)
|
processBuilder.redirectOutput(reportFile)
|
||||||
ExecUtil.execute(processBuilder, DataSourceIngestModuleProcessTerminator(self.context))
|
ExecUtil.execute(processBuilder, DataSourceIngestModuleProcessTerminator(self.context))
|
||||||
|
|
||||||
|
@ -57,6 +57,8 @@ from org.sleuthkit.autopsy.casemodule import Case
|
|||||||
from org.sleuthkit.autopsy.casemodule.services import Services
|
from org.sleuthkit.autopsy.casemodule.services import Services
|
||||||
from org.sleuthkit.autopsy.casemodule.services import FileManager
|
from org.sleuthkit.autopsy.casemodule.services import FileManager
|
||||||
from org.sleuthkit.autopsy.casemodule.services import Blackboard
|
from org.sleuthkit.autopsy.casemodule.services import Blackboard
|
||||||
|
from org.sleuthkit.datamodel import Score
|
||||||
|
from java.util import Arrays
|
||||||
|
|
||||||
# Factory that defines the name and details of the module and allows Autopsy
|
# Factory that defines the name and details of the module and allows Autopsy
|
||||||
# to create instances of the modules that will do the anlaysis.
|
# to create instances of the modules that will do the anlaysis.
|
||||||
@ -107,7 +109,7 @@ class FindBigRoundFilesIngestModule(FileIngestModule):
|
|||||||
def process(self, file):
|
def process(self, file):
|
||||||
|
|
||||||
# Use blackboard class to index blackboard artifacts for keyword search
|
# Use blackboard class to index blackboard artifacts for keyword search
|
||||||
blackboard = Case.getCurrentCase().getServices().getBlackboard()
|
blackboard = Case.getCurrentCase().getSleuthkitCase().getBlackboard()
|
||||||
|
|
||||||
# Skip non-files
|
# Skip non-files
|
||||||
if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or
|
if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) or
|
||||||
@ -120,22 +122,19 @@ class FindBigRoundFilesIngestModule(FileIngestModule):
|
|||||||
|
|
||||||
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
|
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
|
||||||
# artifact. Refer to the developer docs for other examples.
|
# artifact. Refer to the developer docs for other examples.
|
||||||
art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT)
|
art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE,
|
||||||
att = BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(),
|
None, "Big and Round Files", None,
|
||||||
FindBigRoundFilesIngestModuleFactory.moduleName, "Big and Round Files")
|
Arrays.asList(
|
||||||
art.addAttribute(att)
|
BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME,
|
||||||
|
FindBigRoundFilesIngestModuleFactory.moduleName,
|
||||||
|
"Big and Round Files"))).getAnalysisResult()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# index the artifact for keyword search
|
# post the artifact for listeners of artifact events
|
||||||
blackboard.indexArtifact(art)
|
blackboard.postArtifact(art, FindBigRoundFilesIngestModuleFactory.moduleName)
|
||||||
except Blackboard.BlackboardException as e:
|
except Blackboard.BlackboardException as e:
|
||||||
self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName())
|
self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName())
|
||||||
|
|
||||||
# Fire an event to notify the UI and others that there is a new artifact
|
|
||||||
IngestServices.getInstance().fireModuleDataEvent(
|
|
||||||
ModuleDataEvent(FindBigRoundFilesIngestModuleFactory.moduleName,
|
|
||||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None))
|
|
||||||
|
|
||||||
return IngestModule.ProcessResult.OK
|
return IngestModule.ProcessResult.OK
|
||||||
|
|
||||||
# Where any shutdown code is run and resources are freed.
|
# Where any shutdown code is run and resources are freed.
|
||||||
|
@ -45,12 +45,13 @@ from java.lang import Class
|
|||||||
from java.lang import System
|
from java.lang import System
|
||||||
from java.sql import DriverManager, SQLException
|
from java.sql import DriverManager, SQLException
|
||||||
from java.util.logging import Level
|
from java.util.logging import Level
|
||||||
from java.util import ArrayList
|
from java.util import Arrays
|
||||||
from org.sleuthkit.datamodel import SleuthkitCase
|
from org.sleuthkit.datamodel import SleuthkitCase
|
||||||
from org.sleuthkit.datamodel import AbstractFile
|
from org.sleuthkit.datamodel import AbstractFile
|
||||||
from org.sleuthkit.datamodel import ReadContentInputStream
|
from org.sleuthkit.datamodel import ReadContentInputStream
|
||||||
from org.sleuthkit.datamodel import BlackboardArtifact
|
from org.sleuthkit.datamodel import BlackboardArtifact
|
||||||
from org.sleuthkit.datamodel import BlackboardAttribute
|
from org.sleuthkit.datamodel import BlackboardAttribute
|
||||||
|
from org.sleuthkit.datamodel import Blackboard
|
||||||
from org.sleuthkit.datamodel import TskData
|
from org.sleuthkit.datamodel import TskData
|
||||||
from org.sleuthkit.autopsy.ingest import IngestModule
|
from org.sleuthkit.autopsy.ingest import IngestModule
|
||||||
from org.sleuthkit.autopsy.ingest.IngestModule import IngestModuleException
|
from org.sleuthkit.autopsy.ingest.IngestModule import IngestModuleException
|
||||||
@ -130,12 +131,13 @@ class RegistryExampleIngestModule(DataSourceIngestModule):
|
|||||||
tempDir = os.path.join(Case.getCurrentCase().getTempDirectory(), "RegistryExample")
|
tempDir = os.path.join(Case.getCurrentCase().getTempDirectory(), "RegistryExample")
|
||||||
self.log(Level.INFO, "create Directory " + tempDir)
|
self.log(Level.INFO, "create Directory " + tempDir)
|
||||||
try:
|
try:
|
||||||
os.mkdir(tempDir)
|
os.mkdir(tempDir)
|
||||||
except:
|
except:
|
||||||
self.log(Level.INFO, "ExampleRegistry Directory already exists " + tempDir)
|
self.log(Level.INFO, "ExampleRegistry Directory already exists " + tempDir)
|
||||||
|
|
||||||
# Set the database to be read to the once created by the prefetch parser program
|
# Set the database to be read to the once created by the prefetch parser program
|
||||||
skCase = Case.getCurrentCase().getSleuthkitCase();
|
skCase = Case.getCurrentCase().getSleuthkitCase()
|
||||||
|
blackboard = Case.getCurrentCase().getSleuthkitCase().getBlackboard()
|
||||||
fileManager = Case.getCurrentCase().getServices().getFileManager()
|
fileManager = Case.getCurrentCase().getServices().getFileManager()
|
||||||
|
|
||||||
# Look for files to process
|
# Look for files to process
|
||||||
@ -170,12 +172,12 @@ class RegistryExampleIngestModule(DataSourceIngestModule):
|
|||||||
|
|
||||||
|
|
||||||
# Setup Artifact and Attributes
|
# Setup Artifact and Attributes
|
||||||
try:
|
artType = skCase.getArtifactType("TSK_REGISTRY_RUN_KEYS")
|
||||||
artID = skCase.addArtifactType( "TSK_REGISTRY_RUN_KEYS", "Registry Run Keys")
|
if not artType:
|
||||||
except:
|
try:
|
||||||
self.log(Level.INFO, "Artifacts Creation Error, some artifacts may not exist now. ==> ")
|
artType = skCase.addBlackboardArtifactType( "TSK_REGISTRY_RUN_KEYS", "Registry Run Keys")
|
||||||
|
except:
|
||||||
artId = skCase.getArtifactTypeID("TSK_REGISTRY_RUN_KEYS")
|
self.log(Level.WARNING, "Artifacts Creation Error, some artifacts may not exist now. ==> ")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
attributeIdRunKeyName = skCase.addArtifactAttributeType("TSK_REG_RUN_KEY_NAME", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Run Key Name")
|
attributeIdRunKeyName = skCase.addArtifactAttributeType("TSK_REG_RUN_KEY_NAME", BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, "Run Key Name")
|
||||||
@ -198,25 +200,24 @@ class RegistryExampleIngestModule(DataSourceIngestModule):
|
|||||||
|
|
||||||
# RefistryKeysFound is a list that contains a list with the following records abstractFile, Registry Key Location, Key Name, Key value
|
# RefistryKeysFound is a list that contains a list with the following records abstractFile, Registry Key Location, Key Name, Key value
|
||||||
for registryKey in self.registryKeysFound:
|
for registryKey in self.registryKeysFound:
|
||||||
attributes = ArrayList()
|
self.log(Level.INFO, "Creating artifact for registry key with path: " + registryKey[1] + " and key: " + registryKey[2])
|
||||||
art = registryKey[0].newArtifact(artId)
|
art = registryKey[0].newDataArtifact(artType, Arrays.asList(
|
||||||
|
BlackboardAttribute(attributeIdRegKeyLoc, moduleName, registryKey[1]),
|
||||||
attributes.add(BlackboardAttribute(attributeIdRegKeyLoc, moduleName, registryKey[1]))
|
BlackboardAttribute(attributeIdRunKeyName, moduleName, registryKey[2]),
|
||||||
attributes.add(BlackboardAttribute(attributeIdRunKeyName, moduleName, registryKey[2]))
|
BlackboardAttribute(attributeIdRunKeyValue, moduleName, registryKey[3])
|
||||||
attributes.add(BlackboardAttribute(attributeIdRunKeyValue, moduleName, registryKey[3]))
|
))
|
||||||
art.addAttributes(attributes)
|
|
||||||
|
|
||||||
# index the artifact for keyword search
|
# index the artifact for keyword search
|
||||||
try:
|
try:
|
||||||
blackboard.indexArtifact(art)
|
blackboard.postArtifact(art, moduleName)
|
||||||
except:
|
except Blackboard.BlackboardException as ex:
|
||||||
self._logger.log(Level.WARNING, "Error indexing artifact " + art.getDisplayName())
|
self.log(Level.SEVERE, "Unable to index blackboard artifact " + str(art.getArtifactTypeName()), ex)
|
||||||
|
|
||||||
#Clean up registryExample directory and files
|
#Clean up registryExample directory and files
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(tempDir)
|
shutil.rmtree(tempDir)
|
||||||
except:
|
except:
|
||||||
self.log(Level.INFO, "removal of directory tree failed " + tempDir)
|
self.log(Level.INFO, "removal of directory tree failed " + tempDir)
|
||||||
|
|
||||||
# After all databases, post a message to the ingest messages in box.
|
# After all databases, post a message to the ingest messages in box.
|
||||||
message = IngestMessage.createMessage(IngestMessage.MessageType.DATA,
|
message = IngestMessage.createMessage(IngestMessage.MessageType.DATA,
|
||||||
@ -236,7 +237,7 @@ class RegistryExampleIngestModule(DataSourceIngestModule):
|
|||||||
softwareRegFile = RegistryHiveFile(File(softwareHive))
|
softwareRegFile = RegistryHiveFile(File(softwareHive))
|
||||||
for runKey in self.registrySoftwareRunKeys:
|
for runKey in self.registrySoftwareRunKeys:
|
||||||
currentKey = self.findRegistryKey(softwareRegFile, runKey)
|
currentKey = self.findRegistryKey(softwareRegFile, runKey)
|
||||||
if len(currentKey.getValueList()) > 0:
|
if currentKey and len(currentKey.getValueList()) > 0:
|
||||||
skValues = currentKey.getValueList()
|
skValues = currentKey.getValueList()
|
||||||
for skValue in skValues:
|
for skValue in skValues:
|
||||||
regKey = []
|
regKey = []
|
||||||
@ -255,7 +256,7 @@ class RegistryExampleIngestModule(DataSourceIngestModule):
|
|||||||
ntuserRegFile = RegistryHiveFile(File(ntuserHive))
|
ntuserRegFile = RegistryHiveFile(File(ntuserHive))
|
||||||
for runKey in self.registryNTUserRunKeys:
|
for runKey in self.registryNTUserRunKeys:
|
||||||
currentKey = self.findRegistryKey(ntuserRegFile, runKey)
|
currentKey = self.findRegistryKey(ntuserRegFile, runKey)
|
||||||
if len(currentKey.getValueList()) > 0:
|
if currentKey and len(currentKey.getValueList()) > 0:
|
||||||
skValues = currentKey.getValueList()
|
skValues = currentKey.getValueList()
|
||||||
for skValue in skValues:
|
for skValue in skValues:
|
||||||
regKey = []
|
regKey = []
|
||||||
@ -276,9 +277,10 @@ class RegistryExampleIngestModule(DataSourceIngestModule):
|
|||||||
for key in regKeyList:
|
for key in regKeyList:
|
||||||
currentKey = currentKey.getSubkey(key)
|
currentKey = currentKey.getSubkey(key)
|
||||||
return currentKey
|
return currentKey
|
||||||
except:
|
except Exception as ex:
|
||||||
# Key not found
|
# Key not found
|
||||||
return null
|
self.log(Level.SEVERE, "registry key parsing issue:", ex)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import codecs
|
||||||
from java.lang import System
|
from java.lang import System
|
||||||
from java.util.logging import Level
|
from java.util.logging import Level
|
||||||
from org.sleuthkit.datamodel import TskData
|
from org.sleuthkit.datamodel import TskData
|
||||||
@ -72,11 +73,11 @@ class CSVReportModule(GeneralReportModuleAdapter):
|
|||||||
# The 'baseReportDir' object being passed in is a string with the directory that reports are being stored in. Report should go into baseReportDir + getRelativeFilePath().
|
# The 'baseReportDir' object being passed in is a string with the directory that reports are being stored in. Report should go into baseReportDir + getRelativeFilePath().
|
||||||
# The 'progressBar' object is of type ReportProgressPanel.
|
# The 'progressBar' object is of type ReportProgressPanel.
|
||||||
# See: http://sleuthkit.org/autopsy/docs/api-docs/latest/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html
|
# See: http://sleuthkit.org/autopsy/docs/api-docs/latest/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html
|
||||||
def generateReport(self, baseReportDir, progressBar):
|
def generateReport(self, reportSettings, progressBar):
|
||||||
|
|
||||||
# Open the output file.
|
# Open the output file.
|
||||||
fileName = os.path.join(baseReportDir, self.getRelativeFilePath())
|
fileName = os.path.join(reportSettings.getReportDirectoryPath(), self.getRelativeFilePath())
|
||||||
report = open(fileName, 'w')
|
report = codecs.open(fileName, "w", "utf-8")
|
||||||
|
|
||||||
# Query the database for the files (ignore the directories)
|
# Query the database for the files (ignore the directories)
|
||||||
sleuthkitCase = Case.getCurrentCase().getSleuthkitCase()
|
sleuthkitCase = Case.getCurrentCase().getSleuthkitCase()
|
||||||
|
@ -53,9 +53,8 @@ from org.sleuthkit.autopsy.casemodule import Case
|
|||||||
from org.sleuthkit.autopsy.casemodule.services import Services
|
from org.sleuthkit.autopsy.casemodule.services import Services
|
||||||
from org.sleuthkit.autopsy.casemodule.services import FileManager
|
from org.sleuthkit.autopsy.casemodule.services import FileManager
|
||||||
from org.sleuthkit.autopsy.casemodule.services import Blackboard
|
from org.sleuthkit.autopsy.casemodule.services import Blackboard
|
||||||
from org.sleuthkit.autopsy.casemodule.services import Blackboard
|
|
||||||
from org.sleuthkit.datamodel import Score
|
from org.sleuthkit.datamodel import Score
|
||||||
from java.util import ArrayList
|
from java.util import Arrays
|
||||||
|
|
||||||
# Factory that defines the name and details of the module and allows Autopsy
|
# Factory that defines the name and details of the module and allows Autopsy
|
||||||
# to create instances of the modules that will do the analysis.
|
# to create instances of the modules that will do the analysis.
|
||||||
@ -86,8 +85,6 @@ class SampleJythonDataSourceIngestModuleFactory(IngestModuleFactoryAdapter):
|
|||||||
# Data Source-level ingest module. One gets created per data source.
|
# Data Source-level ingest module. One gets created per data source.
|
||||||
# TODO: Rename this to something more specific. Could just remove "Factory" from above name.
|
# TODO: Rename this to something more specific. Could just remove "Factory" from above name.
|
||||||
class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
|
class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
|
||||||
LIKELY_NOTABLE_SCORE = Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO)
|
|
||||||
|
|
||||||
_logger = Logger.getLogger(SampleJythonDataSourceIngestModuleFactory.moduleName)
|
_logger = Logger.getLogger(SampleJythonDataSourceIngestModuleFactory.moduleName)
|
||||||
|
|
||||||
def log(self, level, msg):
|
def log(self, level, msg):
|
||||||
@ -118,7 +115,7 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
|
|||||||
progressBar.switchToIndeterminate()
|
progressBar.switchToIndeterminate()
|
||||||
|
|
||||||
# Use blackboard class to index blackboard artifacts for keyword search
|
# Use blackboard class to index blackboard artifacts for keyword search
|
||||||
blackboard = Case.getCurrentCase().getServices().getBlackboard()
|
blackboard = Case.getCurrentCase().getSleuthkitCase().getBlackboard()
|
||||||
|
|
||||||
# For our example, we will use FileManager to get all
|
# For our example, we will use FileManager to get all
|
||||||
# files with the word "test"
|
# files with the word "test"
|
||||||
@ -142,13 +139,15 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
|
|||||||
|
|
||||||
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
|
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
|
||||||
# artfiact. Refer to the developer docs for other examples.
|
# artfiact. Refer to the developer docs for other examples.
|
||||||
attrs = ArrayList()
|
attrs = Arrays.asList(BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME,
|
||||||
attrs.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, SampleJythonDataSourceIngestModuleFactory.moduleName, "Test file"))
|
SampleJythonDataSourceIngestModuleFactory.moduleName,
|
||||||
art = file.newAnalysisResult(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, self.LIKELY_NOTABLE_SCORE, None, "Test file", None, attrs)
|
"Test file"))
|
||||||
|
art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE,
|
||||||
|
None, "Test file", None, attrs).getAnalysisResult()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# index the artifact for keyword search
|
# post the artifact for listeners of artifact events.
|
||||||
blackboard.indexArtifact(art)
|
blackboard.postArtifact(art, SampleJythonDataSourceIngestModuleFactory.moduleName)
|
||||||
except Blackboard.BlackboardException as e:
|
except Blackboard.BlackboardException as e:
|
||||||
self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName())
|
self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName())
|
||||||
|
|
||||||
|
@ -55,8 +55,7 @@ from org.sleuthkit.autopsy.casemodule import Case
|
|||||||
from org.sleuthkit.autopsy.casemodule.services import Services
|
from org.sleuthkit.autopsy.casemodule.services import Services
|
||||||
from org.sleuthkit.autopsy.casemodule.services import FileManager
|
from org.sleuthkit.autopsy.casemodule.services import FileManager
|
||||||
from org.sleuthkit.autopsy.casemodule.services import Blackboard
|
from org.sleuthkit.autopsy.casemodule.services import Blackboard
|
||||||
from org.sleuthkit.datamodel import Score
|
from java.util import Arrays
|
||||||
from java.util import ArrayList
|
|
||||||
|
|
||||||
# Factory that defines the name and details of the module and allows Autopsy
|
# Factory that defines the name and details of the module and allows Autopsy
|
||||||
# to create instances of the modules that will do the anlaysis.
|
# to create instances of the modules that will do the anlaysis.
|
||||||
@ -89,7 +88,6 @@ class SampleJythonFileIngestModuleFactory(IngestModuleFactoryAdapter):
|
|||||||
# TODO: Rename this to something more specific. Could just remove "Factory" from above name.
|
# TODO: Rename this to something more specific. Could just remove "Factory" from above name.
|
||||||
# Looks at the attributes of the passed in file.
|
# Looks at the attributes of the passed in file.
|
||||||
class SampleJythonFileIngestModule(FileIngestModule):
|
class SampleJythonFileIngestModule(FileIngestModule):
|
||||||
LIKELY_NOTABLE_SCORE = Score(Score.Significance.LIKELY_NOTABLE, Score.MethodCategory.AUTO)
|
|
||||||
|
|
||||||
_logger = Logger.getLogger(SampleJythonFileIngestModuleFactory.moduleName)
|
_logger = Logger.getLogger(SampleJythonFileIngestModuleFactory.moduleName)
|
||||||
|
|
||||||
@ -119,7 +117,7 @@ class SampleJythonFileIngestModule(FileIngestModule):
|
|||||||
return IngestModule.ProcessResult.OK
|
return IngestModule.ProcessResult.OK
|
||||||
|
|
||||||
# Use blackboard class to index blackboard artifacts for keyword search
|
# Use blackboard class to index blackboard artifacts for keyword search
|
||||||
blackboard = Case.getCurrentCase().getServices().getBlackboard()
|
blackboard = Case.getCurrentCase().getSleuthkitCase().getBlackboard()
|
||||||
|
|
||||||
# For an example, we will flag files with .txt in the name and make a blackboard artifact.
|
# For an example, we will flag files with .txt in the name and make a blackboard artifact.
|
||||||
if file.getName().lower().endswith(".txt"):
|
if file.getName().lower().endswith(".txt"):
|
||||||
@ -129,23 +127,18 @@ class SampleJythonFileIngestModule(FileIngestModule):
|
|||||||
|
|
||||||
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
|
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
|
||||||
# artifact. Refer to the developer docs for other examples.
|
# artifact. Refer to the developer docs for other examples.
|
||||||
attrs = ArrayList()
|
attrs = Arrays.asList(BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME,
|
||||||
attrs.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME,
|
|
||||||
SampleJythonFileIngestModuleFactory.moduleName, "Text Files"))
|
SampleJythonFileIngestModuleFactory.moduleName, "Text Files"))
|
||||||
art = file.newAnalysisResult(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, self.LIKELY_NOTABLE_SCORE, None, "Text Files", None, attrs)
|
|
||||||
|
|
||||||
|
art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE,
|
||||||
|
None, "Text Files", None, attrs).getAnalysisResult()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# index the artifact for keyword search
|
# post the artifact for listeners of artifact events
|
||||||
blackboard.indexArtifact(art)
|
blackboard.postArtifact(art, SampleJythonFileIngestModuleFactory.moduleName)
|
||||||
except Blackboard.BlackboardException as e:
|
except Blackboard.BlackboardException as e:
|
||||||
self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName())
|
self.log(Level.SEVERE, "Error indexing artifact " + art.getDisplayName())
|
||||||
|
|
||||||
# Fire an event to notify the UI and others that there is a new artifact
|
|
||||||
IngestServices.getInstance().fireModuleDataEvent(
|
|
||||||
ModuleDataEvent(SampleJythonFileIngestModuleFactory.moduleName,
|
|
||||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, None))
|
|
||||||
|
|
||||||
# For the example (this wouldn't be needed normally), we'll query the blackboard for data that was added
|
# For the example (this wouldn't be needed normally), we'll query the blackboard for data that was added
|
||||||
# by other modules. We then iterate over its attributes. We'll just print them, but you would probably
|
# by other modules. We then iterate over its attributes. We'll just print them, but you would probably
|
||||||
# want to do something with them.
|
# want to do something with them.
|
||||||
|
@ -67,10 +67,12 @@ class SampleGeneralReportModule(GeneralReportModuleAdapter):
|
|||||||
return "sampleReport.txt"
|
return "sampleReport.txt"
|
||||||
|
|
||||||
# TODO: Update this method to make a report
|
# TODO: Update this method to make a report
|
||||||
# The 'baseReportDir' object being passed in is a string with the directory that reports are being stored in. Report should go into baseReportDir + getRelativeFilePath().
|
# The 'reportSettings' object being passed in is an instance of org.sleuthkit.autopsy.report.GeneralReportSettings.
|
||||||
|
# GeneralReportSettings.getReportDirectoryPath() is the directory that reports are being stored in.
|
||||||
|
# Report should go into GeneralReportSettings.getReportDirectoryPath() + getRelativeFilePath().
|
||||||
# The 'progressBar' object is of type ReportProgressPanel.
|
# The 'progressBar' object is of type ReportProgressPanel.
|
||||||
# See: http://sleuthkit.org/autopsy/docs/api-docs/latest/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html
|
# See: http://sleuthkit.org/autopsy/docs/api-docs/latest/classorg_1_1sleuthkit_1_1autopsy_1_1report_1_1_report_progress_panel.html
|
||||||
def generateReport(self, baseReportDir, progressBar):
|
def generateReport(self, reportSettings, progressBar):
|
||||||
|
|
||||||
# For an example, we write a file with the number of files created in the past 2 weeks
|
# For an example, we write a file with the number of files created in the past 2 weeks
|
||||||
# Configure progress bar for 2 tasks
|
# Configure progress bar for 2 tasks
|
||||||
@ -95,7 +97,7 @@ class SampleGeneralReportModule(GeneralReportModuleAdapter):
|
|||||||
progressBar.increment()
|
progressBar.increment()
|
||||||
|
|
||||||
# Write the count to the report file.
|
# Write the count to the report file.
|
||||||
fileName = os.path.join(baseReportDir, self.getRelativeFilePath())
|
fileName = os.path.join(reportSettings.getReportDirectoryPath(), self.getRelativeFilePath())
|
||||||
report = open(fileName, 'w')
|
report = open(fileName, 'w')
|
||||||
report.write("file count = %d" % fileCount)
|
report.write("file count = %d" % fileCount)
|
||||||
report.close()
|
report.close()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user