mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-13 16:36:15 +00:00
Merge branch 'develop' of https://github.com/sleuthkit/autopsy into 7938-OsAccountOCollumn
This commit is contained in:
commit
c63aed98a6
@ -25,8 +25,8 @@ import java.nio.file.Files;
|
|||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -89,7 +89,7 @@ public final class OtherOccurrences {
|
|||||||
logger.log(Level.INFO, String.format("Unable to check create CorrelationAttribtueInstance for osAccount %s.", osAccountAddr.get()), ex);
|
logger.log(Level.INFO, String.format("Unable to check create CorrelationAttribtueInstance for osAccount %s.", osAccountAddr.get()), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new ArrayList<>();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.centralrepository.datamodel;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@ -86,7 +87,7 @@ public class CorrelationAttributeUtil {
|
|||||||
if (artifactTypeID == ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()
|
if (artifactTypeID == ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()
|
||||||
|| artifactTypeID == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()
|
|| artifactTypeID == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()
|
||||||
|| artifactTypeID == ARTIFACT_TYPE.TSK_CONTACT.getTypeID()) {
|
|| artifactTypeID == ARTIFACT_TYPE.TSK_CONTACT.getTypeID()) {
|
||||||
return new ArrayList<>();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
return CorrelationAttributeUtil.makeCorrAttrsForSearch(artifact);
|
return CorrelationAttributeUtil.makeCorrAttrsForSearch(artifact);
|
||||||
}
|
}
|
||||||
@ -109,7 +110,7 @@ public class CorrelationAttributeUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static List<CorrelationAttributeInstance> makeCorrAttrsToSave(AnalysisResult file) {
|
public static List<CorrelationAttributeInstance> makeCorrAttrsToSave(AnalysisResult file) {
|
||||||
return new ArrayList<>();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<CorrelationAttributeInstance> makeCorrAttrsToSave(OsAccountInstance osAccountInstance) {
|
public static List<CorrelationAttributeInstance> makeCorrAttrsToSave(OsAccountInstance osAccountInstance) {
|
||||||
@ -354,7 +355,7 @@ public class CorrelationAttributeUtil {
|
|||||||
/*
|
/*
|
||||||
* Normalize the phone number.
|
* Normalize the phone number.
|
||||||
*/
|
*/
|
||||||
List<CorrelationAttributeInstance> corrAttrInstances = new ArrayList<>();
|
List<CorrelationAttributeInstance> corrAttrInstances = Collections.emptyList();
|
||||||
if (value != null
|
if (value != null
|
||||||
&& CorrelationAttributeNormalizer.isValidPhoneNumber(value)) {
|
&& CorrelationAttributeNormalizer.isValidPhoneNumber(value)) {
|
||||||
value = CorrelationAttributeNormalizer.normalizePhone(value);
|
value = CorrelationAttributeNormalizer.normalizePhone(value);
|
||||||
|
@ -137,7 +137,7 @@ public class AnnotationUtils {
|
|||||||
* @return The pair of artifact (or null if not present) and content (either
|
* @return The pair of artifact (or null if not present) and content (either
|
||||||
* artifact parent content, the node content, or null).
|
* artifact parent content, the node content, or null).
|
||||||
*/
|
*/
|
||||||
private static Pair<BlackboardArtifact, Content> getDisplayContent(Node node) {
|
static DisplayTskItems getDisplayContent(Node node) {
|
||||||
BlackboardArtifactItem<?> artItem = node.getLookup().lookup(BlackboardArtifactItem.class);
|
BlackboardArtifactItem<?> artItem = node.getLookup().lookup(BlackboardArtifactItem.class);
|
||||||
BlackboardArtifact artifact = artItem == null ? null : artItem.getTskContent();
|
BlackboardArtifact artifact = artItem == null ? null : artItem.getTskContent();
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ public class AnnotationUtils {
|
|||||||
? artItem.getSourceContent()
|
? artItem.getSourceContent()
|
||||||
: node.getLookup().lookup(AbstractFile.class);
|
: node.getLookup().lookup(AbstractFile.class);
|
||||||
|
|
||||||
return Pair.of(artifact, content);
|
return new DisplayTskItems(artifact, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -156,7 +156,7 @@ public class AnnotationUtils {
|
|||||||
* @return True if the node is supported.
|
* @return True if the node is supported.
|
||||||
*/
|
*/
|
||||||
public static boolean isSupported(Node node) {
|
public static boolean isSupported(Node node) {
|
||||||
return getDisplayContent(node).getRight() != null;
|
return getDisplayContent(node).getContent() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -172,9 +172,9 @@ public class AnnotationUtils {
|
|||||||
Document html = Jsoup.parse(EMPTY_HTML);
|
Document html = Jsoup.parse(EMPTY_HTML);
|
||||||
Element body = html.getElementsByTag("body").first();
|
Element body = html.getElementsByTag("body").first();
|
||||||
|
|
||||||
Pair<BlackboardArtifact, Content> displayPair = getDisplayContent(node);
|
DisplayTskItems displayItems = getDisplayContent(node);
|
||||||
BlackboardArtifact artifact = displayPair.getLeft();
|
BlackboardArtifact artifact = displayItems.getArtifact();
|
||||||
Content srcContent = displayPair.getRight();
|
Content srcContent = displayItems.getContent();
|
||||||
|
|
||||||
boolean somethingWasRendered = false;
|
boolean somethingWasRendered = false;
|
||||||
if (artifact != null) {
|
if (artifact != null) {
|
||||||
@ -686,4 +686,39 @@ public class AnnotationUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The TSK items that are being displayed as deciphered from the netbeans
|
||||||
|
* node.
|
||||||
|
*/
|
||||||
|
static class DisplayTskItems {
|
||||||
|
|
||||||
|
private final BlackboardArtifact artifact;
|
||||||
|
private final Content content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main constructor.
|
||||||
|
*
|
||||||
|
* @param artifact The artifact being displayed or null.
|
||||||
|
* @param content The parent content or source file being displayed or
|
||||||
|
* null.
|
||||||
|
*/
|
||||||
|
DisplayTskItems(BlackboardArtifact artifact, Content content) {
|
||||||
|
this.artifact = artifact;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The selected artifact or null if no selected artifact.
|
||||||
|
*/
|
||||||
|
BlackboardArtifact getArtifact() {
|
||||||
|
return artifact;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The parent content or source file being displayed or null.
|
||||||
|
*/
|
||||||
|
Content getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.contentviewers.annotations;
|
package org.sleuthkit.autopsy.contentviewers.annotations;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.SwingWorker;
|
import javax.swing.SwingWorker;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import static org.openide.util.NbBundle.Messages;
|
import static org.openide.util.NbBundle.Messages;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
@ -29,8 +35,19 @@ import org.openide.util.lookup.ServiceProvider;
|
|||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
|
import org.openide.util.WeakListeners;
|
||||||
|
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.CommentChangedEvent;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent;
|
||||||
|
import org.sleuthkit.autopsy.contentviewers.annotations.AnnotationUtils.DisplayTskItems;
|
||||||
import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles;
|
import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerHtmlStyles;
|
||||||
import org.sleuthkit.autopsy.contentviewers.utils.ViewerPriority;
|
import org.sleuthkit.autopsy.contentviewers.utils.ViewerPriority;
|
||||||
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
|
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||||
|
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotations view of file contents.
|
* Annotations view of file contents.
|
||||||
@ -47,7 +64,75 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
|
|||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private static final Logger logger = Logger.getLogger(AnnotationsContentViewer.class.getName());
|
private static final Logger logger = Logger.getLogger(AnnotationsContentViewer.class.getName());
|
||||||
|
|
||||||
private AnnotationWorker worker;
|
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.CR_COMMENT_CHANGED);
|
||||||
|
|
||||||
|
private static final Set<IngestManager.IngestModuleEvent> INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED);
|
||||||
|
|
||||||
|
private static final Set<BlackboardArtifact.Type> ARTIFACT_TYPES_OF_INTEREST = ImmutableSet.of(
|
||||||
|
BlackboardArtifact.Type.TSK_HASHSET_HIT,
|
||||||
|
BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT
|
||||||
|
);
|
||||||
|
|
||||||
|
private final PropertyChangeListener ingestEventListener = (evt) -> {
|
||||||
|
Long curArtifactId = AnnotationsContentViewer.this.curArtifactId;
|
||||||
|
Long curContentId = AnnotationsContentViewer.this.curContentId;
|
||||||
|
|
||||||
|
if (curArtifactId == null && curContentId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it is a module data event
|
||||||
|
if (IngestManager.IngestModuleEvent.DATA_ADDED.toString().equals(evt.getPropertyName())
|
||||||
|
&& evt.getOldValue() instanceof ModuleDataEvent) {
|
||||||
|
|
||||||
|
ModuleDataEvent moduleDataEvent = (ModuleDataEvent) evt.getOldValue();
|
||||||
|
|
||||||
|
// if an artifact is relevant, refresh
|
||||||
|
if (ARTIFACT_TYPES_OF_INTEREST.contains(moduleDataEvent.getBlackboardArtifactType())) {
|
||||||
|
for (BlackboardArtifact artifact : moduleDataEvent.getArtifacts()) {
|
||||||
|
if ((curArtifactId != null && artifact.getArtifactID() == curArtifactId)
|
||||||
|
|| (curContentId != null && artifact.getObjectID() == curContentId)) {
|
||||||
|
refresh();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final PropertyChangeListener weakIngestEventListener = WeakListeners.propertyChange(ingestEventListener, null);
|
||||||
|
|
||||||
|
private final PropertyChangeListener caseEventListener = (evt) -> {
|
||||||
|
Long curArtifactId = AnnotationsContentViewer.this.curArtifactId;
|
||||||
|
Long curContentId = AnnotationsContentViewer.this.curContentId;
|
||||||
|
|
||||||
|
if (curArtifactId == null && curContentId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair<Long, Long> artifactContentId = getIdsFromEvent(evt);
|
||||||
|
Long artifactId = artifactContentId.getLeft();
|
||||||
|
Long contentId = artifactContentId.getRight();
|
||||||
|
|
||||||
|
// if there is a match of content id or artifact id and the event, refresh
|
||||||
|
if ((curArtifactId != null && curArtifactId.equals(artifactId)) || (curContentId != null && curContentId.equals(contentId))) {
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final PropertyChangeListener weakCaseEventListener = WeakListeners.propertyChange(caseEventListener, null);
|
||||||
|
|
||||||
|
private final Object updateLock = new Object();
|
||||||
|
|
||||||
|
private AnnotationWorker worker = null;
|
||||||
|
private Node node;
|
||||||
|
private Long curArtifactId;
|
||||||
|
private Long curContentId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of AnnotationsContentViewer.
|
* Creates an instance of AnnotationsContentViewer.
|
||||||
@ -55,23 +140,138 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
|
|||||||
public AnnotationsContentViewer() {
|
public AnnotationsContentViewer() {
|
||||||
initComponents();
|
initComponents();
|
||||||
ContentViewerHtmlStyles.setupHtmlJTextPane(textPanel);
|
ContentViewerHtmlStyles.setupHtmlJTextPane(textPanel);
|
||||||
|
registerListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers case event and ingest event listeners.
|
||||||
|
*/
|
||||||
|
private void registerListeners() {
|
||||||
|
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakCaseEventListener);
|
||||||
|
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakIngestEventListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
|
unregisterListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters case event and ingest event listeners.
|
||||||
|
*/
|
||||||
|
private void unregisterListeners() {
|
||||||
|
Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakCaseEventListener);
|
||||||
|
IngestManager.getInstance().addIngestModuleEventListener(INGEST_MODULE_EVENTS_OF_INTEREST, weakIngestEventListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setNode(Node node) {
|
public void setNode(Node node) {
|
||||||
resetComponent();
|
this.node = node;
|
||||||
|
DisplayTskItems displayItems = AnnotationUtils.getDisplayContent(node);
|
||||||
|
this.curArtifactId = displayItems.getArtifact() == null ? null : displayItems.getArtifact().getArtifactID();
|
||||||
|
this.curContentId = displayItems.getContent() == null ? null : displayItems.getContent().getId();
|
||||||
|
updateData(this.node, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (worker != null) {
|
/**
|
||||||
worker.cancel(true);
|
* Returns a pair of the artifact id (or null) and the content id (or null)
|
||||||
worker = null;
|
* for the case event.
|
||||||
|
*
|
||||||
|
* @param evt The case event.
|
||||||
|
*
|
||||||
|
* @return A pair of the artifact id (or null) and the content id (or null)
|
||||||
|
* for the case event.
|
||||||
|
*/
|
||||||
|
private static Pair<Long, Long> getIdsFromEvent(PropertyChangeEvent evt) {
|
||||||
|
Case.Events eventType = null;
|
||||||
|
try {
|
||||||
|
eventType = Case.Events.valueOf(evt.getPropertyName());
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Unknown event type: " + evt.getPropertyName(), ex);
|
||||||
|
return Pair.of(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Long artifactId = null;
|
||||||
|
Long contentId = null;
|
||||||
|
|
||||||
|
switch (eventType) {
|
||||||
|
case BLACKBOARD_ARTIFACT_TAG_ADDED:
|
||||||
|
if (evt instanceof BlackBoardArtifactTagAddedEvent) {
|
||||||
|
BlackboardArtifact art = ((BlackBoardArtifactTagAddedEvent) evt).getAddedTag().getArtifact();
|
||||||
|
artifactId = art.getArtifactID();
|
||||||
|
contentId = art.getObjectID();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BLACKBOARD_ARTIFACT_TAG_DELETED:
|
||||||
|
if (evt instanceof BlackBoardArtifactTagDeletedEvent) {
|
||||||
|
artifactId = ((BlackBoardArtifactTagDeletedEvent) evt).getDeletedTagInfo().getArtifactID();
|
||||||
|
contentId = ((BlackBoardArtifactTagDeletedEvent) evt).getDeletedTagInfo().getContentID();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONTENT_TAG_ADDED:
|
||||||
|
if (evt instanceof ContentTagAddedEvent) {
|
||||||
|
contentId = ((ContentTagAddedEvent) evt).getAddedTag().getContent().getId();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CONTENT_TAG_DELETED:
|
||||||
|
if (evt instanceof ContentTagDeletedEvent) {
|
||||||
|
contentId = ((ContentTagDeletedEvent) evt).getDeletedTagInfo().getContentID();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CR_COMMENT_CHANGED:
|
||||||
|
if (evt instanceof CommentChangedEvent) {
|
||||||
|
long commentObjId = ((CommentChangedEvent) evt).getContentID();
|
||||||
|
artifactId = commentObjId;
|
||||||
|
contentId = commentObjId;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
return Pair.of(artifactId, contentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes the data displayed.
|
||||||
|
*/
|
||||||
|
private void refresh() {
|
||||||
|
if (this.isVisible()) {
|
||||||
|
updateData(this.node, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates data displayed in the viewer.
|
||||||
|
*
|
||||||
|
* @param node The node to use for data.
|
||||||
|
* @param forceReset If true, forces a reset cancelling the previous worker
|
||||||
|
* if one exists and clearing data in the component. If
|
||||||
|
* false, only submits a worker if no previous worker is
|
||||||
|
* running.
|
||||||
|
*/
|
||||||
|
private void updateData(Node node, boolean forceReset) {
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
worker = new AnnotationWorker(node);
|
if (forceReset) {
|
||||||
worker.execute();
|
resetComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (updateLock) {
|
||||||
|
if (worker != null) {
|
||||||
|
if (forceReset) {
|
||||||
|
worker.cancel(true);
|
||||||
|
worker = null;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
worker = new AnnotationWorker(node, forceReset);
|
||||||
|
worker.execute();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -142,6 +342,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
|
|||||||
@Override
|
@Override
|
||||||
public void resetComponent() {
|
public void resetComponent() {
|
||||||
textPanel.setText("");
|
textPanel.setText("");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -151,9 +352,18 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
|
|||||||
private class AnnotationWorker extends SwingWorker<String, Void> {
|
private class AnnotationWorker extends SwingWorker<String, Void> {
|
||||||
|
|
||||||
private final Node node;
|
private final Node node;
|
||||||
|
private final boolean resetCaretPosition;
|
||||||
|
|
||||||
AnnotationWorker(Node node) {
|
/**
|
||||||
|
* Main constructor.
|
||||||
|
*
|
||||||
|
* @param node The node for which data will be fetched.
|
||||||
|
* @param resetCaretPosition Whether or not to reset the caret position
|
||||||
|
* when finished.
|
||||||
|
*/
|
||||||
|
AnnotationWorker(Node node, boolean resetCaretPosition) {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
|
this.resetCaretPosition = resetCaretPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -173,17 +383,25 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void done() {
|
public void done() {
|
||||||
if (isCancelled()) {
|
if (!isCancelled()) {
|
||||||
return;
|
try {
|
||||||
|
String text = get();
|
||||||
|
ContentViewerHtmlStyles.setStyles(textPanel);
|
||||||
|
textPanel.setText(text);
|
||||||
|
|
||||||
|
if (resetCaretPosition) {
|
||||||
|
textPanel.setCaretPosition(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (InterruptedException | ExecutionException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Failed to get annotation information for node", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
synchronized (updateLock) {
|
||||||
String text = get();
|
if (worker == this) {
|
||||||
ContentViewerHtmlStyles.setStyles(textPanel);
|
worker = null;
|
||||||
textPanel.setText(text);
|
}
|
||||||
textPanel.setCaretPosition(0);
|
|
||||||
} catch (InterruptedException | ExecutionException ex) {
|
|
||||||
logger.log(Level.SEVERE, "Failed to get annotation information for node", ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,13 +23,13 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
|
|||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An super class for an Autopsy Data Model item class with an underlying
|
* An abstract super class for an Autopsy Data Model item class with an
|
||||||
* BlackboardArtifact Sleuth Kit Data Model object, i.e., a DataArtifact or an
|
* underlying BlackboardArtifact Sleuth Kit Data Model object, i.e., a
|
||||||
* AnalysisResult.
|
* DataArtifact or an AnalysisResult.
|
||||||
*
|
*
|
||||||
* @param <T> The concrete BlackboardArtifact class type.
|
* @param <T> The concrete BlackboardArtifact sub class type.
|
||||||
*/
|
*/
|
||||||
public class BlackboardArtifactItem<T extends BlackboardArtifact> extends TskContentItem<T> {
|
public abstract class BlackboardArtifactItem<T extends BlackboardArtifact> extends TskContentItem<T> {
|
||||||
|
|
||||||
private final Content sourceContent;
|
private final Content sourceContent;
|
||||||
|
|
||||||
|
@ -404,10 +404,8 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
|||||||
BlackboardArtifactItem<?> artifactItem;
|
BlackboardArtifactItem<?> artifactItem;
|
||||||
if (artifact instanceof AnalysisResult) {
|
if (artifact instanceof AnalysisResult) {
|
||||||
artifactItem = new AnalysisResultItem((AnalysisResult) artifact, content);
|
artifactItem = new AnalysisResultItem((AnalysisResult) artifact, content);
|
||||||
} else if (artifact instanceof DataArtifact) {
|
|
||||||
artifactItem = new DataArtifactItem((DataArtifact) artifact, content);
|
|
||||||
} else {
|
} else {
|
||||||
artifactItem = new BlackboardArtifactItem<>(artifact, content);
|
artifactItem = new DataArtifactItem((DataArtifact) artifact, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -66,7 +66,7 @@ GeolocationPanel_onNoCrIngest_message=No results will be shown because the GPX P
|
|||||||
GeolocationPanel_unknownRow_title=Unknown
|
GeolocationPanel_unknownRow_title=Unknown
|
||||||
PastCasesPanel_caseColumn_title=Case
|
PastCasesPanel_caseColumn_title=Case
|
||||||
PastCasesPanel_countColumn_title=Count
|
PastCasesPanel_countColumn_title=Count
|
||||||
PastCasesPanel_notableFileTable_tabName=Cases with Common Notable
|
PastCasesPanel_notableFileTable_tabName=Cases with Common Notable Items at Time Of Ingest
|
||||||
PastCasesPanel_onNoCrIngest_message=No results will be shown because the Central Repository module was not run.
|
PastCasesPanel_onNoCrIngest_message=No results will be shown because the Central Repository module was not run.
|
||||||
PastCasesPanel_sameIdsTable_tabName=Past Cases with the Same Devices
|
PastCasesPanel_sameIdsTable_tabName=Past Cases with the Same Devices
|
||||||
RecentFilesPanel_attachmentsTable_tabName=Recent Attachments
|
RecentFilesPanel_attachmentsTable_tabName=Recent Attachments
|
||||||
@ -75,7 +75,7 @@ RecentFilesPanel_col_header_domain=Domain
|
|||||||
RecentFilesPanel_col_header_path=Path
|
RecentFilesPanel_col_header_path=Path
|
||||||
RecentFilesPanel_col_header_sender=Sender
|
RecentFilesPanel_col_header_sender=Sender
|
||||||
RecentFilesPanel_docsTable_tabName=Recently Opened Documents
|
RecentFilesPanel_docsTable_tabName=Recently Opened Documents
|
||||||
RecentFilesPanel_downloadsTable_tabName=Recently Downloads
|
RecentFilesPanel_downloadsTable_tabName=Recent Downloads
|
||||||
RecentFilesPanel_no_open_documents=No recently open documents found.
|
RecentFilesPanel_no_open_documents=No recently open documents found.
|
||||||
SizeRepresentationUtil_units_bytes=bytes
|
SizeRepresentationUtil_units_bytes=bytes
|
||||||
SizeRepresentationUtil_units_gigabytes=GB
|
SizeRepresentationUtil_units_gigabytes=GB
|
||||||
|
@ -41,7 +41,7 @@ import org.sleuthkit.datamodel.DataSource;
|
|||||||
"PastCasesPanel_caseColumn_title=Case",
|
"PastCasesPanel_caseColumn_title=Case",
|
||||||
"PastCasesPanel_countColumn_title=Count",
|
"PastCasesPanel_countColumn_title=Count",
|
||||||
"PastCasesPanel_onNoCrIngest_message=No results will be shown because the Central Repository module was not run.",
|
"PastCasesPanel_onNoCrIngest_message=No results will be shown because the Central Repository module was not run.",
|
||||||
"PastCasesPanel_notableFileTable_tabName=Cases with Common Notable",
|
"PastCasesPanel_notableFileTable_tabName=Cases with Common Notable Items at Time Of Ingest",
|
||||||
"PastCasesPanel_sameIdsTable_tabName=Past Cases with the Same Devices",})
|
"PastCasesPanel_sameIdsTable_tabName=Past Cases with the Same Devices",})
|
||||||
public class PastCasesPanel extends BaseDataSourceSummaryPanel {
|
public class PastCasesPanel extends BaseDataSourceSummaryPanel {
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ import org.sleuthkit.datamodel.DataSource;
|
|||||||
*/
|
*/
|
||||||
@Messages({
|
@Messages({
|
||||||
"RecentFilesPanel_docsTable_tabName=Recently Opened Documents",
|
"RecentFilesPanel_docsTable_tabName=Recently Opened Documents",
|
||||||
"RecentFilesPanel_downloadsTable_tabName=Recently Downloads",
|
"RecentFilesPanel_downloadsTable_tabName=Recent Downloads",
|
||||||
"RecentFilesPanel_attachmentsTable_tabName=Recent Attachments",})
|
"RecentFilesPanel_attachmentsTable_tabName=Recent Attachments",})
|
||||||
public final class RecentFilesPanel extends BaseDataSourceSummaryPanel {
|
public final class RecentFilesPanel extends BaseDataSourceSummaryPanel {
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import java.util.Collection;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.openide.util.Lookup;
|
import org.openide.util.Lookup;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
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.coreutils.ImageUtils;
|
import org.sleuthkit.autopsy.coreutils.ImageUtils;
|
||||||
@ -194,6 +195,7 @@ class SummaryHelpers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({"SummaryHelper.documentSummary.unable.to.read=Unable to extract text from file."})
|
||||||
/**
|
/**
|
||||||
* Get the beginning of text from the specified AbstractFile.
|
* Get the beginning of text from the specified AbstractFile.
|
||||||
*
|
*
|
||||||
@ -217,7 +219,7 @@ class SummaryHelpers {
|
|||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
return Bundle.FileSearch_documentSummary_noBytes();
|
return Bundle.FileSearch_documentSummary_noBytes();
|
||||||
} catch (TextExtractor.InitReaderException ex) {
|
} catch (TextExtractor.InitReaderException ex) {
|
||||||
return Bundle.FileSearch_documentSummary_noPreview();
|
return Bundle.SummaryHelper_documentSummary_unable_to_read();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ ExportIngestHistory_startTimeColumn=Start Time
|
|||||||
ExportIngestHistory_versionColumn=Module Version
|
ExportIngestHistory_versionColumn=Module Version
|
||||||
ExportPastCases_caseColumn_title=Case
|
ExportPastCases_caseColumn_title=Case
|
||||||
ExportPastCases_countColumn_title=Count
|
ExportPastCases_countColumn_title=Count
|
||||||
ExportPastCases_notableFileTable_tabName=Cases with Common Notable
|
ExportPastCases_notableFileTable_tabName=Cases with Common Notable Items at Time Of Ingest
|
||||||
ExportPastCases_sameIdsTable_tabName=Past Cases with the Same Devices
|
ExportPastCases_sameIdsTable_tabName=Past Cases with the Same Devices
|
||||||
ExportRecentFiles_attachmentsTable_tabName=Recent Attachments
|
ExportRecentFiles_attachmentsTable_tabName=Recent Attachments
|
||||||
ExportRecentFiles_col_head_date=Date
|
ExportRecentFiles_col_head_date=Date
|
||||||
|
@ -37,7 +37,7 @@ import org.sleuthkit.datamodel.DataSource;
|
|||||||
@Messages({
|
@Messages({
|
||||||
"ExportPastCases_caseColumn_title=Case",
|
"ExportPastCases_caseColumn_title=Case",
|
||||||
"ExportPastCases_countColumn_title=Count",
|
"ExportPastCases_countColumn_title=Count",
|
||||||
"ExportPastCases_notableFileTable_tabName=Cases with Common Notable",
|
"ExportPastCases_notableFileTable_tabName=Cases with Common Notable Items at Time Of Ingest",
|
||||||
"ExportPastCases_sameIdsTable_tabName=Past Cases with the Same Devices",})
|
"ExportPastCases_sameIdsTable_tabName=Past Cases with the Same Devices",})
|
||||||
class ExportPastCases {
|
class ExportPastCases {
|
||||||
|
|
||||||
|
@ -384,6 +384,20 @@ final class RegexQuery implements KeywordSearchQuery {
|
|||||||
}
|
}
|
||||||
// Replace all non numeric at the end of the hit.
|
// Replace all non numeric at the end of the hit.
|
||||||
hit = hit.replaceAll("[^0-9]$", "");
|
hit = hit.replaceAll("[^0-9]$", "");
|
||||||
|
|
||||||
|
if (offset > 1) {
|
||||||
|
/*
|
||||||
|
* NOTE: our IP and phone number regex patterns look for
|
||||||
|
* boundary characters immediately before and after
|
||||||
|
* the keyword hit. After a match, Java pattern
|
||||||
|
* mather re-starts at the first character not
|
||||||
|
* matched by the previous match. This basically
|
||||||
|
* requires two boundary characters to be present
|
||||||
|
* between each pattern match. To mitigate this we
|
||||||
|
* are resetting the offest one character back.
|
||||||
|
*/
|
||||||
|
offset--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,6 +5,10 @@ ChromeCacheExtract_adding_artifacts_msg=Chrome Cache: Adding %d artifacts for an
|
|||||||
ChromeCacheExtract_adding_extracted_files_msg=Chrome Cache: Adding %d extracted files for analysis.
|
ChromeCacheExtract_adding_extracted_files_msg=Chrome Cache: Adding %d extracted files for analysis.
|
||||||
ChromeCacheExtract_loading_files_msg=Chrome Cache: Loading files from %s.
|
ChromeCacheExtract_loading_files_msg=Chrome Cache: Loading files from %s.
|
||||||
ChromeCacheExtractor.moduleName=ChromeCacheExtractor
|
ChromeCacheExtractor.moduleName=ChromeCacheExtractor
|
||||||
|
# {0} - module name
|
||||||
|
# {1} - row number
|
||||||
|
# {2} - table length
|
||||||
|
# {3} - cache path
|
||||||
ChromeCacheExtractor.progressMsg={0}: Extracting cache entry {1} of {2} entries from {3}
|
ChromeCacheExtractor.progressMsg={0}: Extracting cache entry {1} of {2} entries from {3}
|
||||||
DataSourceUsage_AndroidMedia=Android Media Card
|
DataSourceUsage_AndroidMedia=Android Media Card
|
||||||
DataSourceUsage_DJU_Drone_DAT=DJI Internal SD Card
|
DataSourceUsage_DJU_Drone_DAT=DJI Internal SD Card
|
||||||
@ -152,13 +156,19 @@ Firefox.getDlV24.errMsg.errAnalyzeFile={0}: Error while trying to analyze file:{
|
|||||||
Firefox.getDlV24.errMsg.errParsingArtifacts={0}: Error parsing {1} Firefox web download artifacts.
|
Firefox.getDlV24.errMsg.errParsingArtifacts={0}: Error parsing {1} Firefox web download artifacts.
|
||||||
Progress_Message_Analyze_Registry=Analyzing Registry Files
|
Progress_Message_Analyze_Registry=Analyzing Registry Files
|
||||||
Progress_Message_Analyze_Usage=Data Sources Usage Analysis
|
Progress_Message_Analyze_Usage=Data Sources Usage Analysis
|
||||||
|
# {0} - browserName
|
||||||
Progress_Message_Chrome_AutoFill=Chrome Auto Fill Browser {0}
|
Progress_Message_Chrome_AutoFill=Chrome Auto Fill Browser {0}
|
||||||
|
# {0} - browserName
|
||||||
Progress_Message_Chrome_Bookmarks=Chrome Bookmarks Browser {0}
|
Progress_Message_Chrome_Bookmarks=Chrome Bookmarks Browser {0}
|
||||||
Progress_Message_Chrome_Cache=Chrome Cache
|
Progress_Message_Chrome_Cache=Chrome Cache
|
||||||
|
# {0} - browserName
|
||||||
Progress_Message_Chrome_Cookies=Chrome Cookies Browser {0}
|
Progress_Message_Chrome_Cookies=Chrome Cookies Browser {0}
|
||||||
|
# {0} - browserName
|
||||||
Progress_Message_Chrome_Downloads=Chrome Downloads Browser {0}
|
Progress_Message_Chrome_Downloads=Chrome Downloads Browser {0}
|
||||||
Progress_Message_Chrome_FormHistory=Chrome Form History
|
Progress_Message_Chrome_FormHistory=Chrome Form History
|
||||||
|
# {0} - browserName
|
||||||
Progress_Message_Chrome_History=Chrome History Browser {0}
|
Progress_Message_Chrome_History=Chrome History Browser {0}
|
||||||
|
# {0} - browserName
|
||||||
Progress_Message_Chrome_Logins=Chrome Logins Browser {0}
|
Progress_Message_Chrome_Logins=Chrome Logins Browser {0}
|
||||||
Progress_Message_Edge_Bookmarks=Microsoft Edge Bookmarks
|
Progress_Message_Edge_Bookmarks=Microsoft Edge Bookmarks
|
||||||
Progress_Message_Edge_Cookies=Microsoft Edge Cookies
|
Progress_Message_Edge_Cookies=Microsoft Edge Cookies
|
||||||
|
@ -592,8 +592,13 @@ final class ChromeCacheExtractor {
|
|||||||
|
|
||||||
// see if it is cached
|
// see if it is cached
|
||||||
String fileTableKey = cacheFolderName + cacheFileName;
|
String fileTableKey = cacheFolderName + cacheFileName;
|
||||||
if (cacheFileName.startsWith("f_") && externalFilesTable.containsKey(fileTableKey)) {
|
|
||||||
return Optional.of(externalFilesTable.get(fileTableKey));
|
if (cacheFileName != null) {
|
||||||
|
if (cacheFileName.startsWith("f_") && externalFilesTable.containsKey(fileTableKey)) {
|
||||||
|
return Optional.of(externalFilesTable.get(fileTableKey));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileCopyCache.containsKey(fileTableKey)) {
|
if (fileCopyCache.containsKey(fileTableKey)) {
|
||||||
@ -1306,7 +1311,7 @@ final class ChromeCacheExtractor {
|
|||||||
|
|
||||||
private String key; // Key may be found within the entry or may be external
|
private String key; // Key may be found within the entry or may be external
|
||||||
|
|
||||||
CacheEntry(CacheAddress cacheAdress, FileWrapper cacheFileCopy ) throws TskCoreException {
|
CacheEntry(CacheAddress cacheAdress, FileWrapper cacheFileCopy ) throws TskCoreException, IngestModuleException {
|
||||||
this.selfAddress = cacheAdress;
|
this.selfAddress = cacheAdress;
|
||||||
this.cacheFileCopy = cacheFileCopy;
|
this.cacheFileCopy = cacheFileCopy;
|
||||||
|
|
||||||
@ -1315,7 +1320,11 @@ final class ChromeCacheExtractor {
|
|||||||
int entryOffset = DATAFILE_HDR_SIZE + cacheAdress.getStartBlock() * cacheAdress.getBlockSize();
|
int entryOffset = DATAFILE_HDR_SIZE + cacheAdress.getStartBlock() * cacheAdress.getBlockSize();
|
||||||
|
|
||||||
// reposition the buffer to the the correct offset
|
// reposition the buffer to the the correct offset
|
||||||
fileROBuf.position(entryOffset);
|
if (entryOffset < fileROBuf.capacity()) {
|
||||||
|
fileROBuf.position(entryOffset);
|
||||||
|
} else {
|
||||||
|
throw new IngestModuleException("Position seeked in Buffer to big"); // NON-NLS
|
||||||
|
}
|
||||||
|
|
||||||
hash = fileROBuf.getInt() & UINT32_MASK;
|
hash = fileROBuf.getInt() & UINT32_MASK;
|
||||||
|
|
||||||
@ -1364,8 +1373,10 @@ final class ChromeCacheExtractor {
|
|||||||
if (longKeyAddresses != null) {
|
if (longKeyAddresses != null) {
|
||||||
// Key is stored outside of the entry
|
// Key is stored outside of the entry
|
||||||
try {
|
try {
|
||||||
CacheDataSegment data = new CacheDataSegment(longKeyAddresses, this.keyLen, true);
|
if (longKeyAddresses.getFilename() != null) {
|
||||||
key = data.getDataString();
|
CacheDataSegment data = new CacheDataSegment(longKeyAddresses, this.keyLen, true);
|
||||||
|
key = data.getDataString();
|
||||||
|
}
|
||||||
} catch (TskCoreException | IngestModuleException ex) {
|
} catch (TskCoreException | IngestModuleException ex) {
|
||||||
throw new TskCoreException(String.format("Failed to get external key from address %s", longKeyAddresses)); //NON-NLS
|
throw new TskCoreException(String.format("Failed to get external key from address %s", longKeyAddresses)); //NON-NLS
|
||||||
}
|
}
|
||||||
|
@ -318,7 +318,13 @@ final class ExtractZoneIdentifier extends Extract {
|
|||||||
*/
|
*/
|
||||||
ZoneIdentifierInfo(AbstractFile zoneFile) throws IOException {
|
ZoneIdentifierInfo(AbstractFile zoneFile) throws IOException {
|
||||||
fileName = zoneFile.getName();
|
fileName = zoneFile.getName();
|
||||||
properties.load(new ReadContentInputStream(zoneFile));
|
// properties.load will throw IllegalArgument if unicode characters are found in the zone file.
|
||||||
|
try {
|
||||||
|
properties.load(new ReadContentInputStream(zoneFile));
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
String message = String.format("Unable to parse Zone Id for File %s", fileName); //NON-NLS
|
||||||
|
LOG.log(Level.WARNING, message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user