Autopsy  4.20.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ImportCentralRepoDbProgressDialog.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.awt.Color;
22 import java.beans.PropertyChangeListener;
23 import java.beans.PropertyChangeEvent;
24 import java.util.HashSet;
25 import java.util.Set;
26 import java.util.logging.Level;
27 import javax.swing.JFrame;
28 import javax.swing.SwingWorker;
29 import javax.swing.WindowConstants;
30 import java.util.concurrent.atomic.AtomicLong;
31 import java.util.concurrent.atomic.AtomicBoolean;
32 import java.util.concurrent.atomic.AtomicInteger;
33 import org.openide.util.NbBundle;
34 import org.openide.windows.WindowManager;
40 import org.sleuthkit.datamodel.TskCoreException;
41 import org.sleuthkit.datamodel.TskData;
43 import org.sleuthkit.datamodel.HashEntry;
44 
48 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
49 class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements PropertyChangeListener {
50 
51  private static final long serialVersionUID = 1L;
52 
53  private CentralRepoImportWorker worker; // Swing worker that will import the file and send updates to the dialog
54 
55  @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.title.text=Central Repository Import Progress",})
56  ImportCentralRepoDbProgressDialog() {
57  super((JFrame) WindowManager.getDefault().getMainWindow(),
58  Bundle.ImportCentralRepoDbProgressDialog_title_text(),
59  true);
60 
61  initComponents();
62  customizeComponents();
63  }
64 
65  private void customizeComponents() {
66  // This is preventing the user from closing the dialog using the X
67  setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
68 
69  bnOk.setEnabled(false);
70  }
71 
85  void importFile(String hashSetName, String version, int orgId,
86  boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType,
87  boolean readOnly, String importFileName) {
88 
89  worker = new CentralRepoImportWorker(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages,
90  knownFilesType, readOnly, importFileName);
91  worker.addPropertyChangeListener(this);
92  worker.execute();
93 
94  setLocationRelativeTo((JFrame) WindowManager.getDefault().getMainWindow());
95  this.setVisible(true);
96  }
97 
104  HashDbManager.HashDb getDatabase() {
105  if (worker != null) {
106  return worker.getDatabase();
107  }
108  return null;
109  }
110 
117  @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.errorParsingFile.message=Error parsing hash set file"})
118  @Override
119  public void propertyChange(PropertyChangeEvent evt) {
120 
121  if ("progress".equals(evt.getPropertyName())) {
122  // The progress has been updated. Update the progress bar and text
123  progressBar.setValue(worker.getProgress());
124  lbProgress.setText(getProgressString());
125  } else if ("state".equals(evt.getPropertyName())
126  && (SwingWorker.StateValue.DONE.equals(evt.getNewValue()))) {
127 
128  // The worker is done processing
129  // Disable cancel button and enable ok
130  bnCancel.setEnabled(false);
131  bnOk.setEnabled(true);
132 
133  if (worker.getImportSuccess()) {
134  // If the import succeeded, finish the progress bar and display the
135  // total number of imported hashes
136  progressBar.setValue(progressBar.getMaximum());
137  lbProgress.setText(getProgressString());
138  } else {
139  // If there was an error, reset the progress bar and display an error message
140  progressBar.setValue(0);
141  lbProgress.setForeground(Color.red);
142  lbProgress.setText(Bundle.ImportCentralRepoDbProgressDialog_errorParsingFile_message());
143  }
144  }
145  }
146 
147  @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.linesProcessed.message= hashes processed"})
148  private String getProgressString() {
149  return worker.getNumHashesProcessed() + Bundle.ImportCentralRepoDbProgressDialog_linesProcessed_message();
150  }
151 
152  private class CentralRepoImportWorker extends SwingWorker<Void, Void> {
153 
154  private final int HASH_IMPORT_THRESHOLD = 10000;
155  private final String hashSetName;
156  private final String version;
157  private final int orgId;
158  private final boolean searchDuringIngest;
159  private final boolean sendIngestMessages;
161  private final boolean readOnly;
162  private final String importFileName;
163  private HashDbManager.CentralRepoHashSet newHashDb = null;
164  private final AtomicInteger referenceSetID = new AtomicInteger();
165  private final AtomicLong hashCount = new AtomicLong();
166  private final AtomicBoolean importSuccess = new AtomicBoolean();
167 
168  CentralRepoImportWorker(String hashSetName, String version, int orgId,
169  boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType,
170  boolean readOnly, String importFileName) {
171 
172  this.hashSetName = hashSetName;
173  this.version = version;
174  this.orgId = orgId;
175  this.searchDuringIngest = searchDuringIngest;
176  this.sendIngestMessages = sendIngestMessages;
177  this.knownFilesType = knownFilesType;
178  this.readOnly = readOnly;
179  this.importFileName = importFileName;
180  this.hashCount.set(0);
181  this.importSuccess.set(false);
182  this.referenceSetID.set(-1);
183  }
184 
191  synchronized HashDbManager.CentralRepoHashSet getDatabase() {
192  return newHashDb;
193  }
194 
200  long getNumHashesProcessed() {
201  return hashCount.get();
202  }
203 
210  boolean getImportSuccess() {
211  return importSuccess.get();
212  }
213 
214  @Override
215  protected Void doInBackground() throws Exception {
216 
217  // Create the hash set parser
218  HashSetParser hashSetParser;
219  if (importFileName.toLowerCase().endsWith(".idx") || importFileName.toLowerCase().endsWith(".txt")) {
220  hashSetParser = new IdxHashSetParser(importFileName);
221  } else if (importFileName.toLowerCase().endsWith(".hash")) {
222  hashSetParser = new EncaseHashSetParser(importFileName);
223  } else if (importFileName.toLowerCase().endsWith(".kdb")) {
224  hashSetParser = new KdbHashSetParser(importFileName);
225  } else if (importFileName.toLowerCase().endsWith(".hsh")) {
226  hashSetParser = new HashkeeperHashSetParser(importFileName);
227  } else {
228  // We've gotten here with a format that can't be processed
229  throw new TskCoreException("Hash set to import is an unknown format : " + importFileName);
230  }
231 
232  try {
233  // Conver to the FileKnown enum used by EamGlobalSet
234  TskData.FileKnown knownStatus = knownFilesType.getFileKnown();
235 
236  // Create an empty hashset in the central repository
238  referenceSetID.set(dbManager.newReferenceSet(new CentralRepoFileSet(orgId, hashSetName, version, knownStatus,
240 
241  // Get the "FILES" content type. This is a database lookup so we
242  // only want to do it once.
244 
245  // Holds the current batch of hashes that need to be written to the central repo
246  Set<CentralRepoFileInstance> globalInstances = new HashSet<>();
247 
248  while (!hashSetParser.doneReading()) {
249  if (isCancelled()) {
250  return null;
251  }
252 
253  HashEntry newHash = hashSetParser.getNextHashEntry();
254 
255  if (newHash != null) {
256  CentralRepoFileInstance eamGlobalFileInstance = new CentralRepoFileInstance(
257  referenceSetID.get(),
258  newHash.getMd5Hash(),
259  knownStatus,
260  newHash.getComment());
261 
262  globalInstances.add(eamGlobalFileInstance);
263 
264  // If we've hit the threshold for writing the hashes, write them
265  // all to the central repo
266  if (hashCount.incrementAndGet() % HASH_IMPORT_THRESHOLD == 0) {
267  dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType);
268  globalInstances.clear();
269 
270  int progress = (int) (hashCount.get() * 100 / hashSetParser.getExpectedHashCount());
271  if (progress < 100) {
272  this.setProgress(progress);
273  } else {
274  this.setProgress(99);
275  }
276  }
277  }
278  }
279 
280  // Add any remaining hashes to the central repo
281  dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType);
282  this.setProgress(100);
283  return null;
284  } finally {
285  hashSetParser.close();
286  }
287  }
288 
289  private void deleteIncompleteSet() {
290  if (referenceSetID.get() >= 0) {
291 
292  // This can be slow on large reference sets
293  new Thread(() -> {
294  try {
295  CentralRepository.getInstance().deleteReferenceSet(referenceSetID.get());
296  } catch (CentralRepoException ex2) {
297  Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error deleting incomplete hash set from central repository", ex2);
298  }
299  }).start();
300  }
301  }
302 
303  @Override
304  synchronized protected void done() {
305 
306  if (isCancelled()) {
307  // If the user hit cancel, delete this incomplete hash set from the central repo
308  deleteIncompleteSet();
309  return;
310  }
311 
312  try {
313  get();
314  try {
315  newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetName, version,
316  referenceSetID.get(),
317  searchDuringIngest, sendIngestMessages, knownFilesType, readOnly);
318  importSuccess.set(true);
319  } catch (TskCoreException ex) {
320  Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error adding imported hash set", ex);
321  }
322  } catch (Exception ex) {
323  // Delete this incomplete hash set from the central repo
324  deleteIncompleteSet();
325  Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error importing hash set", ex);
326  }
327  }
328 
329  }
330 
336  @SuppressWarnings("unchecked")
337  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
338  private void initComponents() {
339 
340  progressBar = new javax.swing.JProgressBar();
341  lbProgress = new javax.swing.JLabel();
342  bnOk = new javax.swing.JButton();
343  bnCancel = new javax.swing.JButton();
344  jLabel1 = new javax.swing.JLabel();
345 
346  setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
347 
348  org.openide.awt.Mnemonics.setLocalizedText(lbProgress, org.openide.util.NbBundle.getMessage(ImportCentralRepoDbProgressDialog.class, "ImportCentralRepoDbProgressDialog.lbProgress.text")); // NOI18N
349 
350  org.openide.awt.Mnemonics.setLocalizedText(bnOk, org.openide.util.NbBundle.getMessage(ImportCentralRepoDbProgressDialog.class, "ImportCentralRepoDbProgressDialog.bnOk.text")); // NOI18N
351  bnOk.addActionListener(new java.awt.event.ActionListener() {
352  public void actionPerformed(java.awt.event.ActionEvent evt) {
353  bnOkActionPerformed(evt);
354  }
355  });
356 
357  org.openide.awt.Mnemonics.setLocalizedText(bnCancel, org.openide.util.NbBundle.getMessage(ImportCentralRepoDbProgressDialog.class, "ImportCentralRepoDbProgressDialog.bnCancel.text")); // NOI18N
358  bnCancel.addActionListener(new java.awt.event.ActionListener() {
359  public void actionPerformed(java.awt.event.ActionEvent evt) {
360  bnCancelActionPerformed(evt);
361  }
362  });
363 
364  org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ImportCentralRepoDbProgressDialog.class, "ImportCentralRepoDbProgressDialog.jLabel1.text")); // NOI18N
365 
366  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
367  getContentPane().setLayout(layout);
368  layout.setHorizontalGroup(
369  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
370  .addGroup(layout.createSequentialGroup()
371  .addContainerGap()
372  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
373  .addGroup(layout.createSequentialGroup()
374  .addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
375  .addContainerGap())
376  .addGroup(layout.createSequentialGroup()
377  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
378  .addComponent(jLabel1)
379  .addComponent(lbProgress))
380  .addGap(0, 0, Short.MAX_VALUE))))
381  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
382  .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
383  .addComponent(bnOk)
384  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
385  .addComponent(bnCancel)
386  .addContainerGap())
387  );
388  layout.setVerticalGroup(
389  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
390  .addGroup(layout.createSequentialGroup()
391  .addContainerGap()
392  .addComponent(jLabel1)
393  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
394  .addComponent(lbProgress)
395  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
396  .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
397  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
398  .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
399  .addComponent(bnCancel)
400  .addComponent(bnOk))
401  .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
402  );
403 
404  pack();
405  }// </editor-fold>//GEN-END:initComponents
406 
407  private void bnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCancelActionPerformed
408  this.worker.cancel(true);
409  this.dispose();
410  }//GEN-LAST:event_bnCancelActionPerformed
411 
412  private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed
413  this.dispose();
414  }//GEN-LAST:event_bnOkActionPerformed
415 
416 
417  // Variables declaration - do not modify//GEN-BEGIN:variables
418  private javax.swing.JButton bnCancel;
419  private javax.swing.JButton bnOk;
420  private javax.swing.JLabel jLabel1;
421  private javax.swing.JLabel lbProgress;
422  private javax.swing.JProgressBar progressBar;
423  // End of variables declaration//GEN-END:variables
424 }
void bulkInsertReferenceTypeEntries(Set< CentralRepoFileInstance > globalInstances, CorrelationAttributeInstance.Type contentType)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
CorrelationAttributeInstance.Type getCorrelationTypeById(int typeId)

Copyright © 2012-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.