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