19 package org.sleuthkit.autopsy.casemodule;
23 import com.google.common.annotations.Beta;
24 import com.google.common.eventbus.Subscribe;
25 import com.google.common.util.concurrent.ThreadFactoryBuilder;
26 import java.awt.Cursor;
28 import java.awt.Frame;
29 import java.awt.event.ActionEvent;
30 import java.awt.event.ActionListener;
31 import java.beans.PropertyChangeListener;
32 import java.beans.PropertyChangeSupport;
34 import java.lang.reflect.InvocationTargetException;
35 import java.nio.file.InvalidPathException;
36 import java.nio.file.Path;
37 import java.nio.file.Paths;
38 import java.sql.Connection;
39 import java.sql.DriverManager;
40 import java.sql.ResultSet;
41 import java.sql.SQLException;
42 import java.sql.Statement;
43 import java.text.SimpleDateFormat;
44 import java.util.Collection;
45 import java.util.Date;
46 import java.util.HashMap;
47 import java.util.HashSet;
48 import java.util.List;
51 import java.util.TimeZone;
52 import java.util.UUID;
53 import java.util.concurrent.CancellationException;
54 import java.util.concurrent.ExecutionException;
55 import java.util.concurrent.ExecutorService;
56 import java.util.concurrent.Executors;
57 import java.util.concurrent.Future;
58 import java.util.concurrent.ThreadFactory;
59 import java.util.concurrent.TimeUnit;
60 import java.util.logging.Level;
61 import java.util.stream.Collectors;
62 import java.util.stream.Stream;
63 import javax.annotation.concurrent.GuardedBy;
64 import javax.annotation.concurrent.ThreadSafe;
65 import javax.swing.JOptionPane;
66 import javax.swing.SwingUtilities;
67 import org.apache.commons.lang3.StringUtils;
68 import org.openide.util.Lookup;
69 import org.openide.util.NbBundle;
70 import org.openide.util.NbBundle.Messages;
71 import org.openide.util.actions.CallableSystemAction;
72 import org.openide.windows.WindowManager;
159 import org.
sleuthkit.datamodel.TskUnsupportedSchemaVersionException;
187 = Executors.newSingleThreadExecutor(
new ThreadFactoryBuilder().setNameFormat(
"case-open-file-systems-%d").build());
209 WindowManager.getDefault().invokeWhenUIReady(() -> {
210 mainFrame = WindowManager.getDefault().getMainWindow();
232 if (typeName != null) {
234 if (typeName.equalsIgnoreCase(c.toString())) {
258 "Case_caseType_singleUser=Single-user case",
259 "Case_caseType_multiUser=Multi-user case"
262 if (fromString(typeName) == SINGLE_USER_CASE) {
263 return Bundle.Case_caseType_singleUser();
265 return Bundle.Case_caseType_multiUser();
275 this.typeName = typeName;
290 return (otherTypeName == null) ?
false : typeName.equals(otherTypeName);
545 }
catch (TskCoreException ex) {
546 logger.log(Level.SEVERE,
"Unable to retrieve the hasData status from the db", ex);
589 }
catch (TskCoreException ex) {
590 logger.log(Level.SEVERE,
"Unable to retrieve the hasData status from the db", ex);
673 .map(Events::toString)
674 .collect(Collectors.toSet()), listener);
685 .map(Events::toString)
686 .collect(Collectors.toSet()), listener);
709 eventTypes.forEach((
Events event) -> {
754 eventTypes.forEach((
Events event) -> {
768 return !(caseName.contains(
"\\") || caseName.contains(
"/") || caseName.contains(
":")
769 || caseName.contains(
"*") || caseName.contains(
"?") || caseName.contains(
"\"")
770 || caseName.contains(
"<") || caseName.contains(
">") || caseName.contains(
"|"));
822 "Case.exceptionMessage.emptyCaseName=Must specify a case name.",
823 "Case.exceptionMessage.emptyCaseDir=Must specify a case directory path."
827 throw new CaseActionException(Bundle.Case_exceptionMessage_emptyCaseName());
829 if (caseDir.isEmpty()) {
830 throw new CaseActionException(Bundle.Case_exceptionMessage_emptyCaseDir());
849 "# {0} - exception message",
"Case.exceptionMessage.failedToReadMetadata=Failed to read case metadata:\n{0}.",
850 "Case.exceptionMessage.cannotOpenMultiUserCaseNoSettings=Multi-user settings are missing (see Tools, Options, Multi-user tab), cannot open a multi-user case."
855 metadata =
new CaseMetadata(Paths.get(caseMetadataFilePath));
857 throw new CaseActionException(Bundle.Case_exceptionMessage_failedToReadMetadata(ex.getLocalizedMessage()), ex);
860 throw new CaseActionException(Bundle.Case_exceptionMessage_cannotOpenMultiUserCaseNoSettings());
871 return currentCase != null;
888 throw new IllegalStateException(NbBundle.getMessage(
Case.class,
"Case.getCurCase.exception.noneOpen"), ex);
912 if (openCase == null) {
913 throw new NoCurrentCaseException(NbBundle.getMessage(
Case.class,
"Case.getCurCase.exception.noneOpen"));
928 "# {0} - exception message",
"Case.closeException.couldNotCloseCase=Error closing case: {0}",
929 "Case.progressIndicatorTitle.closingCase=Closing Case"
933 if (null == currentCase) {
939 logger.log(Level.INFO,
"Closing current case {0} ({1}) in {2}",
new Object[]{closedCase.getDisplayName(), closedCase.getName(), closedCase.getCaseDirectory()});
941 logger.log(Level.INFO,
"Closed current case {0} ({1}) in {2}",
new Object[]{closedCase.getDisplayName(), closedCase.getName(), closedCase.getCaseDirectory()});
942 }
catch (CaseActionException ex) {
964 if (null == currentCase) {
984 "Case.progressIndicatorTitle.deletingDataSource=Removing Data Source"
986 static void deleteDataSourceFromCurrentCase(Long dataSourceObjectID)
throws CaseActionException {
988 if (null == currentCase) {
995 CaseMetadata caseMetadata = currentCase.
getMetadata();
1003 Case theCase =
new Case(caseMetadata);
1004 theCase.doOpenCaseAction(Bundle.Case_progressIndicatorTitle_deletingDataSource(), theCase::deleteDataSource, CaseLockType.EXCLUSIVE,
false, dataSourceObjectID);
1025 "Case.progressIndicatorTitle.deletingCase=Deleting Case",
1026 "Case.exceptionMessage.cannotDeleteCurrentCase=Cannot delete current case, it must be closed first.",
1027 "# {0} - case display name",
"Case.exceptionMessage.deletionInterrupted=Deletion of the case {0} was cancelled."
1031 if (null != currentCase) {
1032 throw new CaseActionException(Bundle.Case_exceptionMessage_cannotDeleteCurrentCase());
1042 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
1049 }
catch (InterruptedException ex) {
1055 throw new CaseActionException(Bundle.Case_exceptionMessage_deletionInterrupted(metadata.
getCaseDisplayName()), ex);
1059 progressIndicator.
finish();
1074 "Case.progressIndicatorTitle.creatingCase=Creating Case",
1075 "Case.progressIndicatorTitle.openingCase=Opening Case",
1076 "Case.exceptionMessage.cannotLocateMainWindow=Cannot locate main application window"
1080 if (null != currentCase) {
1083 }
catch (CaseActionException ex) {
1092 logger.log(Level.INFO,
"Opening {0} ({1}) in {2} as the current case",
new Object[]{newCurrentCase.getDisplayName(), newCurrentCase.getName(), newCurrentCase.getCaseDirectory()});
1093 String progressIndicatorTitle;
1096 progressIndicatorTitle = Bundle.Case_progressIndicatorTitle_creatingCase();
1097 openCaseAction = newCurrentCase::create;
1099 progressIndicatorTitle = Bundle.Case_progressIndicatorTitle_openingCase();
1100 openCaseAction = newCurrentCase::open;
1103 currentCase = newCurrentCase;
1104 logger.log(Level.INFO,
"Opened {0} ({1}) in {2} as the current case",
new Object[]{newCurrentCase.getDisplayName(), newCurrentCase.getName(), newCurrentCase.getCaseDirectory()});
1110 logger.log(Level.INFO, String.format(
"Cancelled opening %s (%s) in %s as the current case", newCurrentCase.
getDisplayName(), newCurrentCase.
getName(), newCurrentCase.
getCaseDirectory()));
1112 }
catch (CaseActionException ex) {
1113 logger.log(Level.SEVERE, String.format(
"Error opening %s (%s) in %s as the current case", newCurrentCase.
getDisplayName(), newCurrentCase.
getName(), newCurrentCase.
getCaseDirectory()), ex);
1131 String uniqueCaseName = caseDisplayName.replaceAll(
"[^\\p{ASCII}]",
"_");
1136 uniqueCaseName = uniqueCaseName.replaceAll(
"[\\p{Cntrl}]",
"_");
1141 uniqueCaseName = uniqueCaseName.replaceAll(
"[ /?:'\"\\\\]",
"_");
1146 uniqueCaseName = uniqueCaseName.toLowerCase();
1151 SimpleDateFormat dateFormat =
new SimpleDateFormat(
"yyyyMMdd_HHmmss");
1152 Date date =
new Date();
1153 uniqueCaseName = uniqueCaseName +
"_" + dateFormat.format(date);
1155 return uniqueCaseName;
1172 File caseDir =
new File(caseDirPath);
1173 if (caseDir.exists()) {
1174 if (caseDir.isFile()) {
1175 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.existNotDir", caseDirPath));
1176 }
else if (!caseDir.canRead() || !caseDir.canWrite()) {
1177 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.existCantRW", caseDirPath));
1184 if (!caseDir.mkdirs()) {
1185 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreate", caseDirPath));
1193 String hostPathComponent =
"";
1198 Path exportDir = Paths.get(caseDirPath, hostPathComponent, EXPORT_FOLDER);
1199 if (!exportDir.toFile().mkdirs()) {
1200 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateCaseDir", exportDir));
1203 Path logsDir = Paths.get(caseDirPath, hostPathComponent, LOG_FOLDER);
1204 if (!logsDir.toFile().mkdirs()) {
1205 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateCaseDir", logsDir));
1208 Path cacheDir = Paths.get(caseDirPath, hostPathComponent, CACHE_FOLDER);
1209 if (!cacheDir.toFile().mkdirs()) {
1210 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateCaseDir", cacheDir));
1213 Path moduleOutputDir = Paths.get(caseDirPath, hostPathComponent, MODULE_FOLDER);
1214 if (!moduleOutputDir.toFile().mkdirs()) {
1215 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateModDir", moduleOutputDir));
1218 Path reportsDir = Paths.get(caseDirPath, hostPathComponent, REPORTS_FOLDER);
1219 if (!reportsDir.toFile().mkdirs()) {
1220 throw new CaseActionException(NbBundle.getMessage(
Case.class,
"Case.createCaseDir.exception.cantCreateReportsDir", reportsDir));
1231 static Map<Long, String> getImagePaths(SleuthkitCase db) {
1232 Map<Long, String> imgPaths =
new HashMap<>();
1234 Map<Long, List<String>> imgPathsList = db.getImagePaths();
1235 for (Map.Entry<Long, List<String>> entry : imgPathsList.entrySet()) {
1236 if (entry.getValue().size() > 0) {
1237 imgPaths.put(entry.getKey(), entry.getValue().get(0));
1240 }
catch (TskCoreException ex) {
1241 logger.log(Level.SEVERE,
"Error getting image paths", ex);
1257 "Case.creationException.couldNotAcquireResourcesLock=Failed to get lock on case resources"
1261 Path caseDirPath = Paths.get(caseDir);
1265 }
catch (InterruptedException ex) {
1268 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock(), ex);
1291 String backupDbPath = caseDb.getBackupDatabasePath();
1292 if (null != backupDbPath) {
1293 JOptionPane.showMessageDialog(
1295 NbBundle.getMessage(
Case.class,
"Case.open.msgDlg.updated.msg", backupDbPath),
1296 NbBundle.getMessage(
Case.class,
"Case.open.msgDlg.updated.title"),
1297 JOptionPane.INFORMATION_MESSAGE);
1304 Map<Long, String> imgPaths = getImagePaths(caseDb);
1305 for (Map.Entry<Long, String> entry : imgPaths.entrySet()) {
1306 long obj_id = entry.getKey();
1307 String path = entry.getValue();
1313 && (path == null || path.matches(PLACEHOLDER_DS_PATH_REGEX))) {
1319 String hostName = StringUtils.defaultString(ds.getHost() == null ?
"" : ds.getHost().getName());
1324 SwingUtilities.invokeAndWait(
new Runnable() {
1327 int response = JOptionPane.showConfirmDialog(
1329 NbBundle.getMessage(
Case.class,
"Case.checkImgExist.confDlg.doesntExist.msg", hostName, path),
1330 NbBundle.getMessage(
Case.class,
"Case.checkImgExist.confDlg.doesntExist.title"),
1331 JOptionPane.YES_NO_OPTION);
1332 if (response == JOptionPane.YES_OPTION) {
1333 MissingImageDialog.makeDialog(obj_id, caseDb);
1335 logger.log(Level.SEVERE,
"User proceeding with missing image files");
1341 }
catch (InterruptedException | InvocationTargetException | TskCoreException | TskDataException ex) {
1342 logger.log(Level.SEVERE,
"Failed to show missing image confirmation dialog", ex);
1353 CallableSystemAction.get(CaseDetailsAction.class).setEnabled(
true);
1368 final boolean hasData = newCurrentCase.
hasData();
1370 SwingUtilities.invokeLater(() -> {
1379 mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1386 mainFrame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1402 SwingUtilities.invokeLater(() -> {
1412 CallableSystemAction.get(
AddImageAction.class).setEnabled(
false);
1415 CallableSystemAction.get(CaseDetailsAction.class).setEnabled(
false);
1417 CallableSystemAction.get(CaseDeleteAction.class).setEnabled(
false);
1561 hostPath = Paths.get(caseDirectory);
1563 if (!hostPath.toFile().exists()) {
1564 hostPath.toFile().mkdirs();
1566 return hostPath.toString();
1573 return Paths.get(System.getProperty(
"java.io.tmpdir"),
APP_NAME,
getName());
1585 Path basePath = null;
1590 basePath = (StringUtils.isBlank(customDirectory))
1592 : Paths.get(customDirectory, APP_NAME,
getName());
1610 : Paths.get(TEMP_FOLDER);
1612 File caseTempDir = basePath
1613 .resolve(caseRelPath)
1617 if (!caseTempDir.exists()) {
1618 caseTempDir.mkdirs();
1621 return caseTempDir.getAbsolutePath();
1694 return path.subpath(path.getNameCount() - 2, path.getNameCount()).toString();
1696 return path.subpath(path.getNameCount() - 1, path.getNameCount()).toString();
1710 return caseDb.getRootObjects();
1719 Set<TimeZone> timezones =
new HashSet<>();
1720 String query =
"SELECT time_zone FROM data_source_info";
1721 try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
1722 ResultSet timeZoneSet = dbQuery.getResultSet();
1723 while (timeZoneSet.next()) {
1724 String timeZone = timeZoneSet.getString(
"time_zone");
1725 if (timeZone != null && !timeZone.isEmpty()) {
1726 timezones.add(TimeZone.getTimeZone(timeZone));
1729 }
catch (TskCoreException | SQLException ex) {
1730 logger.log(Level.SEVERE,
"Error getting data source time zones", ex);
1774 hasDataSource =
true;
1882 logger.log(Level.WARNING,
"Unable to send notifcation regarding comment change due to no current case being open", ex);
1932 public void addReport(String localPath, String srcModuleName, String reportName)
throws TskCoreException {
1933 addReport(localPath, srcModuleName, reportName, null);
1950 public Report
addReport(String localPath, String srcModuleName, String reportName, Content parent)
throws TskCoreException {
1951 String normalizedLocalPath;
1953 if (localPath.toLowerCase().contains(
"http:")) {
1954 normalizedLocalPath = localPath;
1956 normalizedLocalPath = Paths.get(localPath).normalize().toString();
1958 }
catch (InvalidPathException ex) {
1959 String errorMsg =
"Invalid local path provided: " + localPath;
1960 throw new TskCoreException(errorMsg, ex);
1964 Report report = this.caseDb.addReport(normalizedLocalPath, srcModuleName, reportName, parent);
1978 return this.caseDb.getAllReports();
1989 public void deleteReports(Collection<? extends Report> reports)
throws TskCoreException {
1990 for (Report report : reports) {
1991 this.caseDb.deleteReport(report);
1996 }
catch (TskCoreException ex) {
1997 logger.log(Level.SEVERE,
"Unable to retrieve the hasData status from the db", ex);
2000 for (Report report : reports) {
2022 "Case.exceptionMessage.metadataUpdateError=Failed to update case metadata"
2024 void updateCaseDetails(CaseDetails caseDetails)
throws CaseActionException {
2027 metadata.setCaseDetails(caseDetails);
2028 }
catch (CaseMetadataException ex) {
2029 throw new CaseActionException(Bundle.Case_exceptionMessage_metadataUpdateError(), ex);
2033 CaseNodeData nodeData = CaseNodeData.readCaseNodeData(metadata.
getCaseDirectory());
2035 CaseNodeData.writeCaseNodeData(nodeData);
2036 }
catch (CaseNodeDataException | InterruptedException ex) {
2037 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotUpdateCaseNodeData(ex.getLocalizedMessage()), ex);
2040 if (!oldCaseDetails.getCaseNumber().equals(caseDetails.
getCaseNumber())) {
2041 eventPublisher.
publish(
new AutopsyEvent(Events.NUMBER.toString(), oldCaseDetails.getCaseNumber(), caseDetails.
getCaseNumber()));
2043 if (!oldCaseDetails.getExaminerName().equals(caseDetails.
getExaminerName())) {
2044 eventPublisher.
publish(
new AutopsyEvent(Events.NUMBER.toString(), oldCaseDetails.getExaminerName(), caseDetails.
getExaminerName()));
2047 eventPublisher.
publish(
new AutopsyEvent(Events.NAME.toString(), oldCaseDetails.getCaseDisplayName(), caseDetails.
getCaseDisplayName()));
2049 eventPublisher.
publish(
new AutopsyEvent(Events.CASE_DETAILS.toString(), oldCaseDetails, caseDetails));
2050 if (RuntimeProperties.runningWithGUI()) {
2051 SwingUtilities.invokeLater(() -> {
2055 }
catch (Exception ex) {
2056 logger.log(Level.SEVERE,
"Error updating case name in UI", ex);
2084 metadata = caseMetaData;
2118 "Case.progressIndicatorCancelButton.label=Cancel",
2119 "Case.progressMessage.preparing=Preparing...",
2120 "Case.progressMessage.cancelling=Cancelling...",
2121 "Case.exceptionMessage.cancelled=Cancelled.",
2122 "# {0} - exception message",
"Case.exceptionMessage.execExceptionWrapperMessage={0}"
2132 if (allowCancellation) {
2136 progressIndicatorTitle,
2137 new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
2138 Bundle.Case_progressIndicatorCancelButton_label(),
2139 cancelButtonListener);
2143 progressIndicatorTitle);
2148 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
2157 caseActionExecutor = Executors.newSingleThreadExecutor(threadFactory);
2158 Future<Void> future = caseActionExecutor.submit(() -> {
2160 caseAction.
execute(progressIndicator, additionalParams);
2164 if (null == resourcesLock) {
2165 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock());
2167 caseAction.
execute(progressIndicator, additionalParams);
2168 }
catch (CaseActionException ex) {
2175 if (null != cancelButtonListener) {
2184 }
catch (InterruptedException discarded) {
2188 if (null != cancelButtonListener) {
2191 future.cancel(
true);
2194 }
catch (CancellationException discarded) {
2200 }
catch (ExecutionException ex) {
2205 throw new CaseActionException(Bundle.Case_exceptionMessage_execExceptionWrapperMessage(ex.getCause().getLocalizedMessage()), ex);
2207 progressIndicator.
finish();
2227 assert (additionalParams == null);
2248 }
catch (CaseActionException ex) {
2257 }
catch (InterruptedException discarded) {
2259 close(progressIndicator);
2279 assert (additionalParams == null);
2299 }
catch (CaseActionException ex) {
2308 }
catch (InterruptedException discarded) {
2310 close(progressIndicator);
2325 "# {0} - case",
"Case.openFileSystems.retrievingImages=Retrieving images for case: {0}...",
2326 "# {0} - image",
"Case.openFileSystems.openingImage=Opening all filesystems for image: {0}..."
2329 if (backgroundOpenFileSystemsFuture != null && !backgroundOpenFileSystemsFuture.isDone()) {
2330 backgroundOpenFileSystemsFuture.cancel(
true);
2359 caseName = (this.tskCase != null) ? this.tskCase.getDatabaseName() :
"";
2370 if (Thread.interrupted()) {
2371 throw new InterruptedException();
2381 progressIndicator.
progress(Bundle.Case_openFileSystems_retrievingImages(caseName));
2383 return this.tskCase.getImages();
2384 }
catch (TskCoreException ex) {
2387 String.format(
"Could not obtain images while opening case: %s.", caseName),
2403 private void openFileSystems(List<Image> images)
throws TskCoreException, InterruptedException {
2404 byte[] tempBuff =
new byte[512];
2406 for (Image image : images) {
2407 String imageStr = image.getName();
2409 progressIndicator.
progress(Bundle.Case_openFileSystems_openingImage(imageStr));
2411 Collection<FileSystem> fileSystems = this.tskCase.getImageFileSystems(image);
2413 for (FileSystem fileSystem : fileSystems) {
2414 fileSystem.read(tempBuff, 0, 512);
2426 if (images == null) {
2434 String.format(
"Skipping background load of file systems due to large number of images in case (%d)", images.size()));
2440 }
catch (InterruptedException ex) {
2443 String.format(
"Background operation opening all file systems in %s has been cancelled.", caseName));
2444 }
catch (Exception ex) {
2446 logger.log(Level.WARNING,
"Error while opening file systems in background", ex);
2467 "Case.progressMessage.deletingDataSource=Removing the data source from the case...",
2468 "Case.exceptionMessage.dataSourceNotFound=The data source was not found.",
2469 "Case.exceptionMessage.errorDeletingDataSourceFromCaseDb=An error occurred while removing the data source from the case database.",
2470 "Case.exceptionMessage.errorDeletingDataSourceFromTextIndex=An error occurred while removing the data source from the text index.",})
2471 Void deleteDataSource(ProgressIndicator progressIndicator, Object additionalParams)
throws CaseActionException {
2472 assert (additionalParams instanceof Long);
2473 open(progressIndicator, null);
2475 progressIndicator.progress(Bundle.Case_progressMessage_deletingDataSource());
2476 Long dataSourceObjectID = (Long) additionalParams;
2478 DataSource dataSource = this.caseDb.getDataSource(dataSourceObjectID);
2479 if (dataSource == null) {
2480 throw new CaseActionException(Bundle.Case_exceptionMessage_dataSourceNotFound());
2482 SleuthkitCaseAdminUtil.deleteDataSource(this.caseDb, dataSourceObjectID);
2483 }
catch (TskDataException | TskCoreException ex) {
2484 throw new CaseActionException(Bundle.Case_exceptionMessage_errorDeletingDataSourceFromCaseDb(), ex);
2488 }
catch (KeywordSearchServiceException ex) {
2489 throw new CaseActionException(Bundle.Case_exceptionMessage_errorDeletingDataSourceFromTextIndex(), ex);
2491 eventPublisher.
publish(
new DataSourceDeletedEvent(dataSourceObjectID));
2494 close(progressIndicator);
2509 public SleuthkitCase
createPortableCase(String caseName, File portableCaseFolder)
throws TskCoreException {
2511 if (portableCaseFolder.exists()) {
2512 throw new TskCoreException(
"Portable case folder " + portableCaseFolder.toString() +
" already exists");
2514 if (!portableCaseFolder.mkdirs()) {
2515 throw new TskCoreException(
"Error creating portable case folder " + portableCaseFolder.toString());
2523 portableCaseMetadata.setCaseDatabaseName(SINGLE_USER_CASE_DB_NAME);
2525 throw new TskCoreException(
"Error creating case metadata", ex);
2529 SleuthkitCase portableSleuthkitCase;
2531 portableSleuthkitCase = SleuthkitCase.newCase(dbFilePath);
2533 return portableSleuthkitCase;
2546 if (Thread.currentThread().isInterrupted()) {
2547 throw new CaseActionCancelledException(Bundle.Case_exceptionMessage_cancelled());
2562 "Case.progressMessage.creatingCaseDirectory=Creating case directory..."
2569 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDirectory());
2571 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDirectory());
2583 "Case.progressMessage.switchingLogDirectory=Switching log directory..."
2586 progressIndicator.
progress(Bundle.Case_progressMessage_switchingLogDirectory());
2602 "Case.progressMessage.savingCaseMetadata=Saving case metadata to file...",
2603 "# {0} - exception message",
"Case.exceptionMessage.couldNotSaveCaseMetadata=Failed to save case metadata:\n{0}."
2606 progressIndicator.
progress(Bundle.Case_progressMessage_savingCaseMetadata());
2608 this.metadata.writeToFile();
2610 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotSaveCaseMetadata(ex.getLocalizedMessage()), ex);
2626 "Case.progressMessage.creatingCaseNodeData=Creating coordination service node data...",
2627 "# {0} - exception message",
"Case.exceptionMessage.couldNotCreateCaseNodeData=Failed to create coordination service node data:\n{0}."
2631 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseNodeData());
2635 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseNodeData(ex.getLocalizedMessage()), ex);
2652 "Case.progressMessage.updatingCaseNodeData=Updating coordination service node data...",
2653 "# {0} - exception message",
"Case.exceptionMessage.couldNotUpdateCaseNodeData=Failed to update coordination service node data:\n{0}."
2657 progressIndicator.
progress(Bundle.Case_progressMessage_updatingCaseNodeData());
2663 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotUpdateCaseNodeData(ex.getLocalizedMessage()), ex);
2674 "Case.progressMessage.clearingTempDirectory=Clearing case temp directory..."
2680 progressIndicator.
progress(Bundle.Case_progressMessage_clearingTempDirectory());
2696 "Case.progressMessage.creatingCaseDatabase=Creating case database...",
2697 "# {0} - exception message",
"Case.exceptionMessage.couldNotGetDbServerConnectionInfo=Failed to get case database server conneciton info:\n{0}.",
2698 "# {0} - exception message",
"Case.exceptionMessage.couldNotCreateCaseDatabase=Failed to create case database:\n{0}.",
2699 "# {0} - exception message",
"Case.exceptionMessage.couldNotSaveDbNameToMetadataFile=Failed to save case database name to case metadata file:\n{0}."
2702 progressIndicator.
progress(Bundle.Case_progressMessage_creatingCaseDatabase());
2711 metadata.setCaseDatabaseName(SINGLE_USER_CASE_DB_NAME);
2719 metadata.setCaseDatabaseName(caseDb.getDatabaseName());
2721 }
catch (TskCoreException ex) {
2722 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreateCaseDatabase(ex.getLocalizedMessage()), ex);
2724 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotGetDbServerConnectionInfo(ex.getLocalizedMessage()), ex);
2726 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotSaveDbNameToMetadataFile(ex.getLocalizedMessage()), ex);
2742 "Case.progressMessage.openingCaseDatabase=Opening case database...",
2743 "# {0} - exception message",
"Case.exceptionMessage.couldNotOpenCaseDatabase=Failed to open case database:\n{0}.",
2744 "# {0} - exception message",
"Case.exceptionMessage.unsupportedSchemaVersionMessage=Unsupported case database schema version:\n{0}.",
2745 "Case.exceptionMessage.contentProviderCouldNotBeFound=Content provider was specified for the case but could not be loaded.",
2746 "Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-User."
2749 progressIndicator.
progress(Bundle.Case_progressMessage_openingCaseDatabase());
2755 if (metadata.
getContentProviderName().trim().toUpperCase().startsWith(CT_PROVIDER_PREFIX.toUpperCase())) {
2758 throw new CaseActionException(Bundle.Case_exceptionMessage_contentProviderCouldNotBeFound());
2766 throw new CaseActionException(Bundle.Case_open_exception_multiUserCaseNotEnabled());
2769 }
catch (TskUnsupportedSchemaVersionException ex) {
2770 throw new CaseActionException(Bundle.Case_exceptionMessage_unsupportedSchemaVersionMessage(ex.getLocalizedMessage()), ex);
2772 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotGetDbServerConnectionInfo(ex.getLocalizedMessage()), ex);
2773 }
catch (TskCoreException ex) {
2774 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotOpenCaseDatabase(ex.getLocalizedMessage()), ex);
2789 Collection<? extends AutopsyContentProvider> customContentProviders = Lookup.getDefault().lookupAll(
AutopsyContentProvider.class);
2790 if (customContentProviders != null) {
2793 if (customProvider == null || !StringUtils.equalsIgnoreCase(providerName, customProvider.getName())) {
2797 ContentStreamProvider contentProvider = customProvider.load();
2798 if (contentProvider != null) {
2799 return contentProvider;
2815 "Case.progressMessage.openingCaseLevelServices=Opening case-level services...",})
2817 progressIndicator.
progress(Bundle.Case_progressMessage_openingCaseLevelServices());
2818 this.caseServices =
new Services(caseDb);
2824 caseDb.registerForEvents(sleuthkitEventListener);
2839 @NbBundle.Messages({
2840 "Case.progressMessage.openingApplicationServiceResources=Opening application service case resources...",
2841 "# {0} - service name",
"Case.serviceOpenCaseResourcesProgressIndicator.title={0} Opening Case Resources",
2842 "# {0} - service name",
"Case.serviceOpenCaseResourcesProgressIndicator.cancellingMessage=Cancelling opening case resources by {0}...",
2843 "# {0} - service name",
"Case.servicesException.notificationTitle={0} Error"
2854 progressIndicator.
progress(Bundle.Case_progressMessage_openingApplicationServiceResources());
2866 cancelButtonListener =
new CancelButtonListener(Bundle.Case_serviceOpenCaseResourcesProgressIndicator_cancellingMessage(service.getServiceName()));
2869 Bundle.Case_serviceOpenCaseResourcesProgressIndicator_title(service.getServiceName()),
2870 new String[]{Bundle.Case_progressIndicatorCancelButton_label()},
2871 Bundle.Case_progressIndicatorCancelButton_label(),
2872 cancelButtonListener);
2876 appServiceProgressIndicator.
start(Bundle.Case_progressMessage_preparing());
2878 String threadNameSuffix = service.getServiceName().replaceAll(
"[ ]",
"-");
2879 threadNameSuffix = threadNameSuffix.toLowerCase();
2881 ExecutorService executor = Executors.newSingleThreadExecutor(threadFactory);
2882 Future<Void> future = executor.submit(() -> {
2883 service.openCaseResources(context);
2886 if (null != cancelButtonListener) {
2898 }
catch (InterruptedException discarded) {
2903 future.cancel(
true);
2904 }
catch (CancellationException discarded) {
2912 }
catch (ExecutionException ex) {
2919 Case.
logger.log(Level.SEVERE, String.format(
"%s failed to open case resources for %s", service.getServiceName(), this.
getDisplayName()), ex);
2921 SwingUtilities.invokeLater(() -> {
2933 appServiceProgressIndicator.
finish();
2951 "Case.progressMessage.settingUpNetworkCommunications=Setting up network communications...",
2952 "# {0} - exception message",
"Case.exceptionMessage.couldNotOpenRemoteEventChannel=Failed to open remote events channel:\n{0}.",
2953 "# {0} - exception message",
"Case.exceptionMessage.couldNotCreatCollaborationMonitor=Failed to create collaboration monitor:\n{0}."
2957 progressIndicator.
progress(Bundle.Case_progressMessage_settingUpNetworkCommunications());
2961 collaborationMonitor =
new CollaborationMonitor(metadata.
getCaseName());
2963 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotOpenRemoteEventChannel(ex.getLocalizedMessage()), ex);
2964 }
catch (CollaborationMonitor.CollaborationMonitorException ex) {
2965 throw new CaseActionException(Bundle.Case_exceptionMessage_couldNotCreatCollaborationMonitor(ex.getLocalizedMessage()), ex);
2993 Bundle.Case_progressIndicatorTitle_closingCase());
2997 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
3006 Future<Void> future = caseActionExecutor.submit(() -> {
3008 close(progressIndicator);
3015 progressIndicator.
progress(Bundle.Case_progressMessage_preparing());
3017 if (null == resourcesLock) {
3018 throw new CaseActionException(Bundle.Case_creationException_couldNotAcquireResourcesLock());
3020 close(progressIndicator);
3034 }
catch (InterruptedException | CancellationException unused) {
3041 }
catch (ExecutionException ex) {
3042 throw new CaseActionException(Bundle.Case_exceptionMessage_execExceptionWrapperMessage(ex.getCause().getMessage()), ex);
3045 progressIndicator.
finish();
3055 "Case.progressMessage.shuttingDownNetworkCommunications=Shutting down network communications...",
3056 "Case.progressMessage.closingApplicationServiceResources=Closing case-specific application service resources...",
3057 "Case.progressMessage.closingCaseDatabase=Closing case database..."
3067 progressIndicator.
progress(Bundle.Case_progressMessage_shuttingDownNetworkCommunications());
3068 if (null != collaborationMonitor) {
3069 collaborationMonitor.shutdown();
3078 progressIndicator.
progress(Bundle.Case_progressMessage_closingApplicationServiceResources());
3084 if (null != caseDb) {
3085 progressIndicator.
progress(Bundle.Case_progressMessage_closingCaseDatabase());
3086 caseDb.unregisterForEvents(sleuthkitEventListener);
3098 progressIndicator.
progress(Bundle.Case_progressMessage_switchingLogDirectory());
3107 "# {0} - serviceName",
"Case.serviceCloseResourcesProgressIndicator.title={0} Closing Case Resources",
3108 "# {0} - service name",
"# {1} - exception message",
"Case.servicesException.serviceResourcesCloseError=Could not close case resources for {0} service: {1}"
3121 Bundle.Case_serviceCloseResourcesProgressIndicator_title(service.getServiceName()));
3125 progressIndicator.
start(Bundle.Case_progressMessage_preparing());
3127 String threadNameSuffix = service.getServiceName().replaceAll(
"[ ]",
"-");
3128 threadNameSuffix = threadNameSuffix.toLowerCase();
3130 ExecutorService executor = Executors.newSingleThreadExecutor(threadFactory);
3131 Future<Void> future = executor.submit(() -> {
3132 service.closeCaseResources(context);
3137 }
catch (InterruptedException ex) {
3138 Case.
logger.log(Level.SEVERE, String.format(
"Unexpected interrupt while waiting on %s service to close case resources", service.getServiceName()), ex);
3139 }
catch (CancellationException ex) {
3140 Case.
logger.log(Level.SEVERE, String.format(
"Unexpected cancellation while waiting on %s service to close case resources", service.getServiceName()), ex);
3141 }
catch (ExecutionException ex) {
3142 Case.
logger.log(Level.SEVERE, String.format(
"%s service failed to open case resources", service.getServiceName()), ex);
3145 Bundle.Case_servicesException_notificationTitle(service.getServiceName()),
3146 Bundle.Case_servicesException_serviceResourcesCloseError(service.getServiceName(), ex.getLocalizedMessage())));
3150 progressIndicator.
finish();
3161 "Case.lockingException.couldNotAcquireSharedLock=Failed to get a shared lock on the case.",
3162 "Case.lockingException.couldNotAcquireExclusiveLock=Failed to get an exclusive lock on the case."
3173 throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireSharedLock());
3175 throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireExclusiveLock());
3180 throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireSharedLock(), ex);
3182 throw new CaseActionException(Bundle.Case_lockingException_couldNotAcquireExclusiveLock(), ex);
3196 logger.log(Level.SEVERE, String.format(
"Failed to release shared case directory lock for %s",
getMetadata().
getCaseDirectory()), ex);
3209 if (!subDirectory.exists()) {
3210 subDirectory.mkdirs();
3212 return subDirectory.toString();
3228 "Case.exceptionMessage.errorsDeletingCase=Errors occured while deleting the case. See the application log for details."
3231 boolean errorsOccurred =
false;
3235 errorsOccurred =
true;
3241 }
catch (CaseActionException ex) {
3242 errorsOccurred =
true;
3248 if (errorsOccurred) {
3249 throw new CaseActionException(Bundle.Case_exceptionMessage_errorsDeletingCase());
3273 "Case.progressMessage.connectingToCoordSvc=Connecting to coordination service...",
3274 "# {0} - exception message",
"Case.exceptionMessage.failedToConnectToCoordSvc=Failed to connect to coordination service:\n{0}.",
3275 "Case.exceptionMessage.cannotGetLockToDeleteCase=Cannot delete case because it is open for another user or host.",
3276 "# {0} - exception message",
"Case.exceptionMessage.failedToLockCaseForDeletion=Failed to exclusively lock case for deletion:\n{0}.",
3277 "Case.progressMessage.fetchingCoordSvcNodeData=Fetching coordination service node data for the case...",
3278 "# {0} - exception message",
"Case.exceptionMessage.failedToFetchCoordSvcNodeData=Failed to fetch coordination service node data:\n{0}.",
3279 "Case.progressMessage.deletingResourcesCoordSvcNode=Deleting case resources coordination service node...",
3280 "Case.progressMessage.deletingCaseDirCoordSvcNode=Deleting case directory coordination service node..."
3283 progressIndicator.
progress(Bundle.Case_progressMessage_connectingToCoordSvc());
3289 throw new CaseActionException(Bundle.Case_exceptionMessage_failedToConnectToCoordSvc(ex.getLocalizedMessage()));
3293 boolean errorsOccurred =
false;
3295 if (dirLock == null) {
3297 throw new CaseActionException(Bundle.Case_exceptionMessage_cannotGetLockToDeleteCase());
3300 progressIndicator.
progress(Bundle.Case_progressMessage_fetchingCoordSvcNodeData());
3305 throw new CaseActionException(Bundle.Case_exceptionMessage_failedToFetchCoordSvcNodeData(ex.getLocalizedMessage()));
3310 progressIndicator.
progress(Bundle.Case_progressMessage_deletingResourcesCoordSvcNode());
3316 errorsOccurred =
true;
3317 logger.log(Level.WARNING, String.format(
"Error deleting the case resources coordination service node for the case at %s (%s) in %s", metadata.
getCaseDisplayName(), metadata.
getCaseName(), metadata.
getCaseDirectory()), ex);
3319 }
catch (InterruptedException ex) {
3320 logger.log(Level.WARNING, String.format(
"Error deleting the case resources coordination service node for the case at %s (%s) in %s", metadata.
getCaseDisplayName(), metadata.
getCaseName(), metadata.
getCaseDirectory()), ex);
3325 throw new CaseActionException(Bundle.Case_exceptionMessage_failedToLockCaseForDeletion(ex.getLocalizedMessage()));
3328 if (!errorsOccurred) {
3329 progressIndicator.
progress(Bundle.Case_progressMessage_deletingCaseDirCoordSvcNode());
3335 errorsOccurred =
true;
3339 if (errorsOccurred) {
3340 throw new CaseActionException(Bundle.Case_exceptionMessage_errorsDeletingCase());
3370 boolean errorsOccurred =
false;
3377 errorsOccurred =
true;
3380 errorsOccurred =
true;
3382 }
catch (CaseActionException ex) {
3383 errorsOccurred =
true;
3386 return errorsOccurred;
3410 "Case.progressMessage.deletingCaseDatabase=Deleting case database..."
3414 progressIndicator.
progress(Bundle.Case_progressMessage_deletingCaseDatabase());
3415 logger.log(Level.INFO, String.format(
"Deleting case database for %s (%s) in %s", caseNodeData.
getDisplayName(), caseNodeData.
getName(), caseNodeData.
getDirectory()));
3417 String url =
"jdbc:postgresql://" + info.getHost() +
":" + info.getPort() +
"/postgres";
3418 Class.forName(
"org.postgresql.Driver");
3419 try (Connection connection = DriverManager.getConnection(url, info.getUserName(), info.getPassword()); Statement statement = connection.createStatement()) {
3420 String dbExistsQuery =
"SELECT 1 from pg_database WHERE datname = '" + metadata.
getCaseDatabaseName() +
"'";
3421 try (ResultSet queryResult = statement.executeQuery(dbExistsQuery)) {
3422 if (queryResult.next()) {
3424 statement.execute(deleteCommand);
3465 "Case.progressMessage.deletingTextIndex=Deleting text index..."
3468 progressIndicator.
progress(Bundle.Case_progressMessage_deletingTextIndex());
3472 searchService.deleteTextIndex(metadata);
3508 "Case.progressMessage.deletingCaseDirectory=Deleting case directory..."
3511 progressIndicator.
progress(Bundle.Case_progressMessage_deletingCaseDirectory());
3513 throw new CaseActionException(String.format(
"Failed to delete %s", metadata.
getCaseDirectory()));
3525 "Case.progressMessage.removingCaseFromRecentCases=Removing case from Recent Cases menu..."
3529 progressIndicator.
progress(Bundle.Case_progressMessage_removingCaseFromRecentCases());
3530 SwingUtilities.invokeLater(() -> {
3546 boolean isNodeNodeEx =
false;
3547 Throwable cause = ex.getCause();
3548 if (cause != null) {
3549 String causeMessage = cause.getMessage();
3550 isNodeNodeEx = causeMessage.contains(NO_NODE_ERROR_MSG_FRAGMENT);
3552 return isNodeNodeEx;
3571 logger.log(Level.SEVERE, String.format(
"Error updating deleted item flag %s for %s (%s) in %s", flag.name(), caseNodeData.
getDisplayName(), caseNodeData.
getName(), caseNodeData.
getDirectory()), ex);
3590 if (!hasDataSource) {
3605 String query =
"SELECT count(*) AS count FROM (SELECT * FROM data_source_info LIMIT 1)t";
3606 try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
3607 ResultSet resultSet = dbQuery.getResultSet();
3608 if (resultSet.next()) {
3609 return resultSet.getLong(
"count") > 0;
3612 }
catch (SQLException ex) {
3613 logger.log(Level.SEVERE,
"Error accessing case database", ex);
3614 throw new TskCoreException(
"Error accessing case databse", ex);
3629 String query =
"SELECT SUM(cnt) total FROM "
3630 +
"(SELECT COUNT(*) AS cnt FROM "
3631 +
"(SELECT * FROM tsk_objects LIMIT 1)t "
3633 +
"SELECT COUNT(*) AS cnt FROM "
3634 +
"(SELECT * FROM tsk_hosts LIMIT 1)r) s";
3635 try (SleuthkitCase.CaseDbQuery dbQuery = caseDb.executeQuery(query)) {
3636 ResultSet resultSet = dbQuery.getResultSet();
3637 if (resultSet.next()) {
3638 return resultSet.getLong(
"total") > 0;
3642 }
catch (SQLException ex) {
3643 logger.log(Level.SEVERE,
"Error accessing case database", ex);
3644 throw new TskCoreException(
"Error accessing case databse", ex);
3668 R
execute(T progressIndicator, V additionalParams)
throws CaseActionException;
3766 ((ModalDialogProgressIndicator) progressIndicator).
setCancelling(cancellationMessage);
3795 return new Thread(task, threadName);
3832 public static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner)
throws CaseActionException {
3857 public static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner,
CaseType caseType)
throws CaseActionException {
3873 public static void open(String caseMetadataFilePath)
throws CaseActionException {
3930 return new File(filePath).isFile();
3969 return "ModuleOutput";
3982 public static PropertyChangeSupport
3984 return new PropertyChangeSupport(
Case.class
4016 public Image
addImage(String imgPath,
long imgId, String timeZone)
throws CaseActionException {
4018 Image newDataSource = caseDb.getImageById(imgId);
4020 return newDataSource;
4021 }
catch (TskCoreException ex) {
4022 throw new CaseActionException(NbBundle.getMessage(
this.getClass(),
"Case.addImg.exception.msg"), ex);
4049 public void deleteReports(Collection<? extends Report> reports,
boolean deleteFromDisk)
throws TskCoreException {
String getLogDirectoryPath()
static final AutopsyEventPublisher eventPublisher
List< Content > getDataSources()
String getModuleOutputDirectoryRelativePath()
static CaseNodeData createCaseNodeData(final CaseMetadata metadata)
void notifyContentTagDeleted(ContentTag deletedTag)
Case(CaseMetadata caseMetaData)
static CaseType fromString(String typeName)
final SleuthkitEventListener sleuthkitEventListener
static final String CASE_ACTION_THREAD_NAME
static void setDeletedItemFlag(CaseNodeData caseNodeData, CaseNodeData.DeletedFlags flag)
void publishLocally(AutopsyEvent event)
static void createAsCurrentCase(CaseType caseType, String caseDir, CaseDetails caseDetails)
static String getCaseDirectoryNodePath(Path caseDirectoryPath)
void notifyBlackBoardArtifactTagDeleted(BlackboardArtifactTag deletedTag)
String getExaminerPhone()
Void open(ProgressIndicator progressIndicator, Object additionalParams)
Set< TimeZone > getTimeZones()
CoordinationService.Lock caseLock
static boolean deleteMultiUserCase(CaseNodeData caseNodeData, CaseMetadata metadata, ProgressIndicator progressIndicator, Logger logger)
static String getNameForTitle()
Image addImage(String imgPath, long imgId, String timeZone)
void publishOsAccountsUpdatedEvent(TskEvent.OsAccountsUpdatedTskEvent event)
static synchronized IngestManager getInstance()
void deleteNode(CategoryNode category, String nodePath)
static final ExecutorService openFileSystemsExecutor
static final String NO_NODE_ERROR_MSG_FRAGMENT
void publishPersonsUpdatedEvent(TskEvent.PersonsUpdatedTskEvent event)
static boolean runningWithGUI
static void closeCurrentCase()
void publishHostsDeletedEvent(TskEvent.HostsDeletedTskEvent event)
void setDeletedFlag(DeletedFlags flag)
void acquireCaseLock(CaseLockType lockType)
String getTempDirectory()
static boolean existsCurrentCase()
boolean isDeletedFlagSet(DeletedFlags flag)
static void removePropertyChangeListener(PropertyChangeListener listener)
void start(String message, int totalWorkUnits)
static final Logger logger
void notifyBlackBoardArtifactTagAdded(BlackboardArtifactTag newTag, List< BlackboardArtifactTag > removedTagList)
void publish(AutopsyEvent event)
String getLocalizedDisplayName()
static Future<?> backgroundOpenFileSystemsFuture
ADDING_DATA_SOURCE_FAILED
static final String EXPORT_FOLDER
static void createCaseDirectory(String caseDirPath, CaseType caseType)
String getCaseDirectory()
static String getAppName()
void publishOsAccountInstancesAddedEvent(TskEvent.OsAcctInstancesAddedTskEvent event)
void notifyTagDefinitionChanged(String changedTagName)
void openFileSystemsInBackground()
void notifyContentTagAdded(ContentTag newTag, List< ContentTag > deletedTagList)
void deleteDataSource(Long dataSourceId)
static volatile Frame mainFrame
static String convertTimeZone(String timeZoneId)
static boolean driveExists(String path)
static void openCoreWindows()
static void deleteSingleUserCase(CaseMetadata metadata, ProgressIndicator progressIndicator)
void addSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
void publishHostsAddedToPersonEvent(TskEvent.HostsAddedToPersonTskEvent event)
void publishTimelineEventAddedEvent(TimelineManager.TimelineEventAddedEvent event)
synchronized static void setLogDirectory(String directoryPath)
volatile ExecutorService caseActionExecutor
void notifyCentralRepoCommentChanged(long contentId, String newComment)
static final String APP_NAME
TaskThreadFactory(String threadName)
static final String CACHE_FOLDER
static String getAutopsyVersion()
CaseType(String typeName)
List< Image > getImages()
static void deleteMultiUserCaseDirectory(CaseNodeData caseNodeData, CaseMetadata metadata, ProgressIndicator progressIndicator, Logger logger)
Case(CaseType caseType, String caseDir, CaseDetails caseDetails)
String getReportDirectory()
static String getCaseResourcesNodePath(Path caseDirectoryPath)
static CaseNodeData readCaseNodeData(String nodePath)
static boolean getIsMultiUserModeEnabled()
void addReport(String localPath, String srcModuleName, String reportName)
static void updateGUIForCaseOpened(Case newCurrentCase)
void notifyDataSourceNameChanged(Content dataSource, String newName)
static String getCustomTempDirectory()
static CaseDbConnectionInfo getDatabaseConnectionInfo()
String getModulesOutputDirAbsPath()
static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner, CaseType caseType)
void publishPersonsDeletedEvent(TskEvent.PersonsDeletedTskEvent event)
void closeAppServiceCaseResources()
static final int CASE_LOCK_TIMEOUT_MINS
static final String SINGLE_USER_CASE_DB_NAME
static void deleteCase(CaseMetadata metadata)
void deleteReports(Collection<?extends Report > reports, boolean deleteFromDisk)
synchronized void closeRemoteEventChannel()
KeywordSearchService getKeywordSearchService()
static final int CASE_RESOURCES_LOCK_TIMEOUT_HOURS
final long MAX_IMAGE_THRESHOLD
List< Report > getAllReports()
static boolean canAddDataSources()
static boolean isValidName(String caseName)
void openCaseDataBase(ProgressIndicator progressIndicator)
void createCaseDirectoryIfDoesNotExist(ProgressIndicator progressIndicator)
CollaborationMonitor collaborationMonitor
void openCommunicationChannels(ProgressIndicator progressIndicator)
static void shutDownTaskExecutor(ExecutorService executor)
static void closeCoreWindows()
ProgressIndicator getProgressIndicator()
static String getModulesOutputDirRelPath()
void saveCaseMetadataToFile(ProgressIndicator progressIndicator)
static void deleteMultiUserCaseTextIndex(CaseNodeData caseNodeData, CaseMetadata metadata, ProgressIndicator progressIndicator, Logger logger)
void doOpenCaseAction(String progressIndicatorTitle, CaseAction< ProgressIndicator, Object, Void > caseAction, CaseLockType caseLockType, boolean allowCancellation, Object additionalParams)
void publisHostsRemovedFromPersonEvent(TskEvent.HostsRemovedFromPersonTskEvent event)
Set< TimeZone > getTimeZone()
static void writeCaseNodeData(CaseNodeData nodeData)
static final String MODULE_FOLDER
static final String CT_PROVIDER_PREFIX
void openCaseLevelServices(ProgressIndicator progressIndicator)
static void create(String caseDir, String caseDisplayName, String caseNumber, String examiner)
void openFileSystems(List< Image > images)
Path getBaseSystemTempPath()
synchronized void openRemoteEventChannel(String channelName)
String getCaseDisplayName()
void publishPersonsAddedEvent(TskEvent.PersonsAddedTskEvent event)
void createCaseNodeData(ProgressIndicator progressIndicator)
void publicTagNamesAdded(TskEvent.TagNamesAddedTskEvent event)
static final String PLACEHOLDER_DS_PATH_REGEX
static void invokeStartupDialog()
void updateDataParameters()
CaseMetadata getMetadata()
static String displayNameToUniqueName(String caseDisplayName)
static void deleteFromRecentCases(CaseMetadata metadata, ProgressIndicator progressIndicator)
static void openAsCurrentCase(String caseMetadataFilePath)
static void removeEventSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
Lock tryGetExclusiveLock(CategoryNode category, String nodePath, int timeOut, TimeUnit timeUnit)
static boolean isNoNodeException(CoordinationServiceException ex)
default void setCancelling(String cancellingMessage)
void setLastAccessDate(Date lastAccessDate)
void close(ProgressIndicator progressIndicator)
final ProgressIndicator progressIndicator
SleuthkitCase getSleuthkitCase()
void notifyBlackBoardArtifactTagAdded(BlackboardArtifactTag newTag)
static PropertyChangeSupport getPropertyChangeSupport()
void publishOsAccountDeletedEvent(TskEvent.OsAccountsDeletedTskEvent event)
String getCacheDirectory()
static void addPropertyChangeListener(PropertyChangeListener listener)
void publishHostsUpdatedEvent(TskEvent.HostsUpdatedTskEvent event)
void removeSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
String getModuleDirectory()
void createCaseDatabase(ProgressIndicator progressIndicator)
Thread newThread(Runnable task)
static void removeEventSubscriber(String eventName, PropertyChangeListener subscriber)
void switchLoggingToCaseLogsDirectory(ProgressIndicator progressIndicator)
void publicTagSetsDeleted(TskEvent.TagSetsDeletedTskEvent event)
final CaseMetadata metadata
static void deleteTextIndex(CaseMetadata metadata, ProgressIndicator progressIndicator)
void deleteTempfilesFromCaseDirectory(ProgressIndicator progressIndicator)
void deleteReports(Collection<?extends Report > reports)
void notifyDataSourceAdded(Content dataSource, UUID addingDataSourceEventId)
static ContentStreamProvider loadContentProvider(String providerName)
Report addReport(String localPath, String srcModuleName, String reportName, Content parent)
static boolean pathExists(String filePath)
SleuthkitCase createPortableCase(String caseName, File portableCaseFolder)
R execute(T progressIndicator, V additionalParams)
BLACKBOARD_ARTIFACT_TAG_ADDED
static void open(String caseMetadataFilePath)
static void openAsCurrentCase(Case newCurrentCase, boolean isNewCase)
static TempDirChoice getTempDirChoice()
static CoordinationService.Lock acquireCaseResourcesLock(String caseDir)
String getOutputDirectory()
static void error(String title, String message)
String getOrCreateSubdirectory(String subDirectoryName)
boolean equalsName(String otherTypeName)
static final String EVENT_CHANNEL_NAME
static Case getCurrentCase()
static String getLocalHostName()
synchronized static Logger getLogger(String name)
void publishOsAccountsAddedEvent(TskEvent.OsAccountsAddedTskEvent event)
static Case getCurrentCaseThrows()
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
static String convertToAlphaNumericFormat(String timeZoneId)
static final String LOG_FOLDER
Void create(ProgressIndicator progressIndicator, Object additionalParams)
Lock tryGetSharedLock(CategoryNode category, String nodePath, int timeOut, TimeUnit timeUnit)
String getConfigDirectory()
static String getAppName()
static synchronized CoordinationService getInstance()
static volatile Case currentCase
static String getVersion()
void openAppServiceCaseResources(ProgressIndicator progressIndicator, boolean isNewCase)
String getExportDirectory()
static void updateGUIForCaseClosed()
void notifyAddingDataSource(UUID eventId)
static void addEventSubscriber(String eventName, PropertyChangeListener subscriber)
void notifyContentTagAdded(ContentTag newTag)
void cancelAllIngestJobs(IngestJob.CancellationReason reason)
static final String CASE_RESOURCES_THREAD_NAME
static StartupWindowProvider getInstance()
static void deleteCurrentCase()
void publishHostsAddedEvent(TskEvent.HostsAddedTskEvent event)
static boolean deleteDir(File dirPath)
static void createAsCurrentCase(String caseDir, String caseDisplayName, String caseNumber, String examiner, CaseType caseType)
void publicTagNamesUpdated(TskEvent.TagNamesUpdatedTskEvent event)
static void deleteCaseDirectory(CaseMetadata metadata, ProgressIndicator progressIndicator)
static synchronized DirectoryTreeTopComponent findInstance()
void notifyFailedAddingDataSource(UUID addingDataSourceEventId)
static void deleteMultiUserCase(CaseMetadata metadata, ProgressIndicator progressIndicator)
static final String CONFIG_FOLDER
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
static final Object caseActionSerializationLock
boolean dbHasDataSource()
static void deleteMultiUserCaseDatabase(CaseNodeData caseNodeData, CaseMetadata metadata, ProgressIndicator progressIndicator, Logger logger)
void publicTagNamesDeleted(TskEvent.TagNamesDeletedTskEvent event)
static boolean isCaseOpen()
String getTextIndexName()
static final String REPORTS_FOLDER
void progress(String message)
HOSTS_REMOVED_FROM_PERSON
static final String TEMP_FOLDER
BLACKBOARD_ARTIFACT_TAG_DELETED
static void checkForCancellation()
static boolean canDeleteCurrentCase()
static void addEventSubscriber(Set< String > eventNames, PropertyChangeListener subscriber)
void updateCaseNodeData(ProgressIndicator progressIndicator)
static void error(String message)
void publicTagSetsAdded(TskEvent.TagSetsAddedTskEvent event)
final SleuthkitCase tskCase
String getExaminerEmail()