19 package org.sleuthkit.autopsy.datamodel;
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.sql.ResultSet;
24 import java.sql.SQLException;
25 import java.util.ArrayList;
26 import java.util.EnumSet;
27 import java.util.HashMap;
28 import java.util.LinkedHashMap;
29 import java.util.List;
31 import java.util.Observable;
32 import java.util.Observer;
34 import java.util.logging.Level;
35 import org.openide.nodes.ChildFactory;
36 import org.openide.nodes.Children;
37 import org.openide.nodes.Node;
38 import org.openide.nodes.Sheet;
39 import org.openide.util.NbBundle;
40 import org.openide.util.WeakListeners;
41 import org.openide.util.lookup.Lookups;
48 import static org.
sleuthkit.datamodel.BlackboardArtifact.Type.TSK_EMAIL_MSG;
51 import org.
sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
64 private static final String
LABEL_NAME = BlackboardArtifact.Type.TSK_EMAIL_MSG.getTypeName();
81 public static final Map<String, String>
parsePath(String path) {
82 Map<String, String> parsed =
new HashMap<>();
83 String[] split = path == null ?
new String[0] : path.split(MAIL_PATH_SEPARATOR);
84 if (split.length < 4) {
85 parsed.put(MAIL_ACCOUNT, NbBundle.getMessage(
EmailExtracted.class,
"EmailExtracted.defaultAcct.text"));
86 parsed.put(MAIL_FOLDER, NbBundle.getMessage(
EmailExtracted.class,
"EmailExtracted.defaultFolder.text"));
89 parsed.put(MAIL_ACCOUNT, split[2]);
90 parsed.put(MAIL_FOLDER, split[3]);
115 this.filteringDSObjId = objId;
121 return visitor.
visit(
this);
127 private final Map<String, Map<String, List<Long>>>
accounts =
new LinkedHashMap<>();
135 return accounts.keySet();
141 return accounts.get(account).keySet();
147 return accounts.get(account).get(folder);
151 @SuppressWarnings(
"deprecation")
154 if (skCase == null) {
162 int emailArtifactId = BlackboardArtifact.Type.TSK_EMAIL_MSG.getTypeID();
163 int pathAttrId = BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID();
165 String query =
"SELECT \n"
166 +
" art.artifact_obj_id AS artifact_obj_id,\n"
167 +
" (SELECT value_text FROM blackboard_attributes attr\n"
168 +
" WHERE attr.artifact_id = art.artifact_id AND attr.attribute_type_id = " + pathAttrId +
"\n"
169 +
" LIMIT 1) AS value_text\n"
171 +
" blackboard_artifacts art\n"
172 +
" WHERE art.artifact_type_id = " + emailArtifactId +
"\n"
173 + ((filteringDSObjId > 0) ?
" AND art.data_source_obj_id = " + filteringDSObjId :
"");
176 Map<String, Map<String, List<Long>>> newMapping =
new HashMap<>();
178 try (CaseDbQuery dbQuery = skCase.executeQuery(query)) {
179 ResultSet resultSet = dbQuery.getResultSet();
180 while (resultSet.next()) {
181 Long artifactObjId = resultSet.getLong(
"artifact_obj_id");
182 Map<String, String> accountFolderMap =
parsePath(resultSet.getString(
"value_text"));
183 String account = accountFolderMap.get(MAIL_ACCOUNT);
184 String folder = accountFolderMap.get(MAIL_FOLDER);
186 Map<String, List<Long>> folders = newMapping.computeIfAbsent(account, (str) ->
new LinkedHashMap<>());
187 List<Long> messages = folders.computeIfAbsent(folder, (str) ->
new ArrayList<>());
188 messages.add(artifactObjId);
190 }
catch (TskCoreException | SQLException ex) {
191 logger.log(Level.WARNING,
"Cannot initialize email extraction: ", ex);
196 accounts.putAll(newMapping);
212 Lookups.singleton(TSK_EMAIL_MSG.getDisplayName()),
213 TSK_EMAIL_MSG.getDisplayName(),
217 super.setName(LABEL_NAME);
218 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/mail-icon-16.png");
229 return visitor.
visit(
this);
234 Sheet sheet = super.createSheet();
235 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
236 if (sheetSet == null) {
237 sheetSet = Sheet.createPropertiesSet();
241 sheetSet.put(
new NodeProperty<>(NbBundle.getMessage(
this.getClass(),
"EmailExtracted.createSheet.name.name"),
242 NbBundle.getMessage(
this.getClass(),
"EmailExtracted.createSheet.name.displayName"),
243 NbBundle.getMessage(
this.getClass(),
"EmailExtracted.createSheet.name.desc"),
251 return getClass().getName();
258 private class AccountFactory extends ChildFactory.Detachable<String> implements Observer {
264 private final PropertyChangeListener
pcl =
new PropertyChangeListener() {
266 public void propertyChange(PropertyChangeEvent evt) {
267 String eventType = evt.getPropertyName();
284 if (null != eventData && eventData.
getBlackboardArtifactType().getTypeID() == BlackboardArtifact.Type.TSK_EMAIL_MSG.getTypeID()) {
310 if (evt.getNewValue() == null) {
318 private final PropertyChangeListener
weakPcl = WeakListeners.propertyChange(pcl, null);
326 emailResults.addObserver(
this);
335 emailResults.deleteObserver(
this);
350 public void update(Observable o, Object arg) {
363 super(Children.create(
new FolderFactory(accountName),
true), Lookups.singleton(accountName));
364 super.setName(accountName);
366 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/account-icon-16.png");
368 emailResults.addObserver(
this);
372 super.setDisplayName(accountName +
" (" + emailResults.
getFolders(accountName) +
")");
377 Sheet sheet = super.createSheet();
378 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
379 if (sheetSet == null) {
380 sheetSet = Sheet.createPropertiesSet();
384 sheetSet.put(
new NodeProperty<>(NbBundle.getMessage(
this.getClass(),
"EmailExtracted.createSheet.name.name"),
385 NbBundle.getMessage(
this.getClass(),
"EmailExtracted.createSheet.name.displayName"),
386 NbBundle.getMessage(
this.getClass(),
"EmailExtracted.createSheet.name.desc"),
399 return visitor.
visit(
this);
403 public void update(Observable o, Object arg) {
409 return getClass().getName();
416 private class FolderFactory extends ChildFactory<String> implements Observer {
423 emailResults.addObserver(
this);
428 list.addAll(emailResults.
getFolders(accountName));
434 return new FolderNode(accountName, folderName);
438 public void update(Observable o, Object arg) {
456 private static String
getFolderKey(String accountName, String folderName) {
457 return accountName +
"_" + folderName;
469 super(Children.create(
new MessageFactory(accountName, folderName),
true), Lookups.singleton(accountName));
471 this.setIconBaseWithExtension(
"org/sleuthkit/autopsy/images/folder-icon-16.png");
475 emailResults.addObserver(
this);
479 super.setDisplayName(folderName +
" (" + emailResults.
getArtifactIds(accountName, folderName).size() +
")");
490 Sheet sheet = super.createSheet();
491 Sheet.Set sheetSet = sheet.get(Sheet.PROPERTIES);
492 if (sheetSet == null) {
493 sheetSet = Sheet.createPropertiesSet();
497 sheetSet.put(
new NodeProperty<>(NbBundle.getMessage(
this.getClass(),
"EmailExtracted.createSheet.name.name"),
498 NbBundle.getMessage(
this.getClass(),
"EmailExtracted.createSheet.name.displayName"),
499 NbBundle.getMessage(
this.getClass(),
"EmailExtracted.createSheet.name.desc"),
507 return visitor.
visit(
this);
511 public void update(Observable o, Object arg) {
517 return getClass().getName();
533 emailResults.addObserver(
this);
542 public void update(Observable o, Object arg) {
548 List<DataArtifact> keys =
new ArrayList<>();
550 if (skCase != null) {
551 emailResults.
getArtifactIds(accountName, folderName).forEach((
id) -> {
553 DataArtifact art = skCase.getBlackboard().getDataArtifactById(
id);
558 }
catch (TskCoreException ex) {
559 logger.log(Level.WARNING,
"Error getting mail messages keys", ex);
BlackboardArtifact.Type getBlackboardArtifactType()
void removeIngestModuleEventListener(final PropertyChangeListener listener)
final long filteringDSObjId
static synchronized IngestManager getInstance()
void removeIngestJobEventListener(final PropertyChangeListener listener)
void addIngestJobEventListener(final PropertyChangeListener listener)
T visit(DataSourceFilesNode in)
void addIngestModuleEventListener(final PropertyChangeListener listener)
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)