Autopsy 4.22.1
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 */
19package org.sleuthkit.autopsy.modules.hashdatabase;
20
21import java.awt.Color;
22import java.beans.PropertyChangeListener;
23import java.beans.PropertyChangeEvent;
24import java.util.HashSet;
25import java.util.Set;
26import java.util.logging.Level;
27import javax.swing.JFrame;
28import javax.swing.SwingWorker;
29import javax.swing.WindowConstants;
30import java.util.concurrent.atomic.AtomicLong;
31import java.util.concurrent.atomic.AtomicBoolean;
32import java.util.concurrent.atomic.AtomicInteger;
33import org.openide.util.NbBundle;
34import org.openide.windows.WindowManager;
35import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
36import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
37import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoFileInstance;
38import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoFileSet;
39import org.sleuthkit.autopsy.coreutils.Logger;
40import org.sleuthkit.datamodel.TskCoreException;
41import org.sleuthkit.datamodel.TskData;
42import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
43import org.sleuthkit.datamodel.HashEntry;
44
48@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
49class 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,
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
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 {
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
309 return;
310 }
311
312 try {
313 get();
314 try {
315 newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetName, version,
316 referenceSetID.get(),
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
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}
synchronized static Logger getLogger(String name)
Definition Logger.java:124
CorrelationAttributeInstance.Type getCorrelationTypeById(int typeId)
void bulkInsertReferenceTypeEntries(Set< CentralRepoFileInstance > globalInstances, CorrelationAttributeInstance.Type contentType)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.