19 package org.sleuthkit.autopsy.casemodule;
22 import java.nio.file.Paths;
23 import java.util.Calendar;
24 import java.util.List;
25 import java.util.logging.Level;
26 import javax.swing.JFileChooser;
27 import javax.swing.JPanel;
28 import org.openide.util.NbBundle;
42 "LocalDiskPanel.errorMessage.noOpenCaseTitle=No open case available",
43 "LocalDiskPanel.errorMessage.noOpenCaseBody=LocalDiskPanel listener couldn't get the open case.",
44 "LocalDiskPanel.imageWriterError.directoryNotExist=Error - directory does not exist",
45 "LocalDiskPanel.imageWriterError.emptyPath=Error - enter path for VHD",
46 "LocalDiskPanel.imageWriterError.isDirectory=Error - VHD path is a directory",
47 "LocalDiskPanel.imageWriterError.fileExists=Error - VHD path already exists",
48 "LocalDiskPanel.moduleErrorMessage.title=Module Error",
49 "LocalDiskPanel.moduleErrorMessage.body=A module caused an error listening to LocalDiskPanel updates. See log to determine which module. Some data could be incomplete.",
50 "LocalDiskPanel.localDiskMessage.unspecified=Unspecified"
52 @SuppressWarnings(
"PMD.SingularField")
53 final class LocalDiskPanel
extends JPanel {
55 private static final Logger logger = Logger.getLogger(LocalDiskPanel.class.getName());
56 private static final String[] SECTOR_SIZE_CHOICES = {
"Auto Detect",
"512",
"1024",
"2048",
"4096"};
57 private static LocalDiskPanel instance;
58 private static final long serialVersionUID = 1L;
59 private LocalDisk localDisk;
60 private boolean enableNext =
false;
61 private final JFileChooser fc =
new JFileChooser();
70 createSectorSizeList();
76 static synchronized LocalDiskPanel getDefault() {
77 if (instance == null) {
78 instance =
new LocalDiskPanel();
83 @SuppressWarnings(
"unchecked")
84 private
void customInit() {
85 imageWriterErrorLabel.setVisible(
false);
86 imageWriterErrorLabel.setText(
"");
87 if (!PlatformUtil.isWindowsOS()) {
88 copyImageCheckbox.setSelected(
false);
89 copyImageCheckbox.setEnabled(
false);
91 pathTextField.setEnabled(copyImageCheckbox.isSelected());
92 browseButton.setEnabled(copyImageCheckbox.isSelected());
93 changeDatabasePathCheckbox.setEnabled(copyImageCheckbox.isSelected());
101 @SuppressWarnings(
"unchecked")
103 private
void initComponents() {
105 timeZoneLabel =
new javax.swing.JLabel();
106 timeZoneComboBox =
new javax.swing.JComboBox<>();
107 noFatOrphansCheckbox =
new javax.swing.JCheckBox();
108 descLabel =
new javax.swing.JLabel();
109 copyImageCheckbox =
new javax.swing.JCheckBox();
110 pathTextField =
new javax.swing.JTextField();
111 browseButton =
new javax.swing.JButton();
112 jLabel1 =
new javax.swing.JLabel();
113 imageWriterErrorLabel =
new javax.swing.JLabel();
114 changeDatabasePathCheckbox =
new javax.swing.JCheckBox();
115 sectorSizeLabel =
new javax.swing.JLabel();
116 sectorSizeComboBox =
new javax.swing.JComboBox<>();
117 selectDiskButton =
new javax.swing.JButton();
118 localDiskLabel =
new javax.swing.JLabel();
119 localDiskNameTextField =
new javax.swing.JTextField();
121 setMinimumSize(
new java.awt.Dimension(0, 420));
122 setPreferredSize(
new java.awt.Dimension(485, 410));
124 timeZoneLabel.setFont(timeZoneLabel.getFont().deriveFont(timeZoneLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
125 org.openide.awt.Mnemonics.setLocalizedText(timeZoneLabel,
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class,
"LocalDiskPanel.timeZoneLabel.text"));
127 timeZoneComboBox.setFont(timeZoneComboBox.getFont().deriveFont(timeZoneComboBox.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
128 timeZoneComboBox.setMaximumRowCount(30);
130 noFatOrphansCheckbox.setFont(noFatOrphansCheckbox.getFont().deriveFont(noFatOrphansCheckbox.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
131 org.openide.awt.Mnemonics.setLocalizedText(noFatOrphansCheckbox,
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class,
"LocalDiskPanel.noFatOrphansCheckbox.text"));
132 noFatOrphansCheckbox.setToolTipText(
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class,
"LocalDiskPanel.noFatOrphansCheckbox.toolTipText"));
134 descLabel.setFont(descLabel.getFont().deriveFont(descLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
135 org.openide.awt.Mnemonics.setLocalizedText(descLabel,
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class,
"LocalDiskPanel.descLabel.text"));
137 org.openide.awt.Mnemonics.setLocalizedText(copyImageCheckbox,
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class,
"LocalDiskPanel.copyImageCheckbox.text"));
138 copyImageCheckbox.addActionListener(
new java.awt.event.ActionListener() {
139 public void actionPerformed(java.awt.event.ActionEvent evt) {
140 copyImageCheckboxActionPerformed(evt);
144 pathTextField.setText(
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class,
"LocalDiskPanel.pathTextField.text"));
145 pathTextField.addKeyListener(
new java.awt.event.KeyAdapter() {
146 public void keyReleased(java.awt.event.KeyEvent evt) {
147 pathTextFieldKeyReleased(evt);
151 org.openide.awt.Mnemonics.setLocalizedText(browseButton,
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class,
"LocalDiskPanel.browseButton.text"));
152 browseButton.addActionListener(
new java.awt.event.ActionListener() {
153 public void actionPerformed(java.awt.event.ActionEvent evt) {
154 browseButtonActionPerformed(evt);
158 org.openide.awt.Mnemonics.setLocalizedText(jLabel1,
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class,
"LocalDiskPanel.jLabel1.text"));
160 imageWriterErrorLabel.setFont(imageWriterErrorLabel.getFont().deriveFont(imageWriterErrorLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
161 imageWriterErrorLabel.setForeground(
new java.awt.Color(255, 0, 0));
162 org.openide.awt.Mnemonics.setLocalizedText(imageWriterErrorLabel,
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class,
"LocalDiskPanel.imageWriterErrorLabel.text"));
164 org.openide.awt.Mnemonics.setLocalizedText(changeDatabasePathCheckbox,
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class,
"LocalDiskPanel.changeDatabasePathCheckbox.text"));
166 org.openide.awt.Mnemonics.setLocalizedText(sectorSizeLabel,
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class,
"LocalDiskPanel.sectorSizeLabel.text"));
168 org.openide.awt.Mnemonics.setLocalizedText(selectDiskButton,
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class,
"LocalDiskPanel.selectDiskButton.text"));
169 selectDiskButton.addActionListener(
new java.awt.event.ActionListener() {
170 public void actionPerformed(java.awt.event.ActionEvent evt) {
171 selectDiskButtonActionPerformed(evt);
175 org.openide.awt.Mnemonics.setLocalizedText(localDiskLabel,
org.openide.util.NbBundle.getMessage(LocalDiskPanel.class,
"LocalDiskPanel.localDiskLabel.text"));
177 localDiskNameTextField.setEditable(
false);
179 javax.swing.GroupLayout layout =
new javax.swing.GroupLayout(
this);
180 this.setLayout(layout);
181 layout.setHorizontalGroup(
182 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
183 .addGroup(layout.createSequentialGroup()
184 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
185 .addGroup(layout.createSequentialGroup()
186 .addComponent(localDiskLabel)
187 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
188 .addComponent(localDiskNameTextField)
189 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
190 .addComponent(selectDiskButton))
191 .addGroup(layout.createSequentialGroup()
192 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
193 .addGroup(layout.createSequentialGroup()
194 .addComponent(timeZoneLabel)
195 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
196 .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 275, javax.swing.GroupLayout.PREFERRED_SIZE))
197 .addComponent(noFatOrphansCheckbox)
198 .addComponent(copyImageCheckbox)
199 .addGroup(layout.createSequentialGroup()
201 .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 342, javax.swing.GroupLayout.PREFERRED_SIZE)
202 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
203 .addComponent(browseButton))
204 .addGroup(layout.createSequentialGroup()
206 .addComponent(sectorSizeLabel)
207 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
208 .addComponent(sectorSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
209 .addGroup(layout.createSequentialGroup()
211 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
212 .addComponent(descLabel)
213 .addComponent(changeDatabasePathCheckbox)
214 .addGroup(layout.createSequentialGroup()
216 .addComponent(jLabel1))
217 .addComponent(imageWriterErrorLabel))))
218 .addGap(0, 39, Short.MAX_VALUE)))
221 layout.setVerticalGroup(
222 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
223 .addGroup(layout.createSequentialGroup()
224 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
225 .addComponent(localDiskLabel)
226 .addComponent(selectDiskButton)
227 .addComponent(localDiskNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
229 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
230 .addComponent(timeZoneLabel)
231 .addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
233 .addComponent(noFatOrphansCheckbox)
234 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
235 .addComponent(descLabel)
237 .addComponent(copyImageCheckbox)
238 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
239 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
240 .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
241 .addComponent(browseButton))
243 .addComponent(changeDatabasePathCheckbox)
244 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
245 .addComponent(jLabel1)
246 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
247 .addComponent(imageWriterErrorLabel)
249 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
250 .addComponent(sectorSizeLabel)
251 .addComponent(sectorSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
252 .addContainerGap(127, Short.MAX_VALUE))
256 private void copyImageCheckboxActionPerformed(java.awt.event.ActionEvent evt) {
257 pathTextField.setEnabled(copyImageCheckbox.isSelected());
258 browseButton.setEnabled(copyImageCheckbox.isSelected());
259 changeDatabasePathCheckbox.setEnabled(copyImageCheckbox.isSelected());
260 changeDatabasePathCheckbox.setSelected(copyImageCheckbox.isSelected());
264 private void pathTextFieldKeyReleased(java.awt.event.KeyEvent evt) {
268 private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {
269 String oldText = pathTextField.getText();
271 File currentFile =
new File(oldText);
272 if ((currentFile.getParentFile() != null) && (currentFile.getParentFile().exists())) {
273 fc.setSelectedFile(currentFile);
276 int retval = fc.showOpenDialog(
this);
277 if (retval == JFileChooser.APPROVE_OPTION) {
278 String path = fc.getSelectedFile().getPath();
279 pathTextField.setText(path);
284 private void selectDiskButtonActionPerformed(java.awt.event.ActionEvent evt) {
285 LocalDiskSelectionDialog selectionDialog =
new LocalDiskSelectionDialog();
286 selectionDialog.display();
287 LocalDisk selectedLocalDisk = selectionDialog.getLocalDiskSelection();
288 if (selectedLocalDisk != null) {
289 localDisk = selectedLocalDisk;
290 localDiskNameTextField.setText(selectedLocalDisk.getName());
294 setPotentialImageWriterPath(localDisk);
295 firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(),
false,
true);
296 }
catch (NoCurrentCaseException ex) {
297 logger.log(Level.SEVERE,
"Exception while getting open case.", ex);
298 MessageNotifyUtil.Notify.show(Bundle.LocalDiskPanel_errorMessage_noOpenCaseTitle(),
299 Bundle.LocalDiskPanel_errorMessage_noOpenCaseBody(),
300 MessageNotifyUtil.MessageType.ERROR);
301 }
catch (Exception ex) {
302 logger.log(Level.SEVERE,
"LocalDiskPanel listener threw exception", ex);
303 MessageNotifyUtil.Notify.show(Bundle.LocalDiskPanel_moduleErrorMessage_title(),
304 Bundle.LocalDiskPanel_moduleErrorMessage_body(),
305 MessageNotifyUtil.MessageType.ERROR);
311 private javax.swing.JButton browseButton;
312 private javax.swing.JCheckBox changeDatabasePathCheckbox;
313 private javax.swing.JCheckBox copyImageCheckbox;
314 private javax.swing.JLabel descLabel;
315 private javax.swing.JLabel imageWriterErrorLabel;
316 private javax.swing.JLabel jLabel1;
317 private javax.swing.JLabel localDiskLabel;
318 private javax.swing.JTextField localDiskNameTextField;
319 private javax.swing.JCheckBox noFatOrphansCheckbox;
320 private javax.swing.JTextField pathTextField;
321 private javax.swing.JComboBox<String> sectorSizeComboBox;
322 private javax.swing.JLabel sectorSizeLabel;
323 private javax.swing.JButton selectDiskButton;
324 private javax.swing.JComboBox<String> timeZoneComboBox;
325 private javax.swing.JLabel timeZoneLabel;
328 private void fireUpdateEvent() {
330 firePropertyChange(DataSourceProcessor.DSP_PANEL_EVENT.UPDATE_UI.toString(),
false,
true);
331 }
catch (Exception e) {
332 logger.log(Level.SEVERE,
"LocalDiskPanel listener threw exception", e);
333 MessageNotifyUtil.Notify.show(Bundle.LocalDiskPanel_moduleErrorMessage_title(),
334 Bundle.LocalDiskPanel_moduleErrorMessage_body(),
335 MessageNotifyUtil.MessageType.ERROR);
342 void resetLocalDiskSelection() {
344 localDiskNameTextField.setText(Bundle.LocalDiskPanel_localDiskMessage_unspecified());
353 String getContentPath() {
354 if (localDisk != null) {
355 return localDisk.getPath();
366 int getSectorSize() {
367 int sectorSizeSelectionIndex = sectorSizeComboBox.getSelectedIndex();
369 if (sectorSizeSelectionIndex == 0) {
373 return Integer.valueOf((String) sectorSizeComboBox.getSelectedItem());
376 String getTimeZone() {
377 String tz = timeZoneComboBox.getSelectedItem().toString();
378 return tz.substring(tz.indexOf(
")") + 2).trim();
382 boolean getNoFatOrphans() {
383 return noFatOrphansCheckbox.isSelected();
386 private static String getDefaultImageWriterFolder() throws NoCurrentCaseException {
387 return Paths.get(Case.getCurrentCaseThrows().getModuleDirectory(),
"Image Writer").toString();
390 private void setPotentialImageWriterPath(LocalDisk disk)
throws NoCurrentCaseException {
392 File subDirectory = Paths.get(getDefaultImageWriterFolder()).toFile();
393 if (!subDirectory.exists()) {
394 subDirectory.mkdirs();
397 String path = disk.getName();
401 path = path.replaceAll(
"[^0-9A-Za-z _()]",
"");
402 if (path.isEmpty() || path.startsWith(
" ")) {
403 path =
"localDisk" + path;
406 path +=
" " + System.currentTimeMillis();
408 pathTextField.setText(Paths.get(getDefaultImageWriterFolder(), path).toString());
411 private boolean imageWriterPathIsValid() {
412 if ((!copyImageCheckbox.isSelected()) || localDisk == null) {
413 imageWriterErrorLabel.setVisible(
false);
414 imageWriterErrorLabel.setText(
"");
418 if (pathTextField.getText().isEmpty()) {
419 imageWriterErrorLabel.setVisible(
true);
420 imageWriterErrorLabel.setText(Bundle.LocalDiskPanel_imageWriterError_emptyPath());
424 File f =
new File(pathTextField.getText());
425 if (((f.getParentFile() != null) && (!f.getParentFile().exists()))
426 || (f.getParentFile() == null)) {
427 imageWriterErrorLabel.setVisible(
true);
428 imageWriterErrorLabel.setText(Bundle.LocalDiskPanel_imageWriterError_directoryNotExist());
431 if (f.isDirectory()) {
432 imageWriterErrorLabel.setVisible(
true);
433 imageWriterErrorLabel.setText(Bundle.LocalDiskPanel_imageWriterError_isDirectory());
437 imageWriterErrorLabel.setVisible(
true);
438 imageWriterErrorLabel.setText(Bundle.LocalDiskPanel_imageWriterError_fileExists());
441 imageWriterErrorLabel.setVisible(
false);
442 imageWriterErrorLabel.setText(
"");
446 boolean getImageWriterEnabled() {
447 return copyImageCheckbox.isSelected();
450 ImageWriterSettings getImageWriterSettings() {
451 return new ImageWriterSettings(pathTextField.getText(), changeDatabasePathCheckbox.isSelected());
460 boolean validatePanel() {
461 if (!imageWriterPathIsValid()) {
471 public void createTimeZoneList() {
472 List<String> timeZoneList = TimeZoneUtils.createTimeZoneList();
473 for (String timeZone : timeZoneList) {
474 timeZoneComboBox.addItem(timeZone);
478 timeZoneComboBox.setSelectedItem(TimeZoneUtils.createTimeZoneString(Calendar.getInstance().getTimeZone()));
485 private void createSectorSizeList() {
486 for (String choice : SECTOR_SIZE_CHOICES) {
487 sectorSizeComboBox.addItem(choice);
489 sectorSizeComboBox.setSelectedIndex(0);