Autopsy  4.15.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
HashDbManager.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2018 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  */
19 package org.sleuthkit.autopsy.modules.hashdatabase;
20 
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.beans.PropertyChangeSupport;
24 import java.io.File;
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Objects;
30 import java.util.Set;
31 import java.util.concurrent.ExecutionException;
32 import java.util.logging.Level;
33 import java.util.stream.Stream;
34 import javax.swing.JFileChooser;
35 import javax.swing.JOptionPane;
36 import javax.swing.SwingWorker;
37 import javax.swing.filechooser.FileNameExtensionFilter;
38 import org.apache.commons.io.FilenameUtils;
39 import org.netbeans.api.progress.ProgressHandle;
40 import org.openide.util.NbBundle;
41 import org.openide.util.NbBundle.Messages;
42 import org.openide.windows.WindowManager;
53 import org.sleuthkit.datamodel.AbstractFile;
54 import org.sleuthkit.datamodel.Content;
55 import org.sleuthkit.datamodel.HashEntry;
56 import org.sleuthkit.datamodel.HashHitInfo;
57 import org.sleuthkit.datamodel.SleuthkitJNI;
58 import org.sleuthkit.datamodel.TskCoreException;
59 import org.sleuthkit.datamodel.TskData;
62 
67 public class HashDbManager implements PropertyChangeListener {
68 
69  private static final String HASH_DATABASE_FILE_EXTENSON = "kdb"; //NON-NLS
70  private static HashDbManager instance = null;
71  private List<HashDb> hashSets = new ArrayList<>();
72  private Set<String> hashSetNames = new HashSet<>();
73  private Set<String> hashSetPaths = new HashSet<>();
74  PropertyChangeSupport changeSupport = new PropertyChangeSupport(HashDbManager.class);
75  private static final Logger logger = Logger.getLogger(HashDbManager.class.getName());
76  private boolean allDatabasesLoadedCorrectly = false;
77 
83  public enum SetEvt {
84 
85  DB_ADDED, DB_DELETED, DB_INDEXED
86  };
87 
93  public static synchronized HashDbManager getInstance() {
94  if (instance == null) {
95  instance = new HashDbManager();
96  }
97  return instance;
98  }
99 
100  public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
101  changeSupport.addPropertyChangeListener(listener);
102  }
103 
104  public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
105  changeSupport.removePropertyChangeListener(listener);
106  }
107 
108  synchronized boolean verifyAllDatabasesLoadedCorrectly() {
110  }
111 
112  private HashDbManager() {
114  }
115 
121  static String getHashDatabaseFileExtension() {
123  }
124 
125  public class HashDbManagerException extends Exception {
126 
127  private static final long serialVersionUID = 1L;
128 
129  private HashDbManagerException(String message) {
130  super(message);
131  }
132 
133  private HashDbManagerException(String message, Throwable exception) {
134  super(message, exception);
135  }
136  }
137 
157  public synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
158  HashDb hashDb = null;
159  hashDb = this.addExistingHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
160  this.save();
161  return hashDb;
162  }
163 
164  synchronized HashDb addExistingHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
165  HashDb hashDb = null;
166  try {
167  if (!new File(path).exists()) {
168  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbDoesNotExistExceptionMsg", path));
169  }
170 
171  if (hashSetPaths.contains(path)) {
172  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbAlreadyAddedExceptionMsg", path));
173  }
174 
175  if (hashSetNames.contains(hashSetName)) {
176  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName));
177  }
178 
179  hashDb = addHashDatabase(SleuthkitJNI.openHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
180  } catch (TskCoreException ex) {
181  throw new HashDbManagerException(ex.getMessage());
182  }
183  return hashDb;
184  }
185 
204  public synchronized HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages,
205  HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
206 
207  HashDb hashDb = null;
208  hashDb = this.addNewHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
209 
210  this.save();
211 
212  return hashDb;
213  }
214 
215  public synchronized HashDb addNewHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages,
216  HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
217  HashDb hashDb = null;
218  try {
219  File file = new File(path);
220  if (file.exists()) {
221  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbFileExistsExceptionMsg", path));
222  }
223  if (!FilenameUtils.getExtension(file.getName()).equalsIgnoreCase(HASH_DATABASE_FILE_EXTENSON)) {
224  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.illegalHashDbFileNameExtensionMsg",
225  getHashDatabaseFileExtension()));
226  }
227 
228  if (hashSetPaths.contains(path)) {
229  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbAlreadyAddedExceptionMsg", path));
230  }
231 
232  if (hashSetNames.contains(hashSetName)) {
233  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName));
234  }
235 
236  hashDb = addHashDatabase(SleuthkitJNI.createHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
237  } catch (TskCoreException ex) {
238  throw new HashDbManagerException(ex.getMessage());
239  }
240  return hashDb;
241  }
242 
243  private SleuthkitHashSet addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws TskCoreException {
244  // Wrap an object around the handle.
245  SleuthkitHashSet hashDb = new SleuthkitHashSet(handle, hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
246 
247  // Get the indentity data before updating the collections since the
248  // accessor methods may throw.
249  String databasePath = hashDb.getDatabasePath();
250  String indexPath = hashDb.getIndexPath();
251 
252  // Update the collections used to ensure that hash set names are unique
253  // and the same database is not added to the configuration more than once.
254  hashSetNames.add(hashDb.getHashSetName());
255  if (!databasePath.equals("None")) { //NON-NLS
256  hashSetPaths.add(databasePath);
257  }
258  if (!indexPath.equals("None")) { //NON-NLS
259  hashSetPaths.add(indexPath);
260  }
261 
262  // Add the hash database to the collection
263  hashSets.add(hashDb);
264 
265  // Let any external listeners know that there's a new set
266  try {
267  changeSupport.firePropertyChange(SetEvt.DB_ADDED.toString(), null, hashSetName);
268  } catch (Exception e) {
269  logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
271  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
272  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
274  }
275  return hashDb;
276  }
277 
278  CentralRepoHashSet addExistingCentralRepoHashSet(String hashSetName, String version, int referenceSetID,
279  boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType,
280  boolean readOnly) throws TskCoreException {
281 
282  if (!CentralRepository.isEnabled()) {
283  throw new TskCoreException("Could not load central repository hash set " + hashSetName + " - central repository is not enabled");
284  }
285 
286  CentralRepoHashSet db = new CentralRepoHashSet(hashSetName, version, referenceSetID, searchDuringIngest,
287  sendIngestMessages, knownFilesType, readOnly);
288 
289  if (!db.isValid()) {
290  throw new TskCoreException("Error finding hash set " + hashSetName + " in central repository");
291  }
292 
293  // Add the hash database to the collection
294  hashSets.add(db);
295 
296  // Let any external listeners know that there's a new set
297  try {
298  changeSupport.firePropertyChange(SetEvt.DB_ADDED.toString(), null, hashSetName);
299  } catch (Exception e) {
300  logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
301  MessageNotifyUtil.Notify.show(
302  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
303  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
304  MessageNotifyUtil.MessageType.ERROR);
305  }
306  return db;
307 
308  }
309 
310  synchronized void indexHashDatabase(SleuthkitHashSet hashDb) {
311  hashDb.addPropertyChangeListener(this);
312  HashDbIndexer creator = new HashDbIndexer(hashDb);
313  creator.execute();
314  }
315 
316  @Override
317  public void propertyChange(PropertyChangeEvent event) {
318  if (event.getPropertyName().equals(SleuthkitHashSet.Event.INDEXING_DONE.name())) {
319  SleuthkitHashSet hashDb = (SleuthkitHashSet) event.getNewValue();
320  if (null != hashDb) {
321  try {
322  String indexPath = hashDb.getIndexPath();
323  if (!indexPath.equals("None")) { //NON-NLS
324  hashSetPaths.add(indexPath);
325  }
326  } catch (TskCoreException ex) {
327  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting index path of " + hashDb.getHashSetName() + " hash set after indexing", ex); //NON-NLS
328  }
329  }
330  }
331  }
332 
341  public synchronized void removeHashDatabase(HashDb hashDb) throws HashDbManagerException {
342  this.removeHashDatabaseNoSave(hashDb);
343  this.save();
344  }
345 
346  public synchronized void removeHashDatabaseNoSave(HashDb hashDb) throws HashDbManagerException {
347  // Don't remove a database if ingest is running
348  boolean ingestIsRunning = IngestManager.getInstance().isIngestRunning();
349  if (ingestIsRunning) {
350  throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.ingestRunningExceptionMsg"));
351  }
352  // Remove the database from whichever hash set list it occupies,
353  // and remove its hash set name from the hash set used to ensure unique
354  // hash set names are used, before undertaking These operations will succeed and constitute
355  // a mostly effective removal, even if the subsequent operations fail.
356  String hashSetName = hashDb.getHashSetName();
357  hashSetNames.remove(hashSetName);
358  hashSets.remove(hashDb);
359 
360  // Now undertake the operations that could throw.
361  // Indexing is only relevanet for sleuthkit hashsets
362  if (hashDb instanceof SleuthkitHashSet) {
363  SleuthkitHashSet hashDatabase = (SleuthkitHashSet) hashDb;
364  try {
365  if (hashDatabase.hasIndex()) {
366  hashSetPaths.remove(hashDatabase.getIndexPath());
367  }
368  } catch (TskCoreException ex) {
369  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting index path of " + hashDatabase.getHashSetName() + " hash set when removing the hash set", ex); //NON-NLS
370  }
371 
372  try {
373  if (!hashDatabase.hasIndexOnly()) {
374  hashSetPaths.remove(hashDatabase.getDatabasePath());
375  }
376  } catch (TskCoreException ex) {
377  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting hash set path of " + hashDatabase.getHashSetName() + " hash set when removing the hash set", ex); //NON-NLS
378  }
379 
380  try {
381  hashDatabase.close();
382  } catch (TskCoreException ex) {
383  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + hashDb.getHashSetName() + " hash set when removing the hash set", ex); //NON-NLS
384  }
385  }
386 
387  // Let any external listeners know that a set has been deleted
388  try {
389  changeSupport.firePropertyChange(SetEvt.DB_DELETED.toString(), null, hashSetName);
390  } catch (Exception e) {
391  logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
393  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
394  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
396  }
397  }
398 
399  void save() throws HashDbManagerException {
400  try {
401  if (!HashLookupSettings.writeSettings(new HashLookupSettings(HashLookupSettings.convertHashSetList(this.hashSets)))) {
402  throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg"));
403  }
404  } catch (HashLookupSettings.HashLookupSettingsException ex) {
405  throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg"));
406  }
407  }
408 
416  public synchronized List<HashDb> getAllHashSets() {
417  try {
419  } catch (TskCoreException ex) {
420  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
421  }
422 
423  List<HashDb> hashDbs = new ArrayList<>();
424  hashDbs.addAll(this.hashSets);
425  return hashDbs;
426  }
427 
433  public synchronized List<HashDb> getKnownFileHashSets() {
434  List<HashDb> hashDbs = new ArrayList<>();
435  try {
437  } catch (TskCoreException ex) {
438  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
439  }
440  this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN)).forEach((db) -> {
441  hashDbs.add(db);
442  });
443  return hashDbs;
444  }
445 
451  public synchronized List<HashDb> getKnownBadFileHashSets() {
452  List<HashDb> hashDbs = new ArrayList<>();
453  try {
455  } catch (TskCoreException ex) {
456  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
457  }
458  this.hashSets.stream().filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN_BAD)).forEach((db) -> {
459  hashDbs.add(db);
460  });
461  return hashDbs;
462  }
463 
469  public synchronized List<HashDb> getUpdateableHashSets() {
470  return getUpdateableHashSets(this.hashSets);
471  }
472 
473  private List<HashDb> getUpdateableHashSets(List<HashDb> hashDbs) {
474  ArrayList<HashDb> updateableDbs = new ArrayList<>();
475  try {
477  } catch (TskCoreException ex) {
478  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
479  }
480  for (HashDb db : hashDbs) {
481  try {
482  if (db.isUpdateable()) {
483  updateableDbs.add(db);
484  }
485  } catch (TskCoreException ex) {
486  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error checking updateable status of " + db.getHashSetName() + " hash set", ex); //NON-NLS
487  }
488  }
489  return updateableDbs;
490  }
491 
492  private List<HashDbInfo> getCentralRepoHashSetsFromDatabase() {
493  List<HashDbInfo> crHashSets = new ArrayList<>();
495  try {
497  for (CentralRepoFileSet globalSet : crSets) {
498 
499  // Defaults for fields not stored in the central repository:
500  // searchDuringIngest: false
501  // sendIngestMessages: true if the hash set is notable
502  boolean sendIngestMessages = KnownFilesType.fromFileKnown(globalSet.getFileKnownStatus()).equals(HashDb.KnownFilesType.KNOWN_BAD);
503  crHashSets.add(new HashDbInfo(globalSet.getSetName(), globalSet.getVersion(),
504  globalSet.getGlobalSetID(), KnownFilesType.fromFileKnown(globalSet.getFileKnownStatus()), globalSet.isReadOnly(), false, sendIngestMessages));
505  }
506  } catch (CentralRepoException ex) {
507  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
508  }
509  }
510  return crHashSets;
511  }
512 
517  public synchronized void loadLastSavedConfiguration() {
518  closeHashDatabases(this.hashSets);
519  hashSetNames.clear();
520  hashSetPaths.clear();
521 
523  }
524 
525  private void closeHashDatabases(List<HashDb> hashDatabases) {
526  for (HashDb database : hashDatabases) {
527  if (database instanceof SleuthkitHashSet) {
528  try {
529  ((SleuthkitHashSet) database).close();
530  } catch (TskCoreException ex) {
531  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + database.getHashSetName() + " hash set", ex); //NON-NLS
532  }
533  }
534  }
535  hashDatabases.clear();
536  }
537 
538  private void loadHashsetsConfiguration() {
539  try {
540  HashLookupSettings settings = HashLookupSettings.readSettings();
541  this.configureSettings(settings);
542  } catch (HashLookupSettings.HashLookupSettingsException ex) {
543  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Could not read Hash lookup settings from disk.", ex);
544  }
545  }
546 
553  @Messages({"# {0} - hash set name", "HashDbManager.noDbPath.message=Couldn't get valid hash set path for: {0}",
554  "HashDbManager.centralRepoLoadError.message=Error loading central repository hash sets"})
555  private void configureSettings(HashLookupSettings settings) {
556  allDatabasesLoadedCorrectly = true;
557  List<HashDbInfo> hashDbInfoList = settings.getHashDbInfo();
558  for (HashDbInfo hashDbInfo : hashDbInfoList) {
559  try {
560  if (hashDbInfo.isFileDatabaseType()) {
561  String dbPath = this.getValidFilePath(hashDbInfo.getHashSetName(), hashDbInfo.getPath());
562  if (dbPath != null) {
563  addHashDatabase(SleuthkitJNI.openHashDatabase(dbPath), hashDbInfo.getHashSetName(), hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), hashDbInfo.getKnownFilesType());
564  } else {
565  logger.log(Level.WARNING, Bundle.HashDbManager_noDbPath_message(hashDbInfo.getHashSetName()));
566  allDatabasesLoadedCorrectly = false;
567  }
568  } else {
570  addExistingCentralRepoHashSet(hashDbInfo.getHashSetName(), hashDbInfo.getVersion(),
571  hashDbInfo.getReferenceSetID(),
572  hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(),
573  hashDbInfo.getKnownFilesType(), hashDbInfo.isReadOnly());
574  }
575  }
576  } catch (TskCoreException ex) {
577  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error opening hash set", ex); //NON-NLS
578  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
579  NbBundle.getMessage(this.getClass(),
580  "HashDbManager.unableToOpenHashDbMsg", hashDbInfo.getHashSetName()),
581  NbBundle.getMessage(this.getClass(), "HashDbManager.openHashDbErr"),
582  JOptionPane.ERROR_MESSAGE);
583  allDatabasesLoadedCorrectly = false;
584  }
585  }
586 
588  try {
590  } catch (TskCoreException ex) {
591  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error opening hash set", ex); //NON-NLS
592 
593  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
594  Bundle.HashDbManager_centralRepoLoadError_message(),
595  NbBundle.getMessage(this.getClass(), "HashDbManager.openHashDbErr"),
596  JOptionPane.ERROR_MESSAGE);
597  allDatabasesLoadedCorrectly = false;
598  }
599  }
600 
601  /*
602  * NOTE: When RuntimeProperties.coreComponentsAreActive() is "false", I
603  * don't think we should overwrite hash db settings file because we were
604  * unable to load a database. The user should have to fix the issue or
605  * remove the database from settings. Overwiting the settings
606  * effectively removes the database from HashLookupSettings and the user
607  * may not know about this because the dialogs are not being displayed.
608  * The next time user starts Autopsy, HashDB will load without errors
609  * and the user may think that the problem was solved.
610  */
611  if (!allDatabasesLoadedCorrectly && RuntimeProperties.runningWithGUI()) {
612  try {
613  HashLookupSettings.writeSettings(new HashLookupSettings(HashLookupSettings.convertHashSetList(this.hashSets)));
614  allDatabasesLoadedCorrectly = true;
615  } catch (HashLookupSettings.HashLookupSettingsException ex) {
616  allDatabasesLoadedCorrectly = false;
617  logger.log(Level.SEVERE, "Could not overwrite hash set settings.", ex);
618  }
619  }
620  }
621 
622  private void updateHashSetsFromCentralRepository() throws TskCoreException {
624  List<HashDbInfo> crHashDbInfoList = getCentralRepoHashSetsFromDatabase();
625  for (HashDbInfo hashDbInfo : crHashDbInfoList) {
626  if (hashDbInfoIsNew(hashDbInfo)) {
627  addExistingCentralRepoHashSet(hashDbInfo.getHashSetName(), hashDbInfo.getVersion(),
628  hashDbInfo.getReferenceSetID(),
629  hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), hashDbInfo.getKnownFilesType(),
630  hashDbInfo.isReadOnly());
631  }
632  }
633  }
634  }
635 
636  private boolean hashDbInfoIsNew(HashDbInfo dbInfo) {
637  for (HashDb db : this.hashSets) {
638  if (dbInfo.matches(db)) {
639  return false;
640  }
641  }
642  return true;
643  }
644 
645  private String getValidFilePath(String hashSetName, String configuredPath) {
646  // Check the configured path.
647  File database = new File(configuredPath);
648  if (database.exists()) {
649  return configuredPath;
650  }
651 
652  // Give the user an opportunity to find the desired file.
653  String newPath = null;
655  && JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(),
656  NbBundle.getMessage(this.getClass(), "HashDbManager.dlgMsg.dbNotFoundAtLoc",
657  hashSetName, configuredPath),
658  NbBundle.getMessage(this.getClass(), "HashDbManager.dlgTitle.MissingDb"),
659  JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
660  newPath = searchForFile();
661  if (null != newPath && !newPath.isEmpty()) {
662  database = new File(newPath);
663  if (!database.exists()) {
664  newPath = null;
665  }
666  }
667  }
668  return newPath;
669  }
670 
671  private String searchForFile() {
672  String filePath = null;
673  JFileChooser fc = new JFileChooser();
674  fc.setDragEnabled(false);
675  fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
676  String[] EXTENSION = new String[]{"txt", "idx", "hash", "Hash", "kdb"}; //NON-NLS
677  FileNameExtensionFilter filter = new FileNameExtensionFilter(
678  NbBundle.getMessage(this.getClass(), "HashDbManager.fileNameExtensionFilter.title"), EXTENSION);
679  fc.setFileFilter(filter);
680  fc.setMultiSelectionEnabled(false);
681  if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
682  File f = fc.getSelectedFile();
683  try {
684  filePath = f.getCanonicalPath();
685  } catch (IOException ex) {
686  Logger.getLogger(HashDbManager.class.getName()).log(Level.WARNING, "Couldn't get selected file path", ex); //NON-NLS
687  }
688  }
689  return filePath;
690  }
691 
692  public static abstract class HashDb {
693 
698  @Messages({
699  "HashDbManager.noChange.text=No Change",
700  "HashDbManager.known.text=Known",
701  "HashDbManager.knownBad.text=Notable"
702  })
703  public enum KnownFilesType {
704 
705  KNOWN(Bundle.HashDbManager_known_text(), TskData.FileKnown.KNOWN, false, false),
706  KNOWN_BAD(Bundle.HashDbManager_knownBad_text(), TskData.FileKnown.BAD, true, true),
707  NO_CHANGE(Bundle.HashDbManager_noChange_text(), TskData.FileKnown.UNKNOWN, true, false);
708 
709  private final String displayName;
710  private final TskData.FileKnown fileKnown;
711  private final boolean allowSendInboxMessages;
712  private final boolean defaultSendInboxMessages;
713 
714  KnownFilesType(String displayName, TskData.FileKnown fileKnown, boolean allowSendInboxMessages, boolean defaultSendInboxMessages) {
715  this.displayName = displayName;
716  this.fileKnown = fileKnown;
717  this.allowSendInboxMessages = allowSendInboxMessages;
718  this.defaultSendInboxMessages = defaultSendInboxMessages;
719  }
720 
729  return allowSendInboxMessages;
730  }
731 
740  return defaultSendInboxMessages;
741  }
742 
743  public String getDisplayName() {
744  return this.displayName;
745  }
746 
753  TskData.FileKnown getFileKnown() {
754  return this.fileKnown;
755  }
756 
764  static KnownFilesType fromFileKnown(TskData.FileKnown fileKnown) {
765  if (fileKnown == null) {
766  return null;
767  }
768 
769  return Stream.of(KnownFilesType.values())
770  .filter((type) -> type.getFileKnown() == fileKnown)
771  .findFirst()
772  .orElseThrow(() -> new IllegalArgumentException("Unknown TskData.FileKnown type: " + fileKnown));
773  }
774  }
775 
779  public enum Event {
780 
781  INDEXING_DONE
782  }
783 
784  public abstract String getHashSetName();
785 
786  abstract String getDisplayName();
787 
788  public abstract String getDatabasePath() throws TskCoreException;
789 
790  public abstract HashDb.KnownFilesType getKnownFilesType();
791 
792  public abstract boolean getSearchDuringIngest();
793 
794  abstract void setSearchDuringIngest(boolean useForIngest);
795 
796  public abstract boolean getSendIngestMessages();
797 
798  abstract void setSendIngestMessages(boolean showInboxMessages);
799 
807  public abstract boolean isUpdateable() throws TskCoreException;
808 
817  public abstract void addHashes(Content content) throws TskCoreException;
818 
819  public abstract void addHashes(Content content, String comment) throws TskCoreException;
820 
821  public abstract void addHashes(List<HashEntry> hashes) throws TskCoreException;
822 
823  public abstract boolean lookupMD5Quick(Content content) throws TskCoreException;
824 
825  public abstract HashHitInfo lookupMD5(Content content) throws TskCoreException;
826 
835  abstract boolean isValid() throws TskCoreException;
836 
837  public abstract String getIndexPath() throws TskCoreException;
838 
839  public abstract boolean hasIndexOnly() throws TskCoreException;
840 
841  public abstract void firePropertyChange(String propertyName, Object oldValue, Object newValue);
842 
843  public abstract void addPropertyChangeListener(PropertyChangeListener pcl);
844 
845  public abstract void removePropertyChangeListener(PropertyChangeListener pcl);
846 
847  @Override
848  public abstract String toString();
849 
850  }
851 
856  class SleuthkitHashSet extends HashDb {
857 
858  private static final long serialVersionUID = 1L;
859  private final int handle;
860  private final String hashSetName;
861  private boolean searchDuringIngest;
862  private boolean sendIngestMessages;
863  private final HashDb.KnownFilesType knownFilesType;
864  private boolean indexing;
865  private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
866 
867  private SleuthkitHashSet(int handle, String hashSetName, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType) {
868  this.handle = handle;
869  this.hashSetName = hashSetName;
870  this.searchDuringIngest = useForIngest;
871  this.sendIngestMessages = sendHitMessages;
872  this.knownFilesType = knownFilesType;
873  this.indexing = false;
874  }
875 
882  @Override
883  public void addPropertyChangeListener(PropertyChangeListener pcl) {
884  propertyChangeSupport.addPropertyChangeListener(pcl);
885  }
886 
892  @Override
893  public void removePropertyChangeListener(PropertyChangeListener pcl) {
894  propertyChangeSupport.removePropertyChangeListener(pcl);
895  }
896 
897  int getHandle() {
898  return handle;
899  }
900 
901  @Override
902  public String getHashSetName() {
903  return hashSetName;
904  }
905 
906  @Override
907  String getDisplayName() {
908  return getHashSetName();
909  }
910 
911  @Override
912  public String getDatabasePath() throws TskCoreException {
913  return SleuthkitJNI.getHashDatabasePath(handle);
914  }
915 
916  public void setIndexing(boolean indexing) {
917  this.indexing = indexing;
918  }
919 
920  @Override
921  public String getIndexPath() throws TskCoreException {
922  return SleuthkitJNI.getHashDatabaseIndexPath(handle);
923  }
924 
925  @Override
926  public KnownFilesType getKnownFilesType() {
927  return knownFilesType;
928  }
929 
930  @Override
931  public boolean getSearchDuringIngest() {
932  return searchDuringIngest;
933  }
934 
935  @Override
936  void setSearchDuringIngest(boolean useForIngest) {
937  this.searchDuringIngest = useForIngest;
938  }
939 
940  @Override
941  public boolean getSendIngestMessages() {
942  return sendIngestMessages;
943  }
944 
945  @Override
946  void setSendIngestMessages(boolean showInboxMessages) {
947  this.sendIngestMessages = showInboxMessages;
948  }
949 
957  @Override
958  public boolean isUpdateable() throws TskCoreException {
959  return SleuthkitJNI.isUpdateableHashDatabase(this.handle);
960  }
961 
970  @Override
971  public void addHashes(Content content) throws TskCoreException {
972  addHashes(content, null);
973  }
974 
985  @Override
986  public void addHashes(Content content, String comment) throws TskCoreException {
987  // This only works for AbstractFiles and MD5 hashes at present.
988  assert content instanceof AbstractFile;
989  if (content instanceof AbstractFile) {
990  AbstractFile file = (AbstractFile) content;
991  if (null != file.getMd5Hash()) {
992  SleuthkitJNI.addToHashDatabase(null, file.getMd5Hash(), null, null, comment, handle);
993  }
994  }
995  }
996 
1004  @Override
1005  public void addHashes(List<HashEntry> hashes) throws TskCoreException {
1006  SleuthkitJNI.addToHashDatabase(hashes, handle);
1007  }
1008 
1018  @Override
1019  public boolean lookupMD5Quick(Content content) throws TskCoreException {
1020  boolean result = false;
1021  assert content instanceof AbstractFile;
1022  if (content instanceof AbstractFile) {
1023  AbstractFile file = (AbstractFile) content;
1024  if (null != file.getMd5Hash()) {
1025  result = SleuthkitJNI.lookupInHashDatabase(file.getMd5Hash(), handle);
1026  }
1027  }
1028  return result;
1029  }
1030 
1040  @Override
1041  public HashHitInfo lookupMD5(Content content) throws TskCoreException {
1042  HashHitInfo result = null;
1043  // This only works for AbstractFiles and MD5 hashes at present.
1044  assert content instanceof AbstractFile;
1045  if (content instanceof AbstractFile) {
1046  AbstractFile file = (AbstractFile) content;
1047  if (null != file.getMd5Hash()) {
1048  result = SleuthkitJNI.lookupInHashDatabaseVerbose(file.getMd5Hash(), handle);
1049  }
1050  }
1051  return result;
1052  }
1053 
1062  @Override
1063  boolean isValid() throws TskCoreException {
1064  return hasIndex();
1065  }
1066 
1067  boolean hasIndex() throws TskCoreException {
1068  return SleuthkitJNI.hashDatabaseHasLookupIndex(handle);
1069  }
1070 
1071  @Override
1072  public boolean hasIndexOnly() throws TskCoreException {
1073  return SleuthkitJNI.hashDatabaseIsIndexOnly(handle);
1074  }
1075 
1076  boolean canBeReIndexed() throws TskCoreException {
1077  return SleuthkitJNI.hashDatabaseCanBeReindexed(handle);
1078  }
1079 
1080  boolean isIndexing() {
1081  return indexing;
1082  }
1083 
1084  @Override
1085  public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
1086  this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
1087  }
1088 
1089  private void close() throws TskCoreException {
1090  SleuthkitJNI.closeHashDatabase(handle);
1091  }
1092 
1093  @Override
1094  public String toString() {
1095  return getHashSetName();
1096  }
1097 
1098  @Override
1099  public int hashCode() {
1100  int code = 23;
1101  code = 47 * code + Integer.hashCode(handle);
1102  code = 47 * code + Objects.hashCode(this.hashSetName);
1103  code = 47 * code + Objects.hashCode(this.propertyChangeSupport);
1104  code = 47 * code + Objects.hashCode(this.knownFilesType);
1105  return code;
1106  }
1107 
1108  @Override
1109  public boolean equals(Object obj) {
1110  if (obj == null) {
1111  return false;
1112  }
1113  if (getClass() != obj.getClass()) {
1114  return false;
1115  }
1116  final SleuthkitHashSet other = (SleuthkitHashSet) obj;
1117  if (!Objects.equals(this.hashSetName, other.hashSetName)) {
1118  return false;
1119  }
1120  if (this.knownFilesType != other.knownFilesType) {
1121  return false;
1122  }
1123  return true;
1124  }
1125  }
1126 
1131  class CentralRepoHashSet extends HashDb {
1132 
1133  private static final long serialVersionUID = 1L;
1134  private final String hashSetName;
1135  private boolean searchDuringIngest;
1136  private boolean sendIngestMessages;
1137  private final HashDb.KnownFilesType knownFilesType;
1138  private final int referenceSetID;
1139  private final String version;
1140  private String orgName;
1141  private final boolean readOnly;
1142  private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
1143 
1144  @Messages({"HashDbManager.CentralRepoHashDb.orgError=Error loading organization"})
1145  private CentralRepoHashSet(String hashSetName, String version, int referenceSetID,
1146  boolean useForIngest, boolean sendHitMessages, HashDb.KnownFilesType knownFilesType,
1147  boolean readOnly)
1148  throws TskCoreException {
1149  this.hashSetName = hashSetName;
1150  this.version = version;
1151  this.referenceSetID = referenceSetID;
1152  this.searchDuringIngest = useForIngest;
1153  this.sendIngestMessages = sendHitMessages;
1154  this.knownFilesType = knownFilesType;
1155  this.readOnly = readOnly;
1156 
1157  try {
1158  orgName = CentralRepository.getInstance().getReferenceSetOrganization(referenceSetID).getName();
1159  } catch (CentralRepoException ex) {
1160  Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error looking up central repository organization for reference set " + referenceSetID, ex); //NON-NLS
1161  orgName = Bundle.HashDbManager_CentralRepoHashDb_orgError();
1162  }
1163  }
1164 
1171  @Override
1172  public void addPropertyChangeListener(PropertyChangeListener pcl) {
1173  propertyChangeSupport.addPropertyChangeListener(pcl);
1174  }
1175 
1181  @Override
1182  public void removePropertyChangeListener(PropertyChangeListener pcl) {
1183  propertyChangeSupport.removePropertyChangeListener(pcl);
1184  }
1185 
1186  @Override
1187  public boolean hasIndexOnly() throws TskCoreException {
1188  return true;
1189  }
1190 
1191  @Override
1192  public String getHashSetName() {
1193  return hashSetName;
1194  }
1195 
1196  @Override
1197  public String getDisplayName() {
1198  if (!getVersion().isEmpty()) {
1199  return getHashSetName() + " " + getVersion() + " (remote)";
1200  } else {
1201  return getHashSetName() + " (remote)";
1202  }
1203  }
1204 
1205  String getVersion() {
1206  return version;
1207  }
1208 
1209  String getOrgName() {
1210  return orgName;
1211  }
1212 
1213  int getReferenceSetID() {
1214  return referenceSetID;
1215  }
1216 
1217  @Override
1218  public String getDatabasePath() throws TskCoreException {
1219  return "";
1220  }
1221 
1222  @Override
1223  public String getIndexPath() throws TskCoreException {
1224  return "";
1225  }
1226 
1227  @Override
1228  public HashDb.KnownFilesType getKnownFilesType() {
1229  return knownFilesType;
1230  }
1231 
1232  @Override
1233  public boolean getSearchDuringIngest() {
1234  return searchDuringIngest;
1235  }
1236 
1237  @Override
1238  void setSearchDuringIngest(boolean useForIngest) {
1239  this.searchDuringIngest = useForIngest;
1240  }
1241 
1242  @Override
1243  public boolean getSendIngestMessages() {
1244  return sendIngestMessages;
1245  }
1246 
1247  @Override
1248  void setSendIngestMessages(boolean showInboxMessages) {
1249  this.sendIngestMessages = showInboxMessages;
1250  }
1251 
1259  @Override
1260  public boolean isUpdateable() throws TskCoreException {
1261  return (!readOnly);
1262  }
1263 
1272  @Override
1273  public void addHashes(Content content) throws TskCoreException {
1274  addHashes(content, null);
1275  }
1276 
1287  @Override
1288  public void addHashes(Content content, String comment) throws TskCoreException {
1289  // This only works for AbstractFiles and MD5 hashes at present.
1290  assert content instanceof AbstractFile;
1291  if (content instanceof AbstractFile) {
1292  AbstractFile file = (AbstractFile) content;
1293  if (null != file.getMd5Hash()) {
1294  TskData.FileKnown type = knownFilesType.getFileKnown();
1295 
1296  try {
1297  CentralRepoFileInstance fileInstance = new CentralRepoFileInstance(referenceSetID, file.getMd5Hash(),
1298  type, comment);
1299  CentralRepository.getInstance().addReferenceInstance(fileInstance, CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID));
1300  } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
1301  throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex); //NON-NLS
1302  }
1303  }
1304  }
1305  }
1306 
1314  @Override
1315  public void addHashes(List<HashEntry> hashes) throws TskCoreException {
1316  Set<CentralRepoFileInstance> globalFileInstances = new HashSet<>();
1317  for (HashEntry hashEntry : hashes) {
1318  TskData.FileKnown type = knownFilesType.getFileKnown();
1319 
1320  try {
1321  globalFileInstances.add(new CentralRepoFileInstance(referenceSetID, hashEntry.getMd5Hash(), type, hashEntry.getComment()));
1322  } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
1323  throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex);
1324  }
1325  }
1326 
1327  try {
1328  CentralRepository.getInstance().bulkInsertReferenceTypeEntries(globalFileInstances,
1329  CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID));
1330  } catch (CentralRepoException ex) {
1331  throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex);
1332  }
1333  }
1334 
1344  @Override
1345  public boolean lookupMD5Quick(Content content) throws TskCoreException {
1346  // This only works for AbstractFiles and MD5 hashes
1347  assert content instanceof AbstractFile;
1348  if (content instanceof AbstractFile) {
1349  AbstractFile file = (AbstractFile) content;
1350  if (null != file.getMd5Hash()) {
1351  try {
1352  return CentralRepository.getInstance().isFileHashInReferenceSet(file.getMd5Hash(), this.referenceSetID);
1353  } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
1354  Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup for hash "
1355  + file.getMd5Hash() + " in reference set " + referenceSetID, ex); //NON-NLS
1356  throw new TskCoreException("Error performing central reposiotry hash lookup", ex);
1357  }
1358  }
1359  }
1360  return false;
1361  }
1362 
1372  @Override
1373  public HashHitInfo lookupMD5(Content content) throws TskCoreException {
1374  HashHitInfo result = null;
1375  // This only works for AbstractFiles and MD5 hashes
1376  assert content instanceof AbstractFile;
1377  if (content instanceof AbstractFile) {
1378  AbstractFile file = (AbstractFile) content;
1379  if (null != file.getMd5Hash()) {
1380  try {
1381  return CentralRepository.getInstance().lookupHash(file.getMd5Hash(), referenceSetID);
1382  } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
1383  Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup for hash "
1384  + file.getMd5Hash() + " in reference set " + referenceSetID, ex); //NON-NLS
1385  throw new TskCoreException("Error performing central reposiotry hash lookup", ex);
1386  }
1387  }
1388  }
1389  return result;
1390  }
1391 
1397  @Override
1398  boolean isValid() {
1399  if (!CentralRepository.isEnabled()) {
1400  return false;
1401  }
1402  try {
1403  return CentralRepository.getInstance().referenceSetIsValid(this.referenceSetID, this.hashSetName, this.version);
1404  } catch (CentralRepoException ex) {
1405  Logger.getLogger(CentralRepoHashSet.class.getName()).log(Level.SEVERE, "Error validating hash set " + hashSetName, ex); //NON-NLS
1406  return false;
1407  }
1408  }
1409 
1410  @Override
1411  public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
1412  this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
1413  }
1414 
1415  @Override
1416  public String toString() {
1417  return getDisplayName();
1418  }
1419 
1420  @Override
1421  public int hashCode() {
1422  int code = 23;
1423  code = 47 * code + Objects.hashCode(this.hashSetName);
1424  code = 47 * code + Objects.hashCode(this.version);
1425  code = 47 * code + Integer.hashCode(this.referenceSetID);
1426  code = 47 * code + Objects.hashCode(this.knownFilesType);
1427  return code;
1428  }
1429 
1430  @Override
1431  public boolean equals(Object obj) {
1432  if (obj == null) {
1433  return false;
1434  }
1435  if (getClass() != obj.getClass()) {
1436  return false;
1437  }
1438  final CentralRepoHashSet other = (CentralRepoHashSet) obj;
1439  if (!Objects.equals(this.hashSetName, other.hashSetName)) {
1440  return false;
1441  }
1442  if (!Objects.equals(this.version, other.version)) {
1443  return false;
1444  }
1445  if (this.knownFilesType != other.knownFilesType) {
1446  return false;
1447  }
1448  return true;
1449  }
1450  }
1451 
1455  private class HashDbIndexer extends SwingWorker<Object, Void> {
1456 
1457  private ProgressHandle progress = null;
1458  private SleuthkitHashSet hashDb = null;
1459 
1460  HashDbIndexer(SleuthkitHashSet hashDb) {
1461  this.hashDb = hashDb;
1462  }
1463 
1464  @Override
1465  protected Object doInBackground() {
1466  hashDb.setIndexing(true);
1467  progress = ProgressHandle.createHandle(
1468  NbBundle.getMessage(this.getClass(), "HashDbManager.progress.indexingHashSet", hashDb.getHashSetName()));
1469  progress.start();
1470  progress.switchToIndeterminate();
1471  try {
1472  SleuthkitJNI.createLookupIndexForHashDatabase(hashDb.getHandle());
1473  } catch (TskCoreException ex) {
1474  Logger.getLogger(HashDbIndexer.class.getName()).log(Level.SEVERE, "Error indexing hash set " + hashDb.getHashSetName(), ex); //NON-NLS
1475  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
1476  NbBundle.getMessage(this.getClass(),
1477  "HashDbManager.dlgMsg.errorIndexingHashSet",
1478  hashDb.getHashSetName()),
1479  NbBundle.getMessage(this.getClass(), "HashDbManager.hashDbIndexingErr"),
1480  JOptionPane.ERROR_MESSAGE);
1481  }
1482  return null;
1483  }
1484 
1485  @Override
1486  protected void done() {
1487  hashDb.setIndexing(false);
1488  progress.finish();
1489 
1490  // see if we got any errors
1491  try {
1492  get();
1493  } catch (InterruptedException | ExecutionException ex) {
1494  logger.log(Level.SEVERE, "Error creating index", ex); //NON-NLS
1496  NbBundle.getMessage(this.getClass(), "HashDbManager.errCreatingIndex.title"),
1497  NbBundle.getMessage(this.getClass(), "HashDbManager.errCreatingIndex.msg", ex.getMessage()),
1499  } // catch and ignore if we were cancelled
1500  catch (java.util.concurrent.CancellationException ex) {
1501  }
1502 
1503  try {
1504  hashDb.firePropertyChange(SleuthkitHashSet.Event.INDEXING_DONE.toString(), null, hashDb);
1505  hashDb.firePropertyChange(HashDbManager.SetEvt.DB_INDEXED.toString(), null, hashDb.getHashSetName());
1506  } catch (Exception e) {
1507  logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
1509  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
1510  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
1512  }
1513  }
1514  }
1515 }
static synchronized IngestManager getInstance()
synchronized void addPropertyChangeListener(PropertyChangeListener listener)
List< CentralRepoFileSet > getAllReferenceSets(CorrelationAttributeInstance.Type correlationType)
static KnownFilesType fromFileKnown(TskData.FileKnown fileKnown)
List< HashDb > getUpdateableHashSets(List< HashDb > hashDbs)
synchronized HashDb addNewHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
abstract void firePropertyChange(String propertyName, Object oldValue, Object newValue)
synchronized void removeHashDatabaseNoSave(HashDb hashDb)
String getValidFilePath(String hashSetName, String configuredPath)
synchronized HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
synchronized void removePropertyChangeListener(PropertyChangeListener listener)
void closeHashDatabases(List< HashDb > hashDatabases)
abstract void addPropertyChangeListener(PropertyChangeListener pcl)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static void show(String title, String message, MessageType type, ActionListener actionListener)
CorrelationAttributeInstance.Type getCorrelationTypeById(int typeId)
KnownFilesType(String displayName, TskData.FileKnown fileKnown, boolean allowSendInboxMessages, boolean defaultSendInboxMessages)
SleuthkitHashSet addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
abstract void removePropertyChangeListener(PropertyChangeListener pcl)

Copyright © 2012-2020 Basis Technology. Generated on: Mon Jul 6 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.