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

Copyright © 2012-2016 Basis Technology. Generated on: Mon May 7 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.