Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ThreadChildNodeFactory.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2019 Basis Technology Corp.
5 * Contact: carrier <at> sleuthkit <dot> org
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19package org.sleuthkit.autopsy.communications.relationships;
20
21import java.util.Comparator;
22import java.util.HashMap;
23import java.util.List;
24import java.util.Map;
25import java.util.Set;
26import java.util.logging.Level;
27import javax.swing.Action;
28import org.openide.nodes.AbstractNode;
29import org.openide.nodes.ChildFactory;
30import org.openide.nodes.Children;
31import org.openide.nodes.Node;
32import org.openide.nodes.Sheet;
33import org.sleuthkit.autopsy.coreutils.Logger;
34import org.sleuthkit.autopsy.datamodel.NodeProperty;
35import org.sleuthkit.datamodel.BlackboardArtifact;
36import org.sleuthkit.datamodel.BlackboardAttribute;
37import org.sleuthkit.datamodel.Content;
38import org.sleuthkit.datamodel.TskCoreException;
39
45final class ThreadChildNodeFactory extends ChildFactory<BlackboardArtifact> {
46
47 private static final Logger logger = Logger.getLogger(ThreadChildNodeFactory.class.getName());
48
49 private SelectionInfo selectionInfo;
50
51 private final Action preferredAction;
52
59
60 ThreadChildNodeFactory(Action preferredAction) {
61 this.preferredAction = preferredAction;
62 }
63
69 public void refresh(SelectionInfo selectionInfo) {
70 this.selectionInfo = selectionInfo;
71 refresh(true);
72 }
73
82 @Override
83 protected boolean createKeys(List<BlackboardArtifact> list) {
84 if(selectionInfo == null) {
85 return true;
86 }
87
88 try {
89 final Set<Content> relationshipSources = selectionInfo.getRelationshipSources();
90 createRootMessageKeys(list, relationshipSources) ;
91 } catch (TskCoreException ex) {
92 logger.log(Level.SEVERE, "Failed to load relationship sources.", ex); //NON-NLS
93 return false;
94 }
95
96 return true;
97 }
98
110 private boolean createRootMessageKeys(List<BlackboardArtifact> list, Set<Content> relationshipSources) throws TskCoreException{
111 Map<String, BlackboardArtifact> rootMessageMap = new HashMap<>();
112 for(Content content: relationshipSources) {
113 if(!(content instanceof BlackboardArtifact)) {
114 continue;
115 }
116
117 BlackboardArtifact bba = (BlackboardArtifact) content;
118 BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba.getArtifactTypeID());
119
120 if (fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG
121 || fromID == BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) {
122
123 // We want email and message artifacts that do not have "threadIDs" to appear as one thread in the UI
124 // To achive this assign any artifact that does not have a threadID
125 // the "UNTHREADED_ID"
126 String threadID = MessageNode.UNTHREADED_ID;
127
128 BlackboardAttribute attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID));
129
130 if(attribute != null) {
131 threadID = attribute.getValueString();
132 }
133
134 BlackboardArtifact tableArtifact = rootMessageMap.get(threadID);
135 if(tableArtifact == null) {
136 rootMessageMap.put(threadID, bba);
137 } else {
138 // Get the date of the message
139 BlackboardAttribute tableAttribute = null;
140 switch(fromID) {
141 case TSK_EMAIL_MSG:
142 tableAttribute = tableArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
143 attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
144 // put the earliest message into the table
145 if(tableAttribute != null
146 && attribute != null
147 && tableAttribute.getValueLong() > attribute.getValueLong()) {
148 rootMessageMap.put(threadID, bba);
149 }
150 break;
151 case TSK_MESSAGE:
152 tableAttribute = tableArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
153 attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
154 // put the earliest message into the table
155 if(tableAttribute != null
156 && attribute != null
157 && tableAttribute.getValueLong() < attribute.getValueLong()) {
158 rootMessageMap.put(threadID, bba);
159 }
160 break;
161 case TSK_CALLLOG:
162 tableAttribute = tableArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
163 attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
164 // put the earliest message into the table
165 if(tableAttribute != null
166 && attribute != null
167 && tableAttribute.getValueLong() > attribute.getValueLong()) {
168 rootMessageMap.put(threadID, bba);
169 }
170 break;
171 }
172
173
174 }
175 }
176 }
177
178 for(BlackboardArtifact bba: rootMessageMap.values()) {
179 list.add(bba);
180 }
181
182 list.sort(new ThreadDateComparator());
183
184 return true;
185 }
186
187 @Override
188 protected Node createNodeForKey(BlackboardArtifact bba) {
189 BlackboardAttribute attribute = null;
190 try {
191 attribute = bba.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_THREAD_ID));
192 } catch (TskCoreException ex) {
193 logger.log(Level.WARNING, String.format("Unable to get threadID for artifact: %s", bba.getName()), ex);
194 }
195
196 if (attribute != null) {
197 return new ThreadNode(bba, attribute.getValueString(), preferredAction);
198 } else {
199 // Only one of these should occur.
200 return new UnthreadedNode();
201 }
202 }
203
207 final class UnthreadedNode extends AbstractNode {
211 UnthreadedNode() {
212 super(Children.LEAF);
213 setDisplayName("Unthreaded");
214 this.setIconBaseWithExtension("org/sleuthkit/autopsy/communications/images/unthreaded.png" );
215 }
216
217 @Override
218 protected Sheet createSheet() {
219 Sheet sheet = super.createSheet();
220 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
221 if (sheetSet == null) {
222 sheetSet = Sheet.createPropertiesSet();
223 sheet.put(sheetSet);
224 }
225
226 // Give this node a threadID of "UNTHEADED_ID"
227 sheetSet.put(new NodeProperty<>("ThreadID", "ThreadID","",MessageNode.UNTHREADED_ID));
228
229 return sheet;
230 }
231 }
232
240 class ThreadDateComparator implements Comparator<BlackboardArtifact> {
241
242 @Override
243 public int compare(BlackboardArtifact bba1, BlackboardArtifact bba2) {
244 BlackboardAttribute attribute1 = null;
245 BlackboardAttribute attribute2 = null;
246 // Inializing to Long.MAX_VALUE so that if a BlackboardArtifact of
247 // any unexpected type is passed in, it will bubble to the top of
248 // the list.
249 long dateTime1 = Long.MAX_VALUE;
250 long dateTime2 = Long.MAX_VALUE;
251
252 if (bba1 != null) {
253 BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba1.getArtifactTypeID());
254 if (fromID != null) {
255 try {
256 switch (fromID) {
257 case TSK_EMAIL_MSG:
258 attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
259
260 break;
261 case TSK_MESSAGE:
262 attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
263
264 break;
265 case TSK_CALLLOG:
266 attribute1 = bba1.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
267
268 break;
269 }
270 } catch (TskCoreException ex) {
271 logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", bba1.getArtifactID()), ex);
272 }
273 }
274 }
275
276 if (bba1 != null) {
277 BlackboardArtifact.ARTIFACT_TYPE fromID = BlackboardArtifact.ARTIFACT_TYPE.fromID(bba2.getArtifactTypeID());
278 if (fromID != null) {
279 try {
280 switch (fromID) {
281 case TSK_EMAIL_MSG:
282 attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_SENT));
283 break;
284 case TSK_MESSAGE:
285 attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME));
286 break;
287 case TSK_CALLLOG:
288 attribute2 = bba2.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START));
289 break;
290 }
291 } catch (TskCoreException ex) {
292 logger.log(Level.WARNING, String.format("Unable to compare attributes for artifact %d", bba2.getArtifactID()), ex);
293 }
294 }
295 }
296
297 if (attribute1 != null) {
298 dateTime1 = attribute1.getValueLong();
299 }
300
301 if (attribute2 != null) {
302 dateTime2 = attribute2.getValueLong();
303 }
304
305 return Long.compare(dateTime1, dateTime2) * -1;
306 }
307 }
308}

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.