1 /*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2011-2016 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.Cursor;
22 import java.awt.Frame;
23 import java.beans.PropertyChangeListener;
24 import java.beans.PropertyChangeSupport;
25 import java.io.File;
26 import java.nio.file.InvalidPathException;
27 import java.nio.file.Path;
28 import java.nio.file.Paths;
29 import java.text.SimpleDateFormat;
30 import java.util.Collection;
31 import java.util.Date;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Set;
37 import java.util.TimeZone;
38 import java.util.UUID;
39 import java.util.logging.Level;
40 import java.util.stream.Collectors;
41 import java.util.stream.Stream;
42 import javax.swing.JOptionPane;
43 import javax.swing.SwingUtilities;
44 import org.openide.util.NbBundle;
45 import org.openide.util.NbBundle.Messages;
46 import org.openide.util.actions.CallableSystemAction;
47 import org.openide.windows.WindowManager;
84
88 public class Case implements SleuthkitCase.ErrorObserver {
89
93 @NbBundle.Messages({"Case_caseType_singleUser=Single-user case", "Case_caseType_multiUser=Multi-user case"})
95
98
100
107 this.typeName = typeName;
108 }
109
115 @Override
117 return typeName;
118 }
119
126 if (fromString(typeName) == SINGLE_USER_CASE) {
127 return Bundle.Case_caseType_singleUser();
128 } else {
129 return Bundle.Case_caseType_multiUser();
130 }
131 }
132
141 if (typeName != null) {
143 if (typeName.equalsIgnoreCase(c.typeName)) {
144 return c;
145 }
146 }
147 }
148 return null;
149 }
150
161 @Deprecated
163 return (otherTypeName == null) ? false : typeName.equals(otherTypeName);
164 }
165
166 };
167
173
268 };
269
277 static final String MODULE_FOLDER = "ModuleOutput"; //NON-NLS
284 private final SleuthkitCase
db;
289
298 }
299
308 .map(Events::toString)
309 .collect(Collectors.toSet()), listener);
310 }
311
320 .map(Events::toString)
321 .collect(Collectors.toSet()), listener);
322 }
323
332 }
333
342 }
343
352 }
353
362 }
363
370 return currentCase != null;
371 }
372
381 if (currentCase != null) {
383 } else {
384 throw new IllegalStateException(NbBundle.getMessage(
Case.class,
"Case.getCurCase.exception.noneOpen"));
385 }
386 }
387
395 }
396
404 }
405
413 }
414
422 }
423
430 return getCaseMetadata().getCreatedDate();
431 }
432
440 }
441
452 void updateCaseName(String oldCaseName, String oldPath, String newCaseName, String newPath)
throws CaseActionException {
453 try {
454 caseMetadata.setCaseName(newCaseName);
455 eventPublisher.
publish(
new AutopsyEvent(Events.NAME.toString(), oldCaseName, newCaseName));
456 SwingUtilities.invokeLater(() -> {
457 try {
458 RecentCases.getInstance().updateRecentCase(oldCaseName, oldPath, newCaseName, newPath); // update the recent case
460 } catch (Exception ex) {
461 Logger.getLogger(
Case.class.getName()).log(Level.SEVERE,
"Error updating case name in UI", ex);
//NON-NLS
462 }
463 });
464 } catch (Exception ex) {
465 throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.updateCaseName.exception.msg"), ex);
466 }
467 }
468
476 }
477
485 }
486
494 }
495
506 Path hostPath;
509 } else {
510 hostPath = Paths.get(caseDirectory);
511 }
512 if (!hostPath.toFile().exists()) {
513 hostPath.toFile().mkdirs();
514 }
515 return hostPath.toString();
516 }
517
526 }
527
536 }
537
546 }
547
556 }
557
566 }
567
576 }
577
588 return path.subpath(path.getNameCount() - 2, path.getNameCount()).toString();
589 } else {
590 return path.subpath(path.getNameCount() - 1, path.getNameCount()).toString();
591 }
592 }
593
602 if (!subDirectory.exists()) {
603 subDirectory.mkdirs();
604 }
605 return subDirectory.toString();
606 }
607
618 List<Content> list = db.getRootObjects();
619 hasDataSources = (list.size() > 0);
620 return list;
621 }
622
629 Set<TimeZone> timezones = new HashSet<>();
630 try {
632 final Content dataSource = c.getDataSource();
633 if ((dataSource != null) && (dataSource instanceof Image)) {
634 Image image = (Image) dataSource;
635 timezones.add(TimeZone.getTimeZone(image.getTimeZone()));
636 }
637 }
638 } catch (TskCoreException ex) {
639 logger.log(Level.SEVERE, "Error getting data source time zones", ex); //NON-NLS
640 }
641 return timezones;
642 }
643
651 }
652
660 if (!hasDataSources) {
661 try {
663 } catch (TskCoreException ex) {
664 logger.log(Level.SEVERE, "Error accessing case database", ex); //NON-NLS
665 }
666 }
668 }
669
682 }
683
696 }
697
711 }
712
722 }
723
733 }
734
744 }
745
755 }
756
768 public void addReport(String localPath, String srcModuleName, String reportName)
throws TskCoreException {
769 String normalizedLocalPath;
770 try {
771 normalizedLocalPath = Paths.get(localPath).normalize().toString();
772 } catch (InvalidPathException ex) {
773 String errorMsg = "Invalid local path provided: " + localPath; // NON-NLS
774 throw new TskCoreException(errorMsg, ex);
775 }
776 Report report = this.db.addReport(normalizedLocalPath, srcModuleName, reportName);
778 }
779
789 return this.db.getAllReports();
790 }
791
800 public void deleteReports(Collection<? extends Report> reports)
throws TskCoreException {
801 for (Report report : reports) {
802 this.db.deleteReport(report);
804 }
805 }
806
814 @Override
816 /*
817 * NOTE: We are accessing tskErrorReporter from two different threads.
818 * This is ok as long as we only read the value of tskErrorReporter
819 * because tskErrorReporter is declared as volatile.
820 */
821 if (null != tskErrorReporter) {
822 tskErrorReporter.addProblems(context, errorMessage);
823 }
824 }
825
836 try {
838 this.db.close();
839 } catch (Exception e) {
840 throw new CaseActionException(NbBundle.getMessage(this.getClass(), "Case.closeCase.exception.msg"), e);
841 }
842 }
843
853 logger.log(Level.INFO, "Deleting case.\ncaseDir: {0}", caseDir); //NON-NLS
854
855 try {
856 boolean result = deleteCaseDirectory(caseDir);
857
858 RecentCases.getInstance().removeRecentCase(this.caseMetadata.
getCaseName(), this.caseMetadata.getFilePath().toString());
// remove it from the recent case
860 if (result == false) {
862 NbBundle.getMessage(this.getClass(), "Case.deleteCase.exception.msg", caseDir));
863 }
864
865 } catch (Exception ex) {
866 logger.log(Level.SEVERE, "Error deleting the current case dir: " + caseDir, ex); //NON-NLS
867 throw new CaseActionException(
868 NbBundle.getMessage(this.getClass(), "Case.deleteCase.exception.msg2", caseDir), ex);
869 }
870 }
871
878 if ((appName == null) || appName.equals("")) {
879 appName = WindowManager.getDefault().getMainWindow().getTitle();
880 }
882 }
883
895 return !(caseName.contains("\\") || caseName.contains("/") || caseName.contains(":")
896 || caseName.contains("*") || caseName.contains("?") || caseName.contains("\"")
897 || caseName.contains("<") || caseName.contains(">") || caseName.contains("|"));
898 }
899
919 }
920
939 @Messages({"Case.creationException=Could not create case: failed to create case metadata file."})
941 logger.log(Level.INFO, "Attempting to create case {0} in directory = {1}", new Object[]{caseName, caseDir}); //NON-NLS
942
943 /*
944 * Create case directory if it doesn't already exist.
945 */
946 if (new File(caseDir).exists() == false) {
947 Case.createCaseDirectory(caseDir, caseType);
948 }
949
950 /*
951 * Sanitize the case name, create a unique keyword search index name,
952 * and create a standard (single-user) or unique (multi-user) case
953 * database name.
954 */
955 String santizedCaseName = sanitizeCaseName(caseName);
956 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
957 Date date = new Date();
958 String indexName = santizedCaseName + "_" + dateFormat.format(date);
959 String dbName = null;
961 dbName = caseDir + File.separator + "autopsy.db"; //NON-NLS
963 dbName = indexName;
964 }
965
966 /*
967 * Create the case metadata (.aut) file.
968 */
970 try {
971 metadata =
new CaseMetadata(caseDir, caseType, caseName, caseNumber, examiner, dbName, indexName);
974 }
975
976 /*
977 * Create the case database.
978 */
979 SleuthkitCase db = null;
980 try {
982 db = SleuthkitCase.newCase(dbName);
985 }
986 } catch (TskCoreException ex) {
987 logger.log(Level.SEVERE, String.format("Error creating a case %s in %s ", caseName, caseDir), ex); //NON-NLS
988 SwingUtilities.invokeLater(() -> {
989 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
990 });
991 /*
992 * SleuthkitCase.newCase throws TskCoreExceptions with user-friendly
993 * messages, so propagate the exception message.
994 */
997 logger.log(Level.SEVERE, "Error accessing case database connection info", ex); //NON-NLS
998 SwingUtilities.invokeLater(() -> {
999 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1000 });
1002 }
1003
1004 Case newCase =
new Case(metadata, db);
1006
1007 logger.log(Level.INFO, "Created case {0} in directory = {1}", new Object[]{caseName, caseDir}); //NON-NLS
1008 }
1009
1035 static String sanitizeCaseName(String caseName) {
1036
1037 String result;
1038
1039 // Remove all non-ASCII characters
1040 result = caseName.replaceAll("[^\\p{ASCII}]", "_"); //NON-NLS
1041
1042 // Remove all control characters
1043 result = result.replaceAll("[\\p{Cntrl}]", "_"); //NON-NLS
1044
1045 // Remove / \ : ? space ' "
1046 result = result.replaceAll("[ /?:'\"\\\\]", "_"); //NON-NLS
1047
1048 // Make it all lowercase
1049 result = result.toLowerCase();
1050
1051 // Must start with letter or underscore for PostgreSQL. If not, prepend an underscore.
1052 if (result.length() > 0 && !(Character.isLetter(result.codePointAt(0))) && !(result.codePointAt(0) == '_')) {
1053 result = "_" + result;
1054 }
1055
1056 // Chop to 63-16=47 left (63 max for PostgreSQL, taking 16 for the date _20151225_123456)
1058 result = result.substring(0, MAX_SANITIZED_CASE_NAME_LEN);
1059 }
1060
1061 if (result.isEmpty()) {
1062 result = "case"; //NON-NLS
1063 }
1064
1065 return result;
1066 }
1067
1076 static void createCaseDirectory(String caseDir, CaseType caseType) throws CaseActionException {
1077
1078 File caseDirF = new File(caseDir);
1079 if (caseDirF.exists()) {
1080 if (caseDirF.isFile()) {
1081 throw new CaseActionException(
1082 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.existNotDir", caseDir));
1083 } else if (!caseDirF.canRead() || !caseDirF.canWrite()) {
1084 throw new CaseActionException(
1085 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.existCantRW", caseDir));
1086 }
1087 }
1088
1089 try {
1090 boolean result = (caseDirF).mkdirs(); // create root case Directory
1091 if (result == false) {
1092 throw new CaseActionException(
1093 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreate", caseDir));
1094 }
1095
1096 // create the folders inside the case directory
1097 String hostClause = "";
1098
1100 hostClause = File.separator + NetworkUtils.getLocalHostName();
1101 }
1102 result = result && (new File(caseDir + hostClause + File.separator + EXPORT_FOLDER)).mkdirs()
1103 && (new File(caseDir + hostClause + File.separator + LOG_FOLDER)).mkdirs()
1104 && (new File(caseDir + hostClause + File.separator + TEMP_FOLDER)).mkdirs()
1105 && (new File(caseDir + hostClause + File.separator + CACHE_FOLDER)).mkdirs();
1106
1107 if (result == false) {
1108 throw new CaseActionException(
1109 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateCaseDir", caseDir));
1110 }
1111
1112 final String modulesOutDir = caseDir + hostClause + File.separator + MODULE_FOLDER;
1113 result = new File(modulesOutDir).mkdir();
1114 if (result == false) {
1115 throw new CaseActionException(
1116 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateModDir",
1117 modulesOutDir));
1118 }
1119
1120 final String reportsOutDir = caseDir + hostClause + File.separator +
REPORTS_FOLDER;
1121 result = new File(reportsOutDir).mkdir();
1122 if (result == false) {
1123 throw new CaseActionException(
1124 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateReportsDir",
1125 modulesOutDir));
1126 }
1127
1128 } catch (Exception e) {
1129 throw new CaseActionException(
1130 NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.gen", caseDir), e);
1131 }
1132 }
1133
1145 logger.log(Level.INFO, "Opening case with metadata file path {0}", caseMetadataFilePath); //NON-NLS
1146
1147 /*
1148 * Verify the extension of the case metadata file.
1149 */
1152 }
1153
1154 try {
1155 /*
1156 * Get the case metadata required to open the case database.
1157 */
1160
1161 /*
1162 * Open the case database.
1163 */
1167 db = SleuthkitCase.openCase(dbPath);
1168 } else {
1170 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.open.exception.multiUserCaseNotEnabled"));
1171 }
1172 try {
1176 }
1177 }
1178
1179 /*
1180 * Check for the presence of the UI and do things that can only be
1181 * done with user interaction.
1182 */
1184 /*
1185 * If the case database was upgraded for a new schema, notify
1186 * the user.
1187 */
1188 if (null != db.getBackupDatabasePath()) {
1189 SwingUtilities.invokeLater(() -> {
1190 JOptionPane.showMessageDialog(
1191 WindowManager.getDefault().getMainWindow(),
1192 NbBundle.getMessage(
Case.class,
"Case.open.msgDlg.updated.msg", db.getBackupDatabasePath()),
1193 NbBundle.getMessage(
Case.class,
"Case.open.msgDlg.updated.title"),
1194 JOptionPane.INFORMATION_MESSAGE);
1195 });
1196 }
1197
1198 /*
1199 * Look for the files for the data sources listed in the case
1200 * database and give the user the opportunity to locate any that
1201 * are missing.
1202 */
1203 Map<Long, String> imgPaths = getImagePaths(db);
1204 for (Map.Entry<Long, String> entry : imgPaths.entrySet()) {
1205 long obj_id = entry.getKey();
1206 String path = entry.getValue();
1207 boolean fileExists = (new File(path).isFile() || driveExists(path));
1208 if (!fileExists) {
1209 int ret = JOptionPane.showConfirmDialog(
1210 WindowManager.getDefault().getMainWindow(),
1211 NbBundle.getMessage(
Case.class,
"Case.checkImgExist.confDlg.doesntExist.msg",
getAppName(), path),
1212 NbBundle.getMessage(
Case.class,
"Case.checkImgExist.confDlg.doesntExist.title"),
1213 JOptionPane.YES_NO_OPTION);
1214 if (ret == JOptionPane.YES_OPTION) {
1215 MissingImageDialog.makeDialog(obj_id, db);
1216 } else {
1217 logger.log(Level.WARNING, "Selected image files don't match old files!"); //NON-NLS
1218 }
1219 }
1220 }
1221 }
1222 Case openedCase =
new Case(metadata, db);
1224
1226 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.metaDataFileCorrupt.exception.msg"), ex);
//NON-NLS
1227 } catch (TskCoreException ex) {
1228 SwingUtilities.invokeLater(() -> {
1229 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1230 });
1231 /*
1232 * SleuthkitCase.openCase throws TskCoreExceptions with
1233 * user-friendly messages, so propagate the exception message.
1234 */
1236 }
1237 }
1238
1246 static Map<Long, String> getImagePaths(SleuthkitCase db) {
1247 Map<Long, String> imgPaths = new HashMap<>();
1248 try {
1249 Map<Long, List<String>> imgPathsList = db.getImagePaths();
1250 for (Map.Entry<Long, List<String>> entry : imgPathsList.entrySet()) {
1251 if (entry.getValue().size() > 0) {
1252 imgPaths.put(entry.getKey(), entry.getValue().get(0));
1253 }
1254 }
1255 } catch (TskException ex) {
1256 logger.log(Level.SEVERE, "Error getting image paths", ex); //NON-NLS
1257 }
1258 return imgPaths;
1259 }
1260
1269 // close the existing case
1272 if (oldCase != null) {
1273 SwingUtilities.invokeLater(() -> {
1274 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1275 });
1279 oldCase.
tskErrorReporter.shutdown();
// stop listening for TSK errors for the old case
1281 }
1286 }
1288 }
1289 }
1290
1291 if (newCase != null) {
1292 currentCase = newCase;
1294 // sanity check
1297 }
1298 // start listening for TSK errors for the new case
1299 currentCase.
tskErrorReporter =
new IntervalErrorReportData(currentCase, MIN_SECS_BETWEEN_TSK_ERROR_REPORTS,
1300 NbBundle.getMessage(
Case.class,
"IntervalErrorReport.ErrorText"));
1302 SwingUtilities.invokeLater(() -> {
1303 RecentCases.getInstance().addRecentCase(currentCase.
getName(), currentCase.getCaseMetadata().getFilePath().toString());
// update the recent cases
1304 });
1306 try {
1316 logger.log(Level.SEVERE, "Failed to setup for collaboration", ex); //NON-NLS
1317 MessageNotifyUtil.
Notify.
error(NbBundle.getMessage(
Case.class,
"Case.CollaborationSetup.FailNotify.Title"), NbBundle.getMessage(
Case.class,
"Case.CollaborationSetup.FailNotify.ErrMsg"));
1318 }
1319 }
1321
1322 } else {
1324 }
1325 SwingUtilities.invokeLater(() -> {
1326 WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1327 });
1328 }
1329
1338 logger.log(Level.INFO, "Changing Case to: {0}", newCase); //NON-NLS
1339 if (newCase != null) { // new case is open
1340
1341 // clear the temp folder when the case is created / opened
1343
1345 // enable these menus
1346 SwingUtilities.invokeLater(() -> {
1349 CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true);
1350 CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true); // Delete Case menu
1352
1354 // open all top components
1356 } else {
1357 // close all top components
1359 }
1361 });
1362 } else {
1363 SwingUtilities.invokeLater(() -> {
1364 Frame f = WindowManager.getDefault().getMainWindow();
1365 f.setTitle(
getAppName());
// set the window name to just application name
1366 });
1367 }
1368
1369 } else { // case is closed
1370 SwingUtilities.invokeLater(() -> {
1372
1373 // close all top components first
1375
1376 // disable these menus
1377 CallableSystemAction.get(
AddImageAction.class).setEnabled(
false);
// Add Image menu
1378 CallableSystemAction.get(
CaseCloseAction.class).setEnabled(
false);
// Case Close menu
1379 CallableSystemAction.get(CasePropertiesAction.class).setEnabled(false); // Case Properties menu
1380 CallableSystemAction.get(CaseDeleteAction.class).setEnabled(false); // Delete Case menu
1382 }
1383
1384 //clear pending notifications
1386 Frame f = WindowManager.getDefault().getMainWindow();
1387 f.setTitle(
getAppName());
// set the window name to just application name
1388 });
1389
1390 //try to force gc to happen
1391 System.gc();
1392 System.gc();
1393 }
1394
1395 //log memory usage after case changed
1397
1398 }
1399
1405 if (tempFolder.isDirectory()) {
1406 File[] files = tempFolder.listFiles();
1407 if (files.length > 0) {
1408 for (File file : files) {
1409 if (file.isDirectory()) {
1410 deleteCaseDirectory(file);
1411 } else {
1412 file.delete();
1413 }
1414 }
1415 }
1416 }
1417 }
1418
1425 if (!newCaseName.equals("")) {
1426 Frame f = WindowManager.getDefault().getMainWindow();
1427 f.setTitle(newCaseName +
" - " +
getAppName());
1428 }
1429 }
1430
1438 static boolean deleteCaseDirectory(File casePath) {
1439 logger.log(Level.INFO, "Deleting case directory: {0}", casePath.getAbsolutePath()); //NON-NLS
1441 }
1442
1450 @Deprecated
1453 }
1454
1465 @Deprecated
1466 static boolean isPhysicalDrive(String path) {
1468 }
1469
1478 @Deprecated
1479 static boolean isPartition(String path) {
1480 return DriveUtils.isPartition(path);
1481 }
1482
1494 @Deprecated
1495 static boolean driveExists(String path) {
1496 return DriveUtils.driveExists(path);
1497 }
1498
1504 @Deprecated
1507 }
1508
1522 @Deprecated
1525 }
1526
1536 @Deprecated
1538 return new File(filePath).isFile();
1539 }
1540
1549 @Deprecated
1552 }
1553
1564 @Deprecated
1565 static void createCaseDirectory(String caseDir, String caseName)
throws CaseActionException {
1567 }
1568
1576 @Deprecated
1578 return currentCase != null;
1579 }
1580
1589 @Deprecated
1592 }
1593
1603 @Deprecated
1605 return "ModuleOutput"; //NON-NLS
1606 }
1607
1617 @Deprecated
1619 return new PropertyChangeSupport(
Case.class);
1620 }
1621
1629 @Deprecated
1630 String getConfigFilePath() {
1631 return getCaseMetadata().getFilePath().toString();
1632 }
1633
1644 @Deprecated
1646 try {
1647 Image newDataSource = db.getImageById(imgId);
1649 return newDataSource;
1650 } catch (Exception ex) {
1651 throw new CaseActionException(NbBundle.getMessage(
this.getClass(),
"Case.addImg.exception.msg"), ex);
1652 }
1653 }
1654
1665 @Deprecated
1666 void addLocalDataSource(Content newDataSource) {
1668 }
1669
1680 @Deprecated
1681 public void deleteReports(Collection<? extends Report> reports,
boolean deleteFromDisk)
throws TskCoreException {
1683 }
1684
1685 @Deprecated
1686 public static final String
propStartup =
"LBL_StartupDialog";
//NON-NLS
1687
1688 }
String getLogDirectoryPath()
static final AutopsyEventPublisher eventPublisher
List< Content > getDataSources()
String getModuleOutputDirectoryRelativePath()
void notifyContentTagDeleted(ContentTag deletedTag)
static final int MIN_SECS_BETWEEN_TSK_ERROR_REPORTS
static CaseType fromString(String typeName)
static void addCaseNameToMainWindowTitle(String newCaseName)
void publishLocally(AutopsyEvent event)
void notifyBlackBoardArtifactTagDeleted(BlackboardArtifactTag deletedTag)
Set< TimeZone > getTimeZones()
Image addImage(String imgPath, long imgId, String timeZone)
static boolean isPhysicalDrive(String path)
static final String propStartup
static synchronized IngestManager getInstance()
String getTempDirectory()
void cancelAllIngestJobs()
static boolean existsCurrentCase()
static void removePropertyChangeListener(PropertyChangeListener listener)
static final Logger logger
void publish(AutopsyEvent event)
String getLocalizedDisplayName()
ADDING_DATA_SOURCE_FAILED
static final String EXPORT_FOLDER
String getCaseDirectory()
static String convertTimeZone(String timeZoneId)
static void openCoreWindows()
void addSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
synchronized static void setLogDirectory(String directoryPath)
static final String CACHE_FOLDER
static String getAutopsyVersion()
CaseType(String typeName)
static final int MAX_SANITIZED_CASE_NAME_LEN
String getReportDirectory()
static boolean getIsMultiUserModeEnabled()
void addReport(String localPath, String srcModuleName, String reportName)
static CaseDbConnectionInfo getDatabaseConnectionInfo()
String getModulesOutputDirAbsPath()
void deleteReports(Collection<?extends Report > reports, boolean deleteFromDisk)
Case(CaseMetadata caseMetadata, SleuthkitCase db)
volatile IntervalErrorReportData tskErrorReporter
List< Report > getAllReports()
static boolean isValidName(String caseName)
static void changeCurrentCase(Case newCase)
CollaborationMonitor collaborationMonitor
static void closeCoreWindows()
static String getModulesOutputDirRelPath()
static void completeCaseChange(Case newCase)
Set< TimeZone > getTimeZone()
static void invokeStartupDialog()
void openRemoteEventChannel(String channelName)
static boolean coreComponentsAreActive()
static void removeEventSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
SleuthkitCase getSleuthkitCase()
void closeRemoteEventChannel()
void notifyBlackBoardArtifactTagAdded(BlackboardArtifactTag newTag)
static PropertyChangeSupport getPropertyChangeSupport()
String getCacheDirectory()
static void addPropertyChangeListener(PropertyChangeListener listener)
void removeSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
String getModuleDirectory()
static void removeEventSubscriber(String eventName, PropertyChangeListener subscriber)
void deleteReports(Collection<?extends Report > reports)
void notifyDataSourceAdded(Content dataSource, UUID addingDataSourceEventId)
static boolean pathExists(String filePath)
BLACKBOARD_ARTIFACT_TAG_ADDED
static void open(String caseMetadataFilePath)
final CaseMetadata caseMetadata
String getOutputDirectory()
static void error(String title, String message)
String getOrCreateSubdirectory(String subDirectoryName)
static void create(String caseDir, String caseName, String caseNumber, String examiner)
boolean equalsName(String otherTypeName)
static final String EVENT_CHANNEL_NAME
static Case getCurrentCase()
static String getLocalHostName()
synchronized static Logger getLogger(String name)
static String convertToAlphaNumericFormat(String timeZoneId)
static final String LOG_FOLDER
void receiveError(String context, String errorMessage)
static String getAppName()
static String getVersion()
String getExportDirectory()
void notifyAddingDataSource(UUID eventId)
static void clearTempFolder()
static void addEventSubscriber(String eventName, PropertyChangeListener subscriber)
void notifyContentTagAdded(ContentTag newTag)
static StartupWindowProvider getInstance()
static boolean deleteDir(File dirPath)
static void create(String caseDir, String caseName, String caseNumber, String examiner, CaseType caseType)
void notifyFailedAddingDataSource(UUID addingDataSourceEventId)
static boolean isCaseOpen()
String getTextIndexName()
static final String REPORTS_FOLDER
static final String TEMP_FOLDER
BLACKBOARD_ARTIFACT_TAG_DELETED
static void addEventSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)