Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ImageFilePanel.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2011-2021 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.casemodule;
20
21import com.google.common.util.concurrent.ThreadFactoryBuilder;
22import java.io.File;
23import java.util.Calendar;
24import java.util.List;
25import java.util.concurrent.Future;
26import java.util.concurrent.ScheduledThreadPoolExecutor;
27import java.util.concurrent.TimeUnit;
28import java.util.concurrent.locks.ReentrantLock;
29import java.util.function.Supplier;
30import java.util.logging.Level;
31import javax.swing.JFileChooser;
32import javax.swing.JOptionPane;
33import javax.swing.JPanel;
34import javax.swing.JTextField;
35import javax.swing.event.DocumentEvent;
36import javax.swing.event.DocumentListener;
37import javax.swing.filechooser.FileFilter;
38import org.apache.commons.lang3.StringUtils;
39import org.openide.util.NbBundle;
40import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
41import org.sleuthkit.autopsy.coreutils.DriveUtils;
42import org.sleuthkit.autopsy.coreutils.Logger;
43import org.sleuthkit.autopsy.coreutils.ModuleSettings;
44import org.sleuthkit.autopsy.coreutils.PathValidator;
45import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
46import org.sleuthkit.autopsy.guiutils.JFileChooserFactory;
47import org.sleuthkit.datamodel.HashUtility;
48import org.sleuthkit.datamodel.SleuthkitJNI;
49import org.sleuthkit.datamodel.SleuthkitJNI.TestOpenImageResult;
50
56@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
57public class ImageFilePanel extends JPanel {
58
59 private static final Logger logger = Logger.getLogger(AddImageTask.class.getName());
60
61 private static final long serialVersionUID = 1L;
62 private static final String PROP_LASTIMAGE_PATH = "LBL_LastImage_PATH"; //NON-NLS
63 private static final String[] SECTOR_SIZE_CHOICES = {"Auto Detect", "512", "1024", "2048", "4096"};
65 private JFileChooser fileChooser;
66 private final String contextName;
67 private final List<FileFilter> fileChooserFilters;
68
69 private static int VALIDATE_TIMEOUT_MILLIS = 1000;
70 static ScheduledThreadPoolExecutor delayedValidationService = new ScheduledThreadPoolExecutor(1, new ThreadFactoryBuilder().setNameFormat("ImageFilePanel delayed validation").build());
71
72 private final ReentrantLock validationWaitingLock = new ReentrantLock();
73 private final ReentrantLock validationLock = new ReentrantLock();
74
75 private Runnable validateAction = null;
76 private Future<?> validateFuture = null;
77
86 private ImageFilePanel(String context, List<FileFilter> fileChooserFilters) {
87 this.contextName = context;
89
90 // Populate the drop down list of time zones
92
93 // Populate the drop down list of sector size options
94 for (String choice : SECTOR_SIZE_CHOICES) {
95 sectorSizeComboBox.addItem(choice);
96 }
97 sectorSizeComboBox.setSelectedIndex(0);
98
99 errorLabel.setVisible(false);
100 loadingLabel.setVisible(false);
101 this.fileChooserFilters = fileChooserFilters;
102 }
103
108 private void createTimeZoneList() {
109 List<String> timeZoneList = TimeZoneUtils.createTimeZoneList();
110 for (String timeZone : timeZoneList) {
111 timeZoneComboBox.addItem(timeZone);
112 }
113
114 // set the selected timezone
115 timeZoneComboBox.setSelectedItem(TimeZoneUtils.createTimeZoneString(Calendar.getInstance().getTimeZone()));
116 }
117
128 public static synchronized ImageFilePanel createInstance(String context, List<FileFilter> fileChooserFilters) {
129 ImageFilePanel instance = new ImageFilePanel(context, fileChooserFilters);
130 DocumentListener delayedValidationListener = instance.new DelayedValidationDocListener();
131
132 // post-constructor initialization of listener support without leaking references of uninitialized objects
133 for (JTextField textField: List.of(
134 instance.getPathTextField(),
135 instance.getMd5TextFieldField(),
136 instance.getSha1TextField(),
137 instance.getSha256TextField(),
138 instance.getPasswordTextField())) {
139 textField.getDocument().addDocumentListener(delayedValidationListener);
140 }
141 return instance;
142 }
143
144 private JTextField getPathTextField() {
145 return pathTextField;
146 }
147
148 private JTextField getMd5TextFieldField() {
149 return md5HashTextField;
150 }
151
152 private JTextField getSha1TextField() {
153 return sha1HashTextField;
154 }
155
156 private JTextField getSha256TextField() {
157 return sha256HashTextField;
158 }
159
160 private JTextField getPasswordTextField() {
161 return passwordTextField;
162 }
163
164 private JFileChooser getChooser() {
165 if(fileChooser == null) {
166 fileChooser = fileChooserHelper.getChooser();
167 fileChooser.setDragEnabled(false);
168 fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
169 fileChooser.setMultiSelectionEnabled(false);
170 fileChooserFilters.forEach(fileChooser::addChoosableFileFilter);
171 if (fileChooserFilters.isEmpty() == false) {
172 fileChooser.setFileFilter(fileChooserFilters.get(0));
173 }
174 }
175
176 return fileChooser;
177 }
178
184 // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
185 private void initComponents() {
186 java.awt.GridBagConstraints gridBagConstraints;
187
188 pathLabel = new javax.swing.JLabel();
189 browseButton = new javax.swing.JButton();
190 pathTextField = new javax.swing.JTextField();
191 timeZoneLabel = new javax.swing.JLabel();
192 timeZoneComboBox = new javax.swing.JComboBox<>();
193 noFatOrphansCheckbox = new javax.swing.JCheckBox();
194 errorLabel = new javax.swing.JLabel();
195 sectorSizeLabel = new javax.swing.JLabel();
196 sectorSizeComboBox = new javax.swing.JComboBox<>();
197 sha256HashLabel = new javax.swing.JLabel();
198 sha256HashTextField = new javax.swing.JTextField();
199 sha1HashTextField = new javax.swing.JTextField();
200 md5HashTextField = new javax.swing.JTextField();
201 sha1HashLabel = new javax.swing.JLabel();
202 md5HashLabel = new javax.swing.JLabel();
203 hashValuesLabel = new javax.swing.JLabel();
204 hashValuesNoteLabel = new javax.swing.JLabel();
205 passwordLabel = new javax.swing.JLabel();
206 passwordTextField = new javax.swing.JTextField();
207 javax.swing.JPanel spacer = new javax.swing.JPanel();
208 loadingLabel = new javax.swing.JLabel();
209
210 setMinimumSize(new java.awt.Dimension(0, 65));
211 setPreferredSize(new java.awt.Dimension(403, 65));
212 setLayout(new java.awt.GridBagLayout());
213
214 org.openide.awt.Mnemonics.setLocalizedText(pathLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.pathLabel.text")); // NOI18N
215 gridBagConstraints = new java.awt.GridBagConstraints();
216 gridBagConstraints.gridx = 0;
217 gridBagConstraints.gridy = 0;
218 gridBagConstraints.gridwidth = 3;
219 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
220 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
221 gridBagConstraints.weightx = 1.0;
222 gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
223 add(pathLabel, gridBagConstraints);
224
225 org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.browseButton.text")); // NOI18N
226 browseButton.addActionListener(new java.awt.event.ActionListener() {
227 public void actionPerformed(java.awt.event.ActionEvent evt) {
228 browseButtonActionPerformed(evt);
229 }
230 });
231 gridBagConstraints = new java.awt.GridBagConstraints();
232 gridBagConstraints.gridx = 2;
233 gridBagConstraints.gridy = 1;
234 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
235 gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
236 add(browseButton, gridBagConstraints);
237
238 pathTextField.setText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.pathTextField.text")); // NOI18N
239 gridBagConstraints = new java.awt.GridBagConstraints();
240 gridBagConstraints.gridx = 0;
241 gridBagConstraints.gridy = 1;
242 gridBagConstraints.gridwidth = 2;
243 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
244 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
245 gridBagConstraints.weightx = 1.0;
246 gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
247 add(pathTextField, gridBagConstraints);
248
249 org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.timeZoneLabel.text")); // NOI18N
250 gridBagConstraints = new java.awt.GridBagConstraints();
251 gridBagConstraints.gridx = 0;
252 gridBagConstraints.gridy = 3;
253 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
254 gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
255 add(timeZoneLabel, gridBagConstraints);
256
257 timeZoneComboBox.setMaximumRowCount(30);
258 gridBagConstraints = new java.awt.GridBagConstraints();
259 gridBagConstraints.gridx = 1;
260 gridBagConstraints.gridy = 3;
261 gridBagConstraints.gridwidth = 2;
262 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
263 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
264 gridBagConstraints.weightx = 1.0;
265 gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
266 add(timeZoneComboBox, gridBagConstraints);
267
268 org.openide.awt.Mnemonics.setLocalizedText(noFatOrphansCheckbox, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.noFatOrphansCheckbox.text")); // NOI18N
269 noFatOrphansCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.noFatOrphansCheckbox.toolTipText")); // NOI18N
270 gridBagConstraints = new java.awt.GridBagConstraints();
271 gridBagConstraints.gridx = 0;
272 gridBagConstraints.gridy = 2;
273 gridBagConstraints.gridwidth = 3;
274 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
275 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
276 gridBagConstraints.weightx = 1.0;
277 gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
278 add(noFatOrphansCheckbox, gridBagConstraints);
279
280 errorLabel.setForeground(new java.awt.Color(255, 0, 0));
281 org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.errorLabel.text")); // NOI18N
282 errorLabel.setVerticalAlignment(javax.swing.SwingConstants.TOP);
283 errorLabel.setMaximumSize(new java.awt.Dimension(500, 60));
284 errorLabel.setMinimumSize(new java.awt.Dimension(200, 20));
285 errorLabel.setPreferredSize(new java.awt.Dimension(200, 60));
286 gridBagConstraints = new java.awt.GridBagConstraints();
287 gridBagConstraints.gridx = 0;
288 gridBagConstraints.gridy = 11;
289 gridBagConstraints.gridwidth = 3;
290 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
291 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
292 gridBagConstraints.weightx = 1.0;
293 gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
294 add(errorLabel, gridBagConstraints);
295
296 org.openide.awt.Mnemonics.setLocalizedText(sectorSizeLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.sectorSizeLabel.text")); // NOI18N
297 gridBagConstraints = new java.awt.GridBagConstraints();
298 gridBagConstraints.gridx = 0;
299 gridBagConstraints.gridy = 4;
300 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
301 gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
302 add(sectorSizeLabel, gridBagConstraints);
303
304 gridBagConstraints = new java.awt.GridBagConstraints();
305 gridBagConstraints.gridx = 1;
306 gridBagConstraints.gridy = 4;
307 gridBagConstraints.gridwidth = 2;
308 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
309 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
310 gridBagConstraints.weightx = 1.0;
311 gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
312 add(sectorSizeComboBox, gridBagConstraints);
313
314 org.openide.awt.Mnemonics.setLocalizedText(sha256HashLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.sha256HashLabel.text")); // NOI18N
315 sha256HashLabel.setEnabled(false);
316 gridBagConstraints = new java.awt.GridBagConstraints();
317 gridBagConstraints.gridx = 0;
318 gridBagConstraints.gridy = 9;
319 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
320 gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
321 add(sha256HashLabel, gridBagConstraints);
322
323 sha256HashTextField.setText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.sha256HashTextField.text")); // NOI18N
324 sha256HashTextField.setEnabled(false);
325 gridBagConstraints = new java.awt.GridBagConstraints();
326 gridBagConstraints.gridx = 1;
327 gridBagConstraints.gridy = 9;
328 gridBagConstraints.gridwidth = 2;
329 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
330 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
331 gridBagConstraints.weightx = 1.0;
332 gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
333 add(sha256HashTextField, gridBagConstraints);
334
335 sha1HashTextField.setText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.sha1HashTextField.text")); // NOI18N
336 sha1HashTextField.setEnabled(false);
337 gridBagConstraints = new java.awt.GridBagConstraints();
338 gridBagConstraints.gridx = 1;
339 gridBagConstraints.gridy = 8;
340 gridBagConstraints.gridwidth = 2;
341 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
342 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
343 gridBagConstraints.weightx = 1.0;
344 gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
345 add(sha1HashTextField, gridBagConstraints);
346
347 md5HashTextField.setText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.md5HashTextField.text")); // NOI18N
348 md5HashTextField.setEnabled(false);
349 gridBagConstraints = new java.awt.GridBagConstraints();
350 gridBagConstraints.gridx = 1;
351 gridBagConstraints.gridy = 7;
352 gridBagConstraints.gridwidth = 2;
353 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
354 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
355 gridBagConstraints.weightx = 1.0;
356 gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
357 add(md5HashTextField, gridBagConstraints);
358
359 org.openide.awt.Mnemonics.setLocalizedText(sha1HashLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.sha1HashLabel.text")); // NOI18N
360 sha1HashLabel.setEnabled(false);
361 gridBagConstraints = new java.awt.GridBagConstraints();
362 gridBagConstraints.gridx = 0;
363 gridBagConstraints.gridy = 8;
364 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
365 gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
366 add(sha1HashLabel, gridBagConstraints);
367
368 org.openide.awt.Mnemonics.setLocalizedText(md5HashLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.md5HashLabel.text")); // NOI18N
369 md5HashLabel.setEnabled(false);
370 gridBagConstraints = new java.awt.GridBagConstraints();
371 gridBagConstraints.gridx = 0;
372 gridBagConstraints.gridy = 7;
373 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
374 gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
375 add(md5HashLabel, gridBagConstraints);
376
377 org.openide.awt.Mnemonics.setLocalizedText(hashValuesLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.hashValuesLabel.text")); // NOI18N
378 hashValuesLabel.setEnabled(false);
379 gridBagConstraints = new java.awt.GridBagConstraints();
380 gridBagConstraints.gridx = 0;
381 gridBagConstraints.gridy = 6;
382 gridBagConstraints.gridwidth = 3;
383 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
384 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
385 gridBagConstraints.weightx = 1.0;
386 gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
387 add(hashValuesLabel, gridBagConstraints);
388
389 org.openide.awt.Mnemonics.setLocalizedText(hashValuesNoteLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.hashValuesNoteLabel.text")); // NOI18N
390 hashValuesNoteLabel.setEnabled(false);
391 gridBagConstraints = new java.awt.GridBagConstraints();
392 gridBagConstraints.gridx = 0;
393 gridBagConstraints.gridy = 10;
394 gridBagConstraints.gridwidth = 3;
395 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
396 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
397 gridBagConstraints.weightx = 1.0;
398 gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
399 add(hashValuesNoteLabel, gridBagConstraints);
400
401 org.openide.awt.Mnemonics.setLocalizedText(passwordLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.passwordLabel.text")); // NOI18N
402 gridBagConstraints = new java.awt.GridBagConstraints();
403 gridBagConstraints.gridx = 0;
404 gridBagConstraints.gridy = 5;
405 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
406 gridBagConstraints.insets = new java.awt.Insets(0, 5, 5, 5);
407 add(passwordLabel, gridBagConstraints);
408
409 passwordTextField.setText(org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.passwordTextField.text")); // NOI18N
410 gridBagConstraints = new java.awt.GridBagConstraints();
411 gridBagConstraints.gridx = 1;
412 gridBagConstraints.gridy = 5;
413 gridBagConstraints.gridwidth = 2;
414 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
415 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
416 gridBagConstraints.weightx = 1.0;
417 gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 5);
418 add(passwordTextField, gridBagConstraints);
419
420 javax.swing.GroupLayout spacerLayout = new javax.swing.GroupLayout(spacer);
421 spacer.setLayout(spacerLayout);
422 spacerLayout.setHorizontalGroup(
423 spacerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
424 .addGap(0, 0, Short.MAX_VALUE)
425 );
426 spacerLayout.setVerticalGroup(
427 spacerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
428 .addGap(0, 0, Short.MAX_VALUE)
429 );
430
431 gridBagConstraints = new java.awt.GridBagConstraints();
432 gridBagConstraints.gridx = 0;
433 gridBagConstraints.gridy = 12;
434 gridBagConstraints.weighty = 1.0;
435 add(spacer, gridBagConstraints);
436
437 loadingLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/working_spinner.gif"))); // NOI18N
438 org.openide.awt.Mnemonics.setLocalizedText(loadingLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.loadingLabel.text")); // NOI18N
439 loadingLabel.setVerticalAlignment(javax.swing.SwingConstants.TOP);
440 loadingLabel.setMaximumSize(new java.awt.Dimension(500, 60));
441 loadingLabel.setMinimumSize(new java.awt.Dimension(200, 20));
442 loadingLabel.setPreferredSize(new java.awt.Dimension(200, 60));
443 gridBagConstraints = new java.awt.GridBagConstraints();
444 gridBagConstraints.gridx = 0;
445 gridBagConstraints.gridy = 11;
446 gridBagConstraints.gridwidth = 3;
447 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
448 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
449 gridBagConstraints.weightx = 1.0;
450 gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
451 add(loadingLabel, gridBagConstraints);
452 }// </editor-fold>//GEN-END:initComponents
453
454 @NbBundle.Messages({"ImageFilePanel.000.confirmationMessage=The selected file"
455 + " has extenson .001 but there is a .000 file in the sequence of raw images."
456 + "\nShould the .000 file be used as the start, instead of the selected .001 file?\n"})
457 private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
458 String oldText = getContentPaths();
459 // set the current directory of the FileChooser if the ImagePath Field is valid
460 File currentDir = new File(oldText);
461 JFileChooser chooser = getChooser();
462 if (currentDir.exists()) {
463 chooser.setCurrentDirectory(currentDir);
464 }
465
466 if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
467 String path = chooser.getSelectedFile().getPath();
468 if (path.endsWith(".001")) {
469 String zeroX3_path = path.substring(0, path.length() - 4) + ".000";
470 if (new File(zeroX3_path).exists()) {
471 int showConfirmDialog = JOptionPane.showConfirmDialog(this,
472 Bundle.ImageFilePanel_000_confirmationMessage(),
473 "Choose .001 file?", JOptionPane.YES_NO_OPTION);
474 if (showConfirmDialog == JOptionPane.YES_OPTION) {
475 path = zeroX3_path;
476 }
477 }
478 }
479
480 setContentPath(path);
481
486 if (!oldText.equals(getContentPaths())) {
487 md5HashTextField.setText(null);
488 sha1HashTextField.setText(null);
489 sha256HashTextField.setText(null);
490 }
491 }
492
493 updateHelper();
494 }//GEN-LAST:event_browseButtonActionPerformed
495
496 // Variables declaration - do not modify//GEN-BEGIN:variables
497 private javax.swing.JButton browseButton;
498 private javax.swing.JLabel errorLabel;
499 private javax.swing.JLabel hashValuesLabel;
500 private javax.swing.JLabel hashValuesNoteLabel;
501 private javax.swing.JLabel loadingLabel;
502 private javax.swing.JLabel md5HashLabel;
503 private javax.swing.JTextField md5HashTextField;
504 private javax.swing.JCheckBox noFatOrphansCheckbox;
505 private javax.swing.JLabel passwordLabel;
506 private javax.swing.JTextField passwordTextField;
507 private javax.swing.JLabel pathLabel;
508 private javax.swing.JTextField pathTextField;
509 private javax.swing.JComboBox<String> sectorSizeComboBox;
510 private javax.swing.JLabel sectorSizeLabel;
511 private javax.swing.JLabel sha1HashLabel;
512 private javax.swing.JTextField sha1HashTextField;
513 private javax.swing.JLabel sha256HashLabel;
514 private javax.swing.JTextField sha256HashTextField;
515 private javax.swing.JComboBox<String> timeZoneComboBox;
516 private javax.swing.JLabel timeZoneLabel;
517 // End of variables declaration//GEN-END:variables
518
524 private void setHashValuesComponentsEnabled(boolean enabled) {
525 hashValuesLabel.setEnabled(enabled);
526 hashValuesNoteLabel.setEnabled(enabled);
527
528 md5HashLabel.setEnabled(enabled);
529 md5HashTextField.setEnabled(enabled);
530
531 sha1HashLabel.setEnabled(enabled);
532 sha1HashTextField.setEnabled(enabled);
533
534 sha256HashLabel.setEnabled(enabled);
535 sha256HashTextField.setEnabled(enabled);
536 }
537
543 public String getContentPaths() {
544 return pathTextField.getText();
545 }
546
552 public void setContentPath(String s) {
553 pathTextField.setText(s);
554 }
555
561 public int getSectorSize() {
562 int sectorSizeSelectionIndex = sectorSizeComboBox.getSelectedIndex();
563
564 if (sectorSizeSelectionIndex == 0) {
565 return 0;
566 }
567
568 return Integer.valueOf((String) sectorSizeComboBox.getSelectedItem());
569 }
570
571 public String getTimeZone() {
572 String tz = timeZoneComboBox.getSelectedItem().toString();
573 return tz.substring(tz.indexOf(')') + 2).trim();
574 }
575
576 public boolean getNoFatOrphans() {
577 return noFatOrphansCheckbox.isSelected();
578 }
579
580 String getMd5() {
581 return this.md5HashTextField.getText();
582 }
583
584 String getSha1() {
585 return this.sha1HashTextField.getText();
586 }
587
588 String getSha256() {
589 return this.sha256HashTextField.getText();
590 }
591
592 String getPassword() {
593 return this.passwordTextField.getText();
594 }
595
596 public void reset() {
597 //reset the UI elements to default
598 pathTextField.setText(null);
599 this.md5HashTextField.setText(null);
600 this.sha1HashTextField.setText(null);
601 this.sha256HashTextField.setText(null);
602 this.passwordTextField.setText(null);
603 }
604
610 private void setUIEnabled(boolean enabled, boolean validNonE01) {
611 this.browseButton.setEnabled(enabled);
612 this.noFatOrphansCheckbox.setEnabled(enabled);
613 this.passwordTextField.setEnabled(enabled);
614 this.pathTextField.setEnabled(enabled);
615 this.sectorSizeComboBox.setEnabled(enabled);
616 this.md5HashTextField.setEnabled(enabled && validNonE01);
617 this.sha1HashTextField.setEnabled(enabled && validNonE01);
618 this.sha256HashTextField.setEnabled(enabled && validNonE01);
619 this.timeZoneComboBox.setEnabled(enabled);
620 }
621
627 @NbBundle.Messages({
628 "ImageFilePanel.validatePanel.dataSourceOnCDriveError=Warning: Path to multi-user data source is on \"C:\" drive",
629 "ImageFilePanel.validatePanel.invalidMD5=Invalid MD5 hash",
630 "ImageFilePanel.validatePanel.invalidSHA1=Invalid SHA1 hash",
631 "ImageFilePanel.validatePanel.invalidSHA256=Invalid SHA256 hash",
632 "# {0} - imageOpenError",
633 "ImageFilePanel_validatePanel_imageOpenError=<html><body><p>An error occurred while opening the image:{0}</p></body></html>",
634 "ImageFilePanel_validatePanel_unknownErrorMsg=<unknown>",
635 "ImageFilePanel_validatePanel_unknownError=<html><body><p>An unknown error occurred while attempting to validate the image</p></body></html>"
636 })
637 public boolean validatePanel() {
638 return runWithLock(this.validationLock, () -> {
639 boolean validNonE01 = true;
640 try {
641
642 // acquire field values at the beginning to minimize chance of changing while validating.
643 String path = getContentPaths();
644
645 validNonE01 = isValidNonE01(path);
646 setUIEnabled(false, validNonE01);
647
648 String md5 = getMd5();
649 String sha1 = getSha1();
650 String sha256 = getSha256();
651 String password = getPassword();
652
653 if (!isImagePathValid(path)) {
654 showError(null);
655 return false;
656 }
657
658 if (!StringUtils.isBlank(md5) && !HashUtility.isValidMd5Hash(md5)) {
659 showError(Bundle.ImageFilePanel_validatePanel_invalidMD5());
660 return false;
661 }
662
663 if (!StringUtils.isBlank(sha1) && !HashUtility.isValidSha1Hash(sha1)) {
664 showError(Bundle.ImageFilePanel_validatePanel_invalidSHA1());
665 return false;
666 }
667
668 if (!StringUtils.isBlank(sha256) && !HashUtility.isValidSha256Hash(sha256)) {
669 showError(Bundle.ImageFilePanel_validatePanel_invalidSHA256());
670 return false;
671 }
672
673 try {
674 TestOpenImageResult testResult = SleuthkitJNI.testOpenImage(path, password);
675 if (!testResult.wasSuccessful()) {
676 showError(Bundle.ImageFilePanel_validatePanel_imageOpenError(
677 StringUtils.defaultIfBlank(
678 testResult.getMessage(),
679 Bundle.ImageFilePanel_validatePanel_unknownErrorMsg())));
680 return false;
681 }
682 } catch (Throwable t) {
683 logger.log(Level.SEVERE, "An unknown error occurred test opening image: " + path, t);
684 showError(Bundle.ImageFilePanel_validatePanel_unknownError());
685 return false;
686 }
687
689 showError(Bundle.ImageFilePanel_validatePanel_dataSourceOnCDriveError());
690 } else {
691 showError(null);
692 }
693 return true;
694 } finally {
695 setUIEnabled(true, validNonE01);
696 }
697 });
698 }
699
706 private void showError(String errorMessage) {
707 loadingLabel.setVisible(false);
708 if (StringUtils.isNotBlank(errorMessage)) {
709 errorLabel.setVisible(true);
710 errorLabel.setText(errorMessage);
711 } else {
712 errorLabel.setVisible(false);
713 errorLabel.setText("");
714 }
715 }
716
723 private boolean isImagePathValid(String path) {
724 if (StringUtils.isBlank(path) || (!(new File(path).isFile() || DriveUtils.isPhysicalDrive(path) || DriveUtils.isPartition(path)))) {
725 return false;
726 }
727
728 return true;
729 }
730
736 private boolean isValidNonE01(String path) {
737 return StringUtils.isNotBlank(path) && isImagePathValid(path) && !path.toLowerCase().endsWith(".e01");
738 }
739
740 public void storeSettings() {
741 String imagePathName = getContentPaths();
742 if (null != imagePathName) {
743 String imagePath = imagePathName.substring(0, imagePathName.lastIndexOf(File.separator) + 1);
745 }
746 }
747
748 public void readSettings() {
750 if (StringUtils.isNotBlank(lastImagePath)) {
751 setContentPath(lastImagePath);
752 }
753 }
754
761 @NbBundle.Messages({"ImageFilePanel.moduleErr=Module Error",
762 "ImageFilePanel.moduleErr.msg=A module caused an error listening to ImageFilePanel updates."
763 + " See log to determine which module. Some data could be incomplete.\n"})
764 private void updateHelper() {
765 String path = getContentPaths();
766 if (isValidNonE01(path)) {
768 } else {
770 }
771
772 firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
773 }
774
778 public void select() {
779 pathTextField.requestFocusInWindow();
780 }
781
791 private <T> T runWithLock(ReentrantLock lock, Supplier<T> action) {
792 try {
793 lock.lock();
794 return action.get();
795 } finally {
796 lock.unlock();
797 }
798 }
799
804 public boolean isValidationLoading() {
805 return runWithLock(this.validationWaitingLock, () -> this.validateFuture != null
806 && !this.validateFuture.isCancelled()
807 && !this.validateFuture.isDone());
808 }
809
814 private class DelayedValidationDocListener implements DocumentListener {
815
816 @Override
817 public void insertUpdate(DocumentEvent e) {
819 }
820
821 @Override
822 public void removeUpdate(DocumentEvent e) {
824 }
825
826 @Override
827 public void changedUpdate(DocumentEvent e) {
829 }
830
835 private void delayValidate() {
836
837 boolean triggerUpdate = runWithLock(validationWaitingLock, () -> {
838
839 boolean toRetTriggerUpdate = false;
840 if (isValidationLoading()) {
841 validateFuture.cancel(true);
842 toRetTriggerUpdate = true;
843 }
844
846
847 validateFuture = delayedValidationService.schedule(
850 TimeUnit.MILLISECONDS);
851
852 return toRetTriggerUpdate;
853 });
854
855 errorLabel.setVisible(false);
856 loadingLabel.setVisible(true);
857
858 // trigger invalidation after setting up new runnable if not already triggered
859 if (triggerUpdate) {
860 firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(), false, true);
861 }
862 }
863
868 private class ValidationRunnable implements Runnable {
869
870 @Override
871 public void run() {
872
873 boolean isRunningAction = runWithLock(validationWaitingLock, () -> {
874 if (validateAction != this) {
875 return false;
876 }
877
878 // set the validation action to null to indicate that this is done running and can be validated.
879 validateAction = null;
880 validateFuture = null;
881
882 return true;
883 });
884
885 if (!isRunningAction) {
886 return;
887 } else if (Thread.interrupted()) {
888 return;
889 }
890
891 ImageFilePanel.this.updateHelper();
892 }
893
894 }
895 }
896}
ImageFilePanel(String context, List< FileFilter > fileChooserFilters)
void setUIEnabled(boolean enabled, boolean validNonE01)
javax.swing.JComboBox< String > sectorSizeComboBox
javax.swing.JComboBox< String > timeZoneComboBox
void browseButtonActionPerformed(java.awt.event.ActionEvent evt)
static synchronized ImageFilePanel createInstance(String context, List< FileFilter > fileChooserFilters)
static boolean isPartition(String path)
static boolean isPhysicalDrive(String path)
synchronized static Logger getLogger(String name)
Definition Logger.java:124
static synchronized void setConfigSetting(String moduleName, String settingName, String settingVal)
static synchronized String getConfigSetting(String moduleName, String settingName)
static boolean isValidForCaseType(String path, Case.CaseType caseType)
static String createTimeZoneString(TimeZone timeZone)

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