Autopsy  3.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
Case.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2015 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.casemodule;
20 
21 import java.awt.Frame;
22 import java.beans.PropertyChangeListener;
23 import java.beans.PropertyChangeSupport;
24 import java.io.BufferedInputStream;
25 import java.io.File;
26 import java.io.FileInputStream;
27 import java.io.IOException;
28 import java.text.DateFormat;
29 import java.text.SimpleDateFormat;
30 import java.util.GregorianCalendar;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.TimeZone;
37 import java.util.logging.Level;
38 import javax.swing.JOptionPane;
39 import javax.swing.SwingUtilities;
40 import org.openide.util.Lookup;
41 import org.openide.util.NbBundle;
42 import org.openide.util.actions.CallableSystemAction;
43 import org.openide.util.actions.SystemAction;
44 import org.openide.windows.WindowManager;
52 import org.sleuthkit.datamodel.*;
54 
60 @SuppressWarnings("deprecation") // TODO: Remove this when ErrorObserver is replaced.
61 public class Case implements SleuthkitCase.ErrorObserver {
62 
63  private static final String autopsyVer = Version.getVersion(); // current version of autopsy. Change it when the version is changed
64  private static String appName = null;
65 
70  public static final String propStartup = "LBL_StartupDialog"; //NON-NLS
71  // pcs is initialized in CaseListener constructor
72  private static final PropertyChangeSupport pcs = new PropertyChangeSupport(Case.class);
73 
78  public enum Events {
79 
87  // @@@ BC: I propose that this is no longer called for case open/close.
130  };
131 
132  private String name;
133  private String number;
134  private String examiner;
135  private String configFilePath;
136  private final XMLCaseManagement xmlcm;
137  private final SleuthkitCase db;
138  // Track the current case (only set with changeCase() method)
139  private static Case currentCase = null;
140  private final Services services;
141  private static final Logger logger = Logger.getLogger(Case.class.getName());
142  static final String CASE_EXTENSION = "aut"; //NON-NLS
143  static final String CASE_DOT_EXTENSION = "." + CASE_EXTENSION;
144 
145  // we cache if the case has data in it yet since a few places ask for it and we dont' need to keep going to DB
146  private boolean hasData = false;
147 
151  private Case(String name, String number, String examiner, String configFilePath, XMLCaseManagement xmlcm, SleuthkitCase db) {
152  this.name = name;
153  this.number = number;
154  this.examiner = examiner;
155  this.configFilePath = configFilePath;
156  this.xmlcm = xmlcm;
157  this.db = db;
158  this.services = new Services(db);
159  }
160 
165  private void init() {
166  db.addErrorObserver(this);
167  }
168 
176  public static Case getCurrentCase() {
177  if (currentCase != null) {
178  return currentCase;
179  } else {
180  throw new IllegalStateException(NbBundle.getMessage(Case.class, "Case.getCurCase.exception.noneOpen"));
181  }
182  }
183 
189  public static boolean isCaseOpen() {
190  return currentCase != null;
191  }
192 
200  private static void changeCase(Case newCase) {
201 
202  // close the existing case
203  Case oldCase = Case.currentCase;
204  Case.currentCase = null;
205  if (oldCase != null) {
206  doCaseChange(null); //closes windows, etc
207 
208  try {
209  pcs.firePropertyChange(Events.CURRENT_CASE.toString(), oldCase, null);
210  } catch (Exception e) {
211  logger.log(Level.SEVERE, "Case listener threw exception", e); //NON-NLS
212  MessageNotifyUtil.Notify.show(NbBundle.getMessage(Case.class, "Case.moduleErr"),
213  NbBundle.getMessage(Case.class,
214  "Case.changeCase.errListenToCaseUpdates.msg"),
216  }
217  doCaseNameChange("");
218 
219  try {
220  pcs.firePropertyChange(Events.NAME.toString(), oldCase.name, "");
221  } catch (Exception e) {
222  logger.log(Level.SEVERE, "Case listener threw exception", e); //NON-NLS
223  MessageNotifyUtil.Notify.show(NbBundle.getMessage(Case.class, "Case.moduleErr"),
224  NbBundle.getMessage(Case.class,
225  "Case.changeCase.errListenToCaseUpdates.msg"),
227  }
228  }
229 
230  if (newCase != null) {
231  currentCase = newCase;
232 
234 
235  try {
236  pcs.firePropertyChange(Events.CURRENT_CASE.toString(), null, currentCase);
237  } catch (Exception e) {
238  logger.log(Level.SEVERE, "Case listener threw exception", e); //NON-NLS
239  MessageNotifyUtil.Notify.show(NbBundle.getMessage(Case.class, "Case.moduleErr"),
240  NbBundle.getMessage(Case.class,
241  "Case.changeCase.errListenToCaseUpdates.msg"),
243  }
244  doCaseChange(currentCase);
245 
246  try {
247  pcs.firePropertyChange(Events.NAME.toString(), "", currentCase.name);
248  } catch (Exception e) {
249  logger.log(Level.SEVERE, "Case threw exception", e); //NON-NLS
250  MessageNotifyUtil.Notify.show(NbBundle.getMessage(Case.class, "Case.moduleErr"),
251  NbBundle.getMessage(Case.class,
252  "Case.changeCase.errListenToCaseUpdates.msg"),
254  }
255  doCaseNameChange(currentCase.name);
256 
257  RecentCases.getInstance().addRecentCase(currentCase.name, currentCase.configFilePath); // update the recent cases
258  } else {
260  }
261  }
262 
263  AddImageProcess makeAddImageProcess(String timezone, boolean processUnallocSpace, boolean noFatOrphans) {
264  return this.db.makeAddImageProcess(timezone, processUnallocSpace, noFatOrphans);
265  }
266 
277  public static void create(String caseDir, String caseName, String caseNumber, String examiner) throws CaseActionException {
278  logger.log(Level.INFO, "Creating new case.\ncaseDir: {0}\ncaseName: {1}", new Object[]{caseDir, caseName}); //NON-NLS
279 
280  // create case directory if it doesn't already exist.
281  if (new File(caseDir).exists() == false) {
282  Case.createCaseDirectory(caseDir);
283  }
284 
285  String configFilePath = caseDir + File.separator + caseName + CASE_DOT_EXTENSION;
286 
287  XMLCaseManagement xmlcm = new XMLCaseManagement();
288  xmlcm.create(caseDir, caseName, examiner, caseNumber); // create a new XML config file
289  xmlcm.writeFile();
290 
291  String dbPath = caseDir + File.separator + "autopsy.db"; //NON-NLS
292  SleuthkitCase db = null;
293  try {
294  db = SleuthkitCase.newCase(dbPath);
295  } catch (TskCoreException ex) {
296  logger.log(Level.SEVERE, "Error creating a case: " + caseName + " in dir " + caseDir, ex); //NON-NLS
297  throw new CaseActionException(
298  NbBundle.getMessage(Case.class, "Case.create.exception.msg", caseName, caseDir), ex);
299  }
300 
305  Case newCase = new Case(caseName, caseNumber, examiner, configFilePath, xmlcm, db);
306  newCase.init();
307 
308  changeCase(newCase);
309  }
310 
318  public static void open(String configFilePath) throws CaseActionException {
319  logger.log(Level.INFO, "Opening case.\nconfigFilePath: {0}", configFilePath); //NON-NLS
320 
321  try {
322  XMLCaseManagement xmlcm = new XMLCaseManagement();
323 
324  xmlcm.open(configFilePath); // open and load the config file to the document handler in the XML class
325  xmlcm.writeFile(); // write any changes to the config file
326 
327  String caseName = xmlcm.getCaseName();
328  String caseNumber = xmlcm.getCaseNumber();
329  String examiner = xmlcm.getCaseExaminer();
330  // if the caseName is "", case / config file can't be opened
331  if (caseName.equals("")) {
332  throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.open.exception.blankCase.msg"));
333  }
334 
335  String caseDir = xmlcm.getCaseDirectory();
336  String dbPath = caseDir + File.separator + "autopsy.db"; //NON-NLS
337  SleuthkitCase db = SleuthkitCase.openCase(dbPath);
338  if (null != db.getBackupDatabasePath()) {
339  JOptionPane.showMessageDialog(null,
340  NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.msg",
341  db.getBackupDatabasePath()),
342  NbBundle.getMessage(Case.class, "Case.open.msgDlg.updated.title"),
343  JOptionPane.INFORMATION_MESSAGE);
344  }
345 
346  checkImagesExist(db);
347 
352  Case openedCase = new Case(caseName, caseNumber, examiner, configFilePath, xmlcm, db);
353  openedCase.init();
354 
355  changeCase(openedCase);
356 
357  } catch (Exception ex) {
358  logger.log(Level.SEVERE, "Error opening the case: ", ex); //NON-NLS
359  // close the previous case if there's any
360  CaseCloseAction closeCase = SystemAction.get(CaseCloseAction.class);
361  closeCase.actionPerformed(null);
362  if (!configFilePath.endsWith(CASE_DOT_EXTENSION)) {
363  throw new CaseActionException(
364  NbBundle.getMessage(Case.class, "Case.open.exception.checkFile.msg", CASE_DOT_EXTENSION), ex);
365  } else {
366  throw new CaseActionException(NbBundle.getMessage(Case.class, "Case.open.exception.gen.msg") + ". " + ex.getMessage(), ex);
367  }
368  }
369  }
370 
371  static Map<Long, String> getImagePaths(SleuthkitCase db) { //TODO: clean this up
372  Map<Long, String> imgPaths = new HashMap<>();
373  try {
374  Map<Long, List<String>> imgPathsList = db.getImagePaths();
375  for (Map.Entry<Long, List<String>> entry : imgPathsList.entrySet()) {
376  if (entry.getValue().size() > 0) {
377  imgPaths.put(entry.getKey(), entry.getValue().get(0));
378  }
379  }
380  } catch (TskException ex) {
381  logger.log(Level.WARNING, "Error getting image paths", ex); //NON-NLS
382  }
383  return imgPaths;
384  }
385 
389  private static void checkImagesExist(SleuthkitCase db) {
390  Map<Long, String> imgPaths = getImagePaths(db);
391  for (Map.Entry<Long, String> entry : imgPaths.entrySet()) {
392  long obj_id = entry.getKey();
393  String path = entry.getValue();
394  boolean fileExists = (pathExists(path)
395  || driveExists(path));
396  if (!fileExists) {
397  int ret = JOptionPane.showConfirmDialog(null,
398  NbBundle.getMessage(Case.class,
399  "Case.checkImgExist.confDlg.doesntExist.msg",
400  appName, path),
401  NbBundle.getMessage(Case.class,
402  "Case.checkImgExist.confDlg.doesntExist.title"),
403  JOptionPane.YES_NO_OPTION);
404  if (ret == JOptionPane.YES_OPTION) {
405 
406  MissingImageDialog.makeDialog(obj_id, db);
407 
408  } else {
409  logger.log(Level.WARNING, "Selected image files don't match old files!"); //NON-NLS
410  }
411 
412  }
413  }
414  }
415 
424  @Deprecated
425  public Image addImage(String imgPath, long imgId, String timeZone) throws CaseActionException {
426  logger.log(Level.INFO, "Adding image to Case. imgPath: {0} ID: {1} TimeZone: {2}", new Object[]{imgPath, imgId, timeZone}); //NON-NLS
427 
428  try {
429  Image newImage = db.getImageById(imgId);
430 
431  try {
432  pcs.firePropertyChange(Events.DATA_SOURCE_ADDED.toString(), null, newImage); // the new value is the instance of the image
433  } catch (Exception e) {
434  logger.log(Level.SEVERE, "Case listener threw exception", e); //NON-NLS
435  MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "Case.moduleErr"),
436  NbBundle.getMessage(this.getClass(),
437  "Case.changeCase.errListenToCaseUpdates.msg"),
439  }
441  return newImage;
442  } catch (Exception ex) {
443  throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.addImg.exception.msg"), ex);
444  }
445  }
446 
453  @Deprecated
454  void addLocalDataSource(Content newDataSource) {
455 
456  notifyNewDataSource(newDataSource);
457  }
458 
465  void notifyNewDataSource(Content newDataSource) {
466 
467  try {
468  pcs.firePropertyChange(Events.DATA_SOURCE_ADDED.toString(), null, newDataSource);
469  } catch (Exception e) {
470  logger.log(Level.SEVERE, "Case threw exception", e); //NON-NLS
471  MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "Case.moduleErr"),
472  NbBundle.getMessage(this.getClass(),
473  "Case.changeCase.errListenToCaseUpdates.msg"),
474  MessageNotifyUtil.MessageType.ERROR);
475  }
476  CoreComponentControl.openCoreWindows();
477  }
478 
483  return services;
484  }
485 
493  return this.db;
494  }
495 
499  public void closeCase() throws CaseActionException {
500  changeCase(null);
501 
502  try {
503  services.close();
504  this.xmlcm.close(); // close the xmlcm
505  this.db.close();
506  } catch (Exception e) {
507  throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.closeCase.exception.msg"), e);
508  }
509  }
510 
518  void deleteCase(File caseDir) throws CaseActionException {
519  logger.log(Level.INFO, "Deleting case.\ncaseDir: {0}", caseDir); //NON-NLS
520 
521  try {
522 
523  xmlcm.close(); // close the xmlcm
524  boolean result = deleteCaseDirectory(caseDir); // delete the directory
525 
526  RecentCases.getInstance().removeRecentCase(this.name, this.configFilePath); // remove it from the recent case
527  Case.changeCase(null);
528  if (result == false) {
529  throw new CaseActionException(
530  NbBundle.getMessage(this.getClass(), "Case.deleteCase.exception.msg", caseDir));
531  }
532  } catch (Exception ex) {
533  logger.log(Level.SEVERE, "Error deleting the current case dir: " + caseDir, ex); //NON-NLS
534  throw new CaseActionException(
535  NbBundle.getMessage(this.getClass(), "Case.deleteCase.exception.msg2", caseDir), ex);
536  }
537  }
538 
547  void updateCaseName(String oldCaseName, String oldPath, String newCaseName, String newPath) throws CaseActionException {
548  try {
549  xmlcm.setCaseName(newCaseName); // set the case
550  name = newCaseName; // change the local value
551  RecentCases.getInstance().updateRecentCase(oldCaseName, oldPath, newCaseName, newPath); // update the recent case
552  try {
553  pcs.firePropertyChange(Events.NAME.toString(), oldCaseName, newCaseName);
554  } catch (Exception e) {
555  logger.log(Level.SEVERE, "Case listener threw exception", e); //NON-NLS
556  MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "Case.moduleErr"),
557  NbBundle.getMessage(this.getClass(),
558  "Case.changeCase.errListenToCaseUpdates.msg"),
559  MessageNotifyUtil.MessageType.ERROR);
560  }
561  doCaseNameChange(newCaseName);
562 
563  } catch (Exception e) {
564  throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.updateCaseName.exception.msg"), e);
565  }
566  }
567 
574  void updateExaminer(String oldExaminer, String newExaminer) throws CaseActionException {
575  try {
576  xmlcm.setCaseExaminer(newExaminer); // set the examiner
577  examiner = newExaminer;
578  try {
579  pcs.firePropertyChange(Events.EXAMINER.toString(), oldExaminer, newExaminer);
580  } catch (Exception e) {
581  logger.log(Level.SEVERE, "Case listener threw exception", e); //NON-NLS
582  MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "Case.moduleErr"),
583  NbBundle.getMessage(this.getClass(),
584  "Case.changeCase.errListenToCaseUpdates.msg"),
585  MessageNotifyUtil.MessageType.ERROR);
586  }
587  } catch (Exception e) {
588  throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.updateExaminer.exception.msg"), e);
589  }
590  }
591 
598  void updateCaseNumber(String oldCaseNumber, String newCaseNumber) throws CaseActionException {
599  try {
600  xmlcm.setCaseNumber(newCaseNumber); // set the case number
601  number = newCaseNumber;
602 
603  try {
604  pcs.firePropertyChange(Events.NUMBER.toString(), oldCaseNumber, newCaseNumber);
605  } catch (Exception e) {
606  logger.log(Level.SEVERE, "Case listener threw exception", e); //NON-NLS
607  MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "Case.moduleErr"),
608  NbBundle.getMessage(this.getClass(),
609  "Case.changeCase.errListenToCaseUpdates.msg"),
610  MessageNotifyUtil.MessageType.ERROR);
611  }
612  } catch (Exception e) {
613  throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.updateCaseNum.exception.msg"), e);
614  }
615  }
616 
622  public static boolean existsCurrentCase() {
623  return currentCase != null;
624  }
625 
631  private void setConfigFilePath(String givenPath) {
632  configFilePath = givenPath;
633  }
634 
640  String getConfigFilePath() {
641  return configFilePath;
642  }
643 
649  public static String getAutopsyVersion() {
650  return autopsyVer;
651  }
652 
658  public static String getAppName() {
659  if ((appName == null) || appName.equals("")) {
660  appName = WindowManager.getDefault().getMainWindow().getTitle();
661  }
662  return appName;
663  }
664 
670  public String getName() {
671  return name;
672  }
673 
679  public String getNumber() {
680  return number;
681  }
682 
688  public String getExaminer() {
689  return examiner;
690  }
691 
697  public String getCaseDirectory() {
698  if (xmlcm == null) {
699  return "";
700  } else {
701  return xmlcm.getCaseDirectory();
702  }
703  }
704 
710  public String getTempDirectory() {
711  if (xmlcm == null) {
712  return "";
713  } else {
714  return xmlcm.getTempDir();
715  }
716  }
717 
723  public String getCacheDirectory() {
724  if (xmlcm == null) {
725  return "";
726  } else {
727  return xmlcm.getCacheDir();
728  }
729  }
730 
736  public String getExportDirectory() {
737  if (xmlcm == null) {
738  return "";
739  } else {
740  return xmlcm.getExportDir();
741  }
742  }
743 
749  public String getLogDirectoryPath() {
750  if (xmlcm == null) {
751  return "";
752  } else {
753  return xmlcm.getLogDir();
754  }
755  }
756 
762  public String getCreatedDate() {
763  if (xmlcm == null) {
764  return "";
765  } else {
766  return xmlcm.getCreatedDate();
767  }
768  }
769 
776  public String getModulesOutputDirAbsPath() {
777  return this.getCaseDirectory() + File.separator + getModulesOutputDirRelPath();
778  }
779 
787  public static String getModulesOutputDirRelPath() {
788  return "ModuleOutput"; //NON-NLS
789  }
790 
796  public static PropertyChangeSupport getPropertyChangeSupport() {
797  return pcs;
798  }
799 
806  public List<Content> getDataSources() throws TskCoreException {
807  List<Content> list = db.getRootObjects();
808  hasData = (list.size() > 0);
809  return list;
810  }
811 
817  public Set<TimeZone> getTimeZone() {
818  Set<TimeZone> timezones = new HashSet<>();
819  try {
820  for (Content c : getDataSources()) {
821  final Content dataSource = c.getDataSource();
822  if ((dataSource != null) && (dataSource instanceof Image)) {
823  Image image = (Image) dataSource;
824  timezones.add(TimeZone.getTimeZone(image.getTimeZone()));
825  }
826  }
827  } catch (TskCoreException ex) {
828  logger.log(Level.INFO, "Error getting time zones", ex); //NON-NLS
829  }
830  return timezones;
831  }
832 
833  public static synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
834  pcs.addPropertyChangeListener(listener);
835  }
836 
837  public static synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
838  pcs.removePropertyChangeListener(listener);
839  }
840 
848  public static boolean pathExists(String imgPath) {
849  return new File(imgPath).isFile();
850  }
854  private static final String pdisk = "\\\\.\\physicaldrive"; //NON-NLS
855  private static final String dev = "/dev/"; //NON-NLS
856 
857  static boolean isPhysicalDrive(String path) {
858  return path.toLowerCase().startsWith(pdisk)
859  || path.toLowerCase().startsWith(dev);
860  }
861 
865  static boolean isPartition(String path) {
866  return path.toLowerCase().startsWith("\\\\.\\")
867  && path.toLowerCase().endsWith(":");
868  }
869 
877  static boolean driveExists(String path) {
878  // Test the drive by reading the first byte and checking if it's -1
879  BufferedInputStream br = null;
880  try {
881  File tmp = new File(path);
882  br = new BufferedInputStream(new FileInputStream(tmp));
883  int b = br.read();
884  return b != -1;
885  } catch (Exception ex) {
886  return false;
887  } finally {
888  try {
889  if (br != null) {
890  br.close();
891  }
892  } catch (IOException ex) {
893  }
894  }
895  }
896 
906  public static String convertTimeZone(String timezoneID) {
907 
908  TimeZone zone = TimeZone.getTimeZone(timezoneID);
909  int offset = zone.getRawOffset() / 1000;
910  int hour = offset / 3600;
911  int min = (offset % 3600) / 60;
912 
913  DateFormat dfm = new SimpleDateFormat("z");
914  dfm.setTimeZone(zone);
915  boolean hasDaylight = zone.useDaylightTime();
916  String first = dfm.format(new GregorianCalendar(2010, 1, 1).getTime()).substring(0, 3); // make it only 3 letters code
917  String second = dfm.format(new GregorianCalendar(2011, 6, 6).getTime()).substring(0, 3); // make it only 3 letters code
918  int mid = hour * -1;
919  String result = first + Integer.toString(mid);
920  if (min != 0) {
921  result = result + ":" + Integer.toString(min);
922  }
923  if (hasDaylight) {
924  result = result + second;
925  }
926 
927  return result;
928  }
929 
930  /*
931  * The methods below are used to manage the case directories (creating,
932  * checking, deleting, etc)
933  */
943  static void createCaseDirectory(String caseDir, String caseName) throws CaseActionException {
944  createCaseDirectory(caseDir);
945 
946  }
947 
955  static void createCaseDirectory(String caseDir) throws CaseActionException {
956 
957  File caseDirF = new File(caseDir);
958  if (caseDirF.exists()) {
959  if (caseDirF.isFile()) {
960  throw new CaseActionException(
961  NbBundle.getMessage(Case.class, "Case.createCaseDir.exception.existNotDir", caseDir));
962  } else if (!caseDirF.canRead() || !caseDirF.canWrite()) {
963  throw new CaseActionException(
964  NbBundle.getMessage(Case.class, "Case.createCaseDir.exception.existCantRW", caseDir));
965  }
966  }
967 
968  try {
969  boolean result = (caseDirF).mkdirs(); // create root case Directory
970  if (result == false) {
971  throw new CaseActionException(
972  NbBundle.getMessage(Case.class, "Case.createCaseDir.exception.cantCreate", caseDir));
973  }
974 
975  // create the folders inside the case directory
976  result = result && (new File(caseDir + File.separator + XMLCaseManagement.EXPORT_FOLDER_RELPATH)).mkdir()
977  && (new File(caseDir + File.separator + XMLCaseManagement.LOG_FOLDER_RELPATH)).mkdir()
978  && (new File(caseDir + File.separator + XMLCaseManagement.TEMP_FOLDER_RELPATH)).mkdir()
979  && (new File(caseDir + File.separator + XMLCaseManagement.CACHE_FOLDER_RELPATH)).mkdir();
980 
981  if (result == false) {
982  throw new CaseActionException(
983  NbBundle.getMessage(Case.class, "Case.createCaseDir.exception.cantCreateCaseDir", caseDir));
984  }
985 
986  final String modulesOutDir = caseDir + File.separator + getModulesOutputDirRelPath();
987  result = new File(modulesOutDir).mkdir();
988  if (result == false) {
989  throw new CaseActionException(
990  NbBundle.getMessage(Case.class, "Case.createCaseDir.exception.cantCreateModDir",
991  modulesOutDir));
992  }
993 
994  } catch (Exception e) {
995  throw new CaseActionException(
996  NbBundle.getMessage(Case.class, "Case.createCaseDir.exception.gen", caseDir), e);
997  }
998  }
999 
1007  static boolean deleteCaseDirectory(File casePath) {
1008  logger.log(Level.INFO, "Deleting case directory: {0}", casePath.getAbsolutePath()); //NON-NLS
1009  return FileUtil.deleteDir(casePath);
1010  }
1011 
1015  static public void invokeStartupDialog() {
1017  }
1018 
1023  private static void runAddImageAction() {
1024  SwingUtilities.invokeLater(new Runnable() {
1025  @Override
1026  public void run() {
1027  final AddImageAction action = Lookup.getDefault().lookup(AddImageAction.class);
1028  action.actionPerformed(null);
1029  }
1030  });
1031  }
1032 
1040  static public boolean isValidName(String caseName) {
1041  return !(caseName.contains("\\") || caseName.contains("/") || caseName.contains(":")
1042  || caseName.contains("*") || caseName.contains("?") || caseName.contains("\"")
1043  || caseName.contains("<") || caseName.contains(">") || caseName.contains("|"));
1044  }
1045 
1046  static private void clearTempFolder() {
1047  File tempFolder = new File(currentCase.getTempDirectory());
1048  if (tempFolder.isDirectory()) {
1049  File[] files = tempFolder.listFiles();
1050  if (files.length > 0) {
1051  for (File file : files) {
1052  if (file.isDirectory()) {
1053  deleteCaseDirectory(file);
1054  } else {
1055  file.delete();
1056  }
1057  }
1058  }
1059  }
1060  }
1061 
1067  private static void checkSubFolders(Case openedCase) {
1068  String modulesOutputDir = openedCase.getModulesOutputDirAbsPath();
1069  File modulesOutputDirF = new File(modulesOutputDir);
1070  if (!modulesOutputDirF.exists()) {
1071  logger.log(Level.INFO, "Creating modules output dir for the case."); //NON-NLS
1072 
1073  try {
1074  if (!modulesOutputDirF.mkdir()) {
1075  logger.log(Level.SEVERE, "Error creating modules output dir for the case, dir: {0}", modulesOutputDir); //NON-NLS
1076  }
1077  } catch (SecurityException e) {
1078  logger.log(Level.SEVERE, "Error creating modules output dir for the case, dir: " + modulesOutputDir, e); //NON-NLS
1079  }
1080  }
1081  }
1082 
1083  //case change helper
1084  private static void doCaseChange(Case toChangeTo) {
1085  logger.log(Level.INFO, "Changing Case to: {0}", toChangeTo); //NON-NLS
1086  if (toChangeTo != null) { // new case is open
1087 
1088  // clear the temp folder when the case is created / opened
1090  checkSubFolders(toChangeTo);
1091 
1092  // enable these menus
1093  CallableSystemAction.get(AddImageAction.class).setEnabled(true);
1094  CallableSystemAction.get(CaseCloseAction.class).setEnabled(true);
1095  CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true);
1096  CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true); // Delete Case menu
1097 
1098  if (toChangeTo.hasData()) {
1099  // open all top components
1101  } else {
1102  // close all top components
1104  }
1105  } else { // case is closed
1106  // close all top components first
1108 
1109  // disable these menus
1110  CallableSystemAction.get(AddImageAction.class).setEnabled(false); // Add Image menu
1111  CallableSystemAction.get(CaseCloseAction.class).setEnabled(false); // Case Close menu
1112  CallableSystemAction.get(CasePropertiesAction.class).setEnabled(false); // Case Properties menu
1113  CallableSystemAction.get(CaseDeleteAction.class).setEnabled(false); // Delete Case menu
1114 
1115  //clear pending notifications
1117 
1118  Frame f = WindowManager.getDefault().getMainWindow();
1119  f.setTitle(Case.getAppName()); // set the window name to just application name
1120 
1121  //try to force gc to happen
1122  System.gc();
1123  System.gc();
1124  }
1125 
1126  //log memory usage after case changed
1127  logger.log(Level.INFO, PlatformUtil.getAllMemUsageInfo());
1128 
1129  }
1130 
1131  //case name change helper
1132  private static void doCaseNameChange(String newCaseName) {
1133  // update case name
1134  if (!newCaseName.equals("")) {
1135  Frame f = WindowManager.getDefault().getMainWindow();
1136  f.setTitle(newCaseName + " - " + Case.getAppName()); // set the window name to the new value
1137  }
1138  }
1139 
1140  //delete image helper
1141  private void doDeleteImage() {
1142  // no more image left in this case
1143  if (currentCase.hasData()) {
1144  // close all top components
1146  }
1147  }
1148 
1149  @Override
1150  public void receiveError(String context, String errorMessage) {
1151  MessageNotifyUtil.Notify.error(context, errorMessage);
1152  }
1153 
1165  public void addReport(String localPath, String srcModuleName, String reportName) throws TskCoreException {
1166  Report report = this.db.addReport(localPath, srcModuleName, reportName);
1167  try {
1168  Case.pcs.firePropertyChange(Events.REPORT_ADDED.toString(), null, report);
1169  } catch (Exception ex) {
1170  String errorMessage = String.format("A Case %s listener threw an exception", Events.REPORT_ADDED.toString()); //NON-NLS
1171  logger.log(Level.SEVERE, errorMessage, ex);
1172  }
1173  }
1174 
1175  public List<Report> getAllReports() throws TskCoreException {
1176  return this.db.getAllReports();
1177  }
1178 
1184  public boolean hasData() {
1185  // false is also the initial value, so make the DB trip if it is still false
1186  if (!hasData) {
1187  try {
1188  hasData = (getDataSources().size() > 0);
1189  } catch (TskCoreException ex) {
1190  }
1191  }
1192  return hasData;
1193  }
1194 }
List< Content > getDataSources()
Definition: Case.java:806
static String convertTimeZone(String timezoneID)
Definition: Case.java:906
static final PropertyChangeSupport pcs
Definition: Case.java:72
AddImageProcess makeAddImageProcess(String timezone, boolean processUnallocSpace, boolean noFatFsOrphans)
Case(String name, String number, String examiner, String configFilePath, XMLCaseManagement xmlcm, SleuthkitCase db)
Definition: Case.java:151
Image addImage(String imgPath, long imgId, String timeZone)
Definition: Case.java:425
void addErrorObserver(ErrorObserver observer)
static void doCaseNameChange(String newCaseName)
Definition: Case.java:1132
static boolean existsCurrentCase()
Definition: Case.java:622
static void open(String configFilePath)
Definition: Case.java:318
static void setLogDirectory(String directoryPath)
Definition: Logger.java:108
void setConfigFilePath(String givenPath)
Definition: Case.java:631
void addReport(String localPath, String srcModuleName, String reportName)
Definition: Case.java:1165
Map< Long, List< String > > getImagePaths()
static void changeCase(Case newCase)
Definition: Case.java:200
static boolean isValidName(String caseName)
Definition: Case.java:1040
static String getModulesOutputDirRelPath()
Definition: Case.java:787
static void checkSubFolders(Case openedCase)
Definition: Case.java:1067
static PropertyChangeSupport getPropertyChangeSupport()
Definition: Case.java:796
Report addReport(String localPath, String sourceModuleName, String reportName)
static void checkImagesExist(SleuthkitCase db)
Definition: Case.java:389
static synchronized void removePropertyChangeListener(PropertyChangeListener listener)
Definition: Case.java:837
static boolean pathExists(String imgPath)
Definition: Case.java:848
final XMLCaseManagement xmlcm
Definition: Case.java:136
static synchronized void addPropertyChangeListener(PropertyChangeListener listener)
Definition: Case.java:833
static void create(String caseDir, String caseName, String caseNumber, String examiner)
Definition: Case.java:277
static void show(String title, String message, MessageType type, ActionListener actionListener)
static SleuthkitCase openCase(String dbPath)
static SleuthkitCase newCase(String dbPath)
void receiveError(String context, String errorMessage)
Definition: Case.java:1150
static Logger getLogger(String name)
Definition: Logger.java:131
static void doCaseChange(Case toChangeTo)
Definition: Case.java:1084

Copyright © 2012-2015 Basis Technology. Generated on: Mon Oct 19 2015
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.