Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
UnpackagePortableCaseProgressDialog.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2019 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 java.awt.Color;
22import java.beans.PropertyChangeEvent;
23import java.beans.PropertyChangeListener;
24import java.io.BufferedReader;
25import java.io.File;
26import java.io.IOException;
27import java.io.InputStreamReader;
28import java.nio.file.Paths;
29import java.util.Map;
30import java.util.concurrent.atomic.AtomicBoolean;
31import java.util.logging.Level;
32import javax.swing.JFrame;
33import javax.swing.SwingWorker;
34import org.apache.commons.io.FilenameUtils;
35import org.apache.commons.lang3.StringUtils;
36import org.openide.modules.InstalledFileLocator;
37import org.openide.util.NbBundle;
38import org.openide.windows.WindowManager;
39import org.sleuthkit.autopsy.coreutils.Logger;
40import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
41import org.sleuthkit.autopsy.coreutils.ModuleSettings;
42import org.sleuthkit.autopsy.coreutils.PlatformUtil;
43import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
44import org.sleuthkit.datamodel.TskCoreException;
45
49@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
50class UnpackagePortableCaseProgressDialog extends javax.swing.JDialog implements PropertyChangeListener {
51
52 private UnpackageWorker worker;
53 private final static String CASES_OPENED_LOG_FILE = "portable_cases_opened"; //NON-NLS
54 private final static String PORTABLE_CASE_NAME = "portable_case_name"; //NON-NLS
55 private final static String PORTABLE_CASE_DIR = "portable_case_dir_opened"; //NON-NLS
56
60 @NbBundle.Messages({"UnpackagePortableCaseProgressDialog.title.text=Unpackage Portable Case Progress",})
61 UnpackagePortableCaseProgressDialog() {
62 super((JFrame) WindowManager.getDefault().getMainWindow(),
63 Bundle.UnpackagePortableCaseProgressDialog_title_text(),
64 true);
65 initComponents();
66 customizeComponents();
67 }
68
69 private void customizeComponents() {
70 cancelButton.setEnabled(true);
71 okButton.setEnabled(false);
72 progressBar.setIndeterminate(true);
73 resultLabel.setText(""); // NON-NLS
74 }
75
82 void unpackageCase(String packagedCase, String outputFolder) {
83
84 worker = new UnpackageWorker(packagedCase, outputFolder);
85 worker.addPropertyChangeListener(this);
86 worker.execute();
87
88 setLocationRelativeTo((JFrame) WindowManager.getDefault().getMainWindow());
89 this.setVisible(true);
90
91 }
92
98 boolean isSuccess() {
99 if (worker == null) {
100 return false;
101 } else {
102 return worker.isSuccess();
103 }
104 }
105
106 @NbBundle.Messages({"UnpackagePortableCaseProgressDialog.propertyChange.success=Successfully unpacked case",})
107 @Override
108 public void propertyChange(PropertyChangeEvent evt) {
109
110 if ("state".equals(evt.getPropertyName())
111 && (SwingWorker.StateValue.DONE.equals(evt.getNewValue()))) { // NON-NLS
112
113 // The worker is done processing
114 // Disable cancel button and enable ok
115 cancelButton.setEnabled(false);
116 okButton.setEnabled(true);
117
118 if (worker.isSuccess()) {
119 progressBar.setIndeterminate(false);
120 progressBar.setValue(progressBar.getMaximum());
121 resultLabel.setText(Bundle.UnpackagePortableCaseProgressDialog_propertyChange_success());
122 } else {
123 // If there was an error, reset the progress bar and display an error message
124 progressBar.setIndeterminate(false);
125 progressBar.setValue(0);
126 resultLabel.setForeground(Color.red);
127 resultLabel.setText(worker.getDisplayError());
128 }
129 }
130 }
131
135 private class UnpackageWorker extends SwingWorker<Void, Void> {
136
137 private final String packagedCase;
138 private final String outputFolder;
139
140 private final AtomicBoolean success = new AtomicBoolean();
141 private String lastError = "";
142
143 UnpackageWorker(String packagedCase, String outputFolder) {
144 this.packagedCase = packagedCase;
145 this.outputFolder = outputFolder;
146 this.success.set(false);
147 }
148
149 @NbBundle.Messages({
150 "UnpackageWorker.doInBackground.errorFinding7zip=Could not locate 7-Zip executable",
151 "UnpackageWorker.doInBackground.errorCompressingCase=Error unpackaging case",
152 "UnpackageWorker.doInBackground.canceled=Unpackaging canceled by user",
153 "UnpackageWorker.doInBackground.previouslySeenCase=Case has been previously opened. Open it again?",})
154 @Override
155 protected Void doInBackground() throws Exception {
156
157 // Check to see if this case has been already opened before
158 String caseUnpackedBefore = getCaseIfUnpackedBefore(packagedCase);
159 if ((!caseUnpackedBefore.isEmpty())
160 && (MessageNotifyUtil.Message.confirm(Bundle.UnpackageWorker_doInBackground_previouslySeenCase()))) {
161 try {
162 Case.openAsCurrentCase(caseUnpackedBefore);
163 success.set(true);
164 return null;
165 } catch (CaseActionException ex) {
166 throw new TskCoreException("Error opening case after unpacking it.", ex); // NON-NLS
167 }
168 }
169 // Find 7-Zip
170 File sevenZipExe = locate7ZipExecutable();
171 if (sevenZipExe == null) {
172 setDisplayError(Bundle.UnpackageWorker_doInBackground_errorFinding7zip());
173 throw new TskCoreException("Error finding 7-Zip executable"); // NON-NLS
174 }
175
176 String outputFolderSwitch = "-o" + outputFolder; // NON-NLS
177 ProcessBuilder procBuilder = new ProcessBuilder();
178 procBuilder.command(
179 sevenZipExe.getAbsolutePath(),
180 "x", // Extract
182 outputFolderSwitch
183 );
184
185 try {
186 Process process = procBuilder.start();
187
188 while (process.isAlive()) {
189 if (this.isCancelled()) {
190 setDisplayError(Bundle.UnpackageWorker_doInBackground_canceled());
191 return null;
192 }
193 Thread.sleep(200);
194 }
195
196 int exitCode = process.exitValue();
197 if (exitCode != 0) {
198 // Save any errors so they can be logged
199 StringBuilder sb = new StringBuilder();
200 try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
201 String line;
202 while ((line = br.readLine()) != null) {
203 sb.append(line).append(System.getProperty("line.separator")); // NON-NLS
204 }
205 }
206
207 setDisplayError(Bundle.UnpackageWorker_doInBackground_errorCompressingCase());
208 throw new TskCoreException("Error unpackaging case. 7-Zip output: " + sb.toString()); // NON-NLS
209 }
210 } catch (IOException | InterruptedException ex) {
211 setDisplayError(Bundle.UnpackageWorker_doInBackground_errorCompressingCase());
212 throw new TskCoreException("Error unpackaging case", ex); // NON-NLS
213 }
214
215 try {
216 String caseFileDirectory = FilenameUtils.getBaseName(packagedCase);
217 String caseDirectory = StringUtils.substringBefore(caseFileDirectory, ".zip");
218 String caseFileToOpen = outputFolder + File.separator + caseDirectory + File.separator + caseDirectory + ".aut";
219 Case.openAsCurrentCase(caseFileToOpen); // NON-NLS
220 String timestampFileOpened = TimeStampUtils.createTimeStamp();
221 if (ModuleSettings.configExists(CASES_OPENED_LOG_FILE)) {
222 ModuleSettings.setConfigSetting(CASES_OPENED_LOG_FILE, timestampFileOpened + "-" + PORTABLE_CASE_NAME, packagedCase);
223 ModuleSettings.setConfigSetting(CASES_OPENED_LOG_FILE, timestampFileOpened + "-" + PORTABLE_CASE_DIR, caseFileToOpen);
224 } else {
225 ModuleSettings.makeConfigFile(CASES_OPENED_LOG_FILE);
226 ModuleSettings.setConfigSetting(CASES_OPENED_LOG_FILE, timestampFileOpened + "-" + PORTABLE_CASE_NAME, packagedCase);
227 ModuleSettings.setConfigSetting(CASES_OPENED_LOG_FILE, timestampFileOpened + "-" + PORTABLE_CASE_DIR, caseFileToOpen);
228 }
229 } catch (CaseActionException ex) {
230 throw new TskCoreException("Error opening case after unpacking it.", ex); // NON-NLS
231 }
232
233 success.set(true);
234
235 return null;
236 }
237
238 @Override
239 synchronized protected void done() {
240 if (this.isCancelled()) {
241 return;
242 }
243
244 try {
245 get();
246 } catch (Exception ex) {
247 Logger.getLogger(UnpackagePortableCaseProgressDialog.class.getName()).log(Level.SEVERE, "Error unpackaging portable case", ex); // NON-NLS
248 }
249 }
250
256 private synchronized void setDisplayError(String errorStr) {
257 lastError = errorStr;
258 }
259
265 private synchronized String getDisplayError() {
266 return lastError;
267 }
268
269 protected boolean isSuccess() {
270 return success.get();
271 }
272
278 private File locate7ZipExecutable() {
279 if (!PlatformUtil.isWindowsOS()) {
280 return null;
281 }
282
283 String executableToFindName = Paths.get("7-Zip", "7z.exe").toString(); // NON-NLS
284 File exeFile = InstalledFileLocator.getDefault().locate(executableToFindName, UnpackagePortableCaseProgressDialog.class.getPackage().getName(), false);
285 if (null == exeFile) {
286 return null;
287 }
288
289 if (!exeFile.canExecute()) {
290 return null;
291 }
292
293 return exeFile;
294 }
295
299 private String getCaseIfUnpackedBefore(String packedCaseName) {
300 if (!ModuleSettings.configExists(CASES_OPENED_LOG_FILE)) {
301 return "";
302 }
303
304 Map<String, String> configEntries = ModuleSettings.getConfigSettings(CASES_OPENED_LOG_FILE);
305
306 for (Map.Entry<String, String> entries : configEntries.entrySet()) {
307 if (entries.getValue().contains(packedCaseName)) {
308 String entryFound = entries.getKey().substring(0, entries.getKey().indexOf('-'));
309 String caseFileName = ModuleSettings.getConfigSetting(CASES_OPENED_LOG_FILE, entryFound + "-" + PORTABLE_CASE_DIR);
310 File caseFile = new File(caseFileName);
311 if (caseFile.exists()) {
312 return caseFileName;
313 } else {
314 return "";
315 }
316 }
317 }
318
319 return "";
320 }
321
322 }
323
329 @SuppressWarnings("unchecked")
330 // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
331 private void initComponents() {
332
333 progressBar = new javax.swing.JProgressBar();
334 cancelButton = new javax.swing.JButton();
335 okButton = new javax.swing.JButton();
336 resultLabel = new javax.swing.JLabel();
337
338 setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
339
340 org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(UnpackagePortableCaseProgressDialog.class, "UnpackagePortableCaseProgressDialog.cancelButton.text")); // NOI18N
341 cancelButton.addActionListener(new java.awt.event.ActionListener() {
342 public void actionPerformed(java.awt.event.ActionEvent evt) {
343 cancelButtonActionPerformed(evt);
344 }
345 });
346
347 org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(UnpackagePortableCaseProgressDialog.class, "UnpackagePortableCaseProgressDialog.okButton.text")); // NOI18N
348 okButton.addActionListener(new java.awt.event.ActionListener() {
349 public void actionPerformed(java.awt.event.ActionEvent evt) {
350 okButtonActionPerformed(evt);
351 }
352 });
353
354 org.openide.awt.Mnemonics.setLocalizedText(resultLabel, org.openide.util.NbBundle.getMessage(UnpackagePortableCaseProgressDialog.class, "UnpackagePortableCaseProgressDialog.resultLabel.text")); // NOI18N
355
356 javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
357 getContentPane().setLayout(layout);
358 layout.setHorizontalGroup(
359 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
360 .addGroup(layout.createSequentialGroup()
361 .addContainerGap()
362 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
363 .addComponent(progressBar, javax.swing.GroupLayout.DEFAULT_SIZE, 409, Short.MAX_VALUE)
364 .addGroup(layout.createSequentialGroup()
365 .addComponent(resultLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
366 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
367 .addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE)
368 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
369 .addComponent(cancelButton)))
370 .addContainerGap())
371 );
372 layout.setVerticalGroup(
373 layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
374 .addGroup(layout.createSequentialGroup()
375 .addContainerGap()
376 .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
377 .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
378 .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
379 .addComponent(cancelButton)
380 .addComponent(okButton)
381 .addComponent(resultLabel))
382 .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
383 );
384
385 pack();
386 }// </editor-fold>//GEN-END:initComponents
387
388 private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
389 worker.cancel(true);
390 dispose();
391 }//GEN-LAST:event_cancelButtonActionPerformed
392
393 private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
394 dispose();
395 }//GEN-LAST:event_okButtonActionPerformed
396
397 // Variables declaration - do not modify//GEN-BEGIN:variables
398 private javax.swing.JButton cancelButton;
399 private javax.swing.JButton okButton;
400 private javax.swing.JProgressBar progressBar;
401 private javax.swing.JLabel resultLabel;
402 // End of variables declaration//GEN-END:variables
403}
static void openAsCurrentCase(String caseMetadataFilePath)
Definition Case.java:856
synchronized static Logger getLogger(String name)
Definition Logger.java:124
static synchronized void setConfigSetting(String moduleName, String settingName, String settingVal)
static synchronized Map< String, String > getConfigSettings(String moduleName)
static synchronized boolean configExists(String moduleName)
static synchronized String getConfigSetting(String moduleName, String settingName)
static synchronized boolean makeConfigFile(String moduleName)

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