19 package org.sleuthkit.autopsy.report.modules.portablecase;
21 import com.google.common.collect.ArrayListMultimap;
22 import com.google.common.collect.Multimap;
23 import com.google.gson.Gson;
24 import com.google.gson.GsonBuilder;
25 import com.google.gson.JsonElement;
26 import com.google.gson.stream.JsonWriter;
28 import java.util.logging.Level;
29 import java.io.BufferedReader;
31 import java.io.FileOutputStream;
32 import java.io.FileWriter;
33 import java.io.InputStreamReader;
34 import java.io.IOException;
35 import java.io.OutputStream;
36 import java.io.OutputStreamWriter;
37 import java.nio.file.Files;
38 import java.nio.file.Path;
39 import java.nio.file.Paths;
40 import java.sql.ResultSet;
41 import java.sql.SQLException;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.Collection;
45 import java.util.HashMap;
46 import java.util.List;
48 import org.apache.commons.io.FileUtils;
49 import org.openide.modules.InstalledFileLocator;
50 import org.openide.util.NbBundle;
66 import org.
sleuthkit.datamodel.Blackboard.BlackboardException;
81 import org.
sleuthkit.datamodel.OsAccountManager.NotUserSIDException;
87 import org.
sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction;
89 import org.
sleuthkit.datamodel.TaggingManager.ContentTagChange;
94 import org.
sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper;
95 import org.
sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil;
96 import org.
sleuthkit.datamodel.blackboardutils.attributes.MessageAttachments;
117 private static final List<Integer>
SPECIALLY_HANDLED_ATTRS = Arrays.asList(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID(),
118 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ATTACHMENTS.getTypeID(), BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID());
157 "PortableCaseReportModule.getName.name=Portable Case"
161 return Bundle.PortableCaseReportModule_getName_name();
165 "PortableCaseReportModule.getDescription.description=Copies selected items to a new single-user case that can be easily shared"
169 return Bundle.PortableCaseReportModule_getDescription_description();
189 logger.log(Level.INFO,
"Portable case creation canceled by user");
207 logger.log(Level.WARNING, logWarning);
209 logger.log(Level.SEVERE, logWarning, ex);
217 "PortableCaseReportModule.generateReport.verifying=Verifying selected parameters...",
218 "PortableCaseReportModule.generateReport.creatingCase=Creating portable case database...",
219 "PortableCaseReportModule.generateReport.copyingTags=Copying tags...",
221 "PortableCaseReportModule.generateReport.copyingFiles=Copying files tagged as {0}...",
223 "PortableCaseReportModule.generateReport.copyingArtifacts=Copying artifacts tagged as {0}...",
224 "# {0} - output folder",
225 "PortableCaseReportModule.generateReport.outputDirDoesNotExist=Output folder {0} does not exist",
226 "# {0} - output folder",
227 "PortableCaseReportModule.generateReport.outputDirIsNotDir=Output folder {0} is not a folder",
228 "PortableCaseReportModule.generateReport.caseClosed=Current case has been closed",
229 "PortableCaseReportModule.generateReport.interestingItemError=Error loading intersting items",
230 "PortableCaseReportModule.generateReport.errorReadingTags=Error while reading tags from case database",
231 "PortableCaseReportModule.generateReport.errorReadingSets=Error while reading interesting items sets from case database",
232 "PortableCaseReportModule.generateReport.noContentToCopy=No interesting files, results, or tagged items to copy",
233 "PortableCaseReportModule.generateReport.errorCopyingTags=Error copying tags",
234 "PortableCaseReportModule.generateReport.errorCopyingFiles=Error copying tagged files",
235 "PortableCaseReportModule.generateReport.errorCopyingArtifacts=Error copying tagged artifacts",
236 "PortableCaseReportModule.generateReport.errorCopyingInterestingFiles=Error copying interesting files",
237 "PortableCaseReportModule.generateReport.errorCopyingInterestingResults=Error copying interesting results",
238 "PortableCaseReportModule.generateReport.errorCreatingImageTagTable=Error creating image tags table",
239 "PortableCaseReportModule.generateReport.errorCopyingAutopsy=Error copying application",
240 "# {0} - attribute type name",
241 "PortableCaseReportModule.generateReport.errorLookingUpAttrType=Error looking up attribute type {0}",
242 "PortableCaseReportModule.generateReport.compressingCase=Compressing case...",
243 "PortableCaseReportModule_generateReport_copyingAutopsy=Copying application..."
249 @SuppressWarnings(
"deprecation")
251 this.settings = options;
253 progressPanel.
start();
254 progressPanel.
updateStatusLabel(Bundle.PortableCaseReportModule_generateReport_verifying());
260 File outputDir =
new File(reportPath);
261 if (!outputDir.exists()) {
262 handleError(
"Output folder " + outputDir.toString() +
" does not exist",
263 Bundle.PortableCaseReportModule_generateReport_outputDirDoesNotExist(outputDir.toString()), null, progressPanel);
267 if (!outputDir.isDirectory()) {
268 handleError(
"Output folder " + outputDir.toString() +
" is not a folder",
269 Bundle.PortableCaseReportModule_generateReport_outputDirIsNotDir(outputDir.toString()), null, progressPanel);
279 Bundle.PortableCaseReportModule_generateReport_caseClosed(), null, progressPanel);
285 outputDir = Paths.get(outputDir.toString(),
caseName).toFile();
288 List<TagName> tagNames;
294 Bundle.PortableCaseReportModule_generateReport_errorReadingTags(), ex, progressPanel);
301 List<String> setNames;
306 handleError(
"Unable to get all interesting items sets",
307 Bundle.PortableCaseReportModule_generateReport_errorReadingSets(), ex, progressPanel);
314 if (tagNames.isEmpty() && setNames.isEmpty()) {
316 Bundle.PortableCaseReportModule_generateReport_noContentToCopy(), null, progressPanel);
322 progressPanel.
updateStatusLabel(Bundle.PortableCaseReportModule_generateReport_creatingCase());
324 if (portableSkCase == null) {
338 }
catch (TskCoreException ex) {
339 handleError(
"Error creating image tag table", Bundle.PortableCaseReportModule_generateReport_errorCreatingImageTagTable(), ex, progressPanel);
344 progressPanel.
updateStatusLabel(Bundle.PortableCaseReportModule_generateReport_copyingTags());
346 for (TagName tagName : tagNames) {
347 TagName newTagName = portableSkCase.getTaggingManager().addOrUpdateTagName(tagName.getDisplayName(), tagName.getDescription(), tagName.getColor(), tagName.getKnownStatus());
348 oldTagNameToNewTagName.put(tagName, newTagName);
350 }
catch (TskCoreException ex) {
351 handleError(
"Error copying tags", Bundle.PortableCaseReportModule_generateReport_errorCopyingTags(), ex, progressPanel);
356 for (BlackboardArtifact.ARTIFACT_TYPE type : BlackboardArtifact.ARTIFACT_TYPE.values()) {
357 oldArtTypeIdToNewArtTypeId.put(type.getTypeID(), type.getTypeID());
359 for (BlackboardAttribute.ATTRIBUTE_TYPE type : BlackboardAttribute.ATTRIBUTE_TYPE.values()) {
362 }
catch (TskCoreException ex) {
363 handleError(
"Error looking up attribute name " + type.getLabel(),
364 Bundle.PortableCaseReportModule_generateReport_errorLookingUpAttrType(type.getLabel()),
371 for (TagName tagName : tagNames) {
377 progressPanel.
updateStatusLabel(Bundle.PortableCaseReportModule_generateReport_copyingFiles(tagName.getDisplayName()));
386 }
catch (TskCoreException ex) {
387 handleError(
"Error copying tagged files", Bundle.PortableCaseReportModule_generateReport_errorCopyingFiles(), ex, progressPanel);
393 for (TagName tagName : tagNames) {
399 progressPanel.
updateStatusLabel(Bundle.PortableCaseReportModule_generateReport_copyingArtifacts(tagName.getDisplayName()));
408 }
catch (TskCoreException ex) {
409 handleError(
"Error copying tagged artifacts", Bundle.PortableCaseReportModule_generateReport_errorCopyingArtifacts(), ex, progressPanel);
414 if (!setNames.isEmpty()) {
416 List<AnalysisResult> interestingFiles = currentCase.
getSleuthkitCase().getBlackboard().getAnalysisResultsByType(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT.getTypeID());
417 for (AnalysisResult art : interestingFiles) {
424 BlackboardAttribute setAttr = art.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
425 if (setNames.contains(setAttr.getValueString())) {
429 }
catch (TskCoreException ex) {
430 handleError(
"Error copying interesting files", Bundle.PortableCaseReportModule_generateReport_errorCopyingInterestingFiles(), ex, progressPanel);
435 List<AnalysisResult> interestingResults = currentCase.
getSleuthkitCase().getBlackboard().getAnalysisResultsByType(BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT.getTypeID());
436 for (AnalysisResult art : interestingResults) {
442 BlackboardAttribute setAttr = art.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
443 if (setNames.contains(setAttr.getValueString())) {
447 }
catch (TskCoreException ex) {
448 handleError(
"Error copying interesting results", Bundle.PortableCaseReportModule_generateReport_errorCopyingInterestingResults(), ex, progressPanel);
453 List<AnalysisResult> interestingResults = currentCase.
getSleuthkitCase().getBlackboard().getAnalysisResultsByType(BlackboardArtifact.Type.TSK_INTERESTING_ITEM.getTypeID());
454 for (AnalysisResult art : interestingResults) {
460 BlackboardAttribute setAttr = art.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
461 if (setNames.contains(setAttr.getValueString())) {
465 }
catch (TskCoreException ex) {
466 handleError(
"Error copying interesting items", Bundle.PortableCaseReportModule_generateReport_errorCopyingInterestingResults(), ex, progressPanel);
482 progressPanel.
updateStatusLabel(Bundle.PortableCaseReportModule_generateReport_copyingAutopsy());
485 }
catch (IOException ex) {
486 handleError(
"Error copying autopsy", Bundle.PortableCaseReportModule_generateReport_errorCopyingAutopsy(), ex, progressPanel);
492 progressPanel.
updateStatusLabel(Bundle.PortableCaseReportModule_generateReport_compressingCase());
525 "PortableCaseReportModule.generateCaseUcoReport.errorCreatingReportFolder=Could not make report folder",
526 "PortableCaseReportModule.generateCaseUcoReport.errorGeneratingCaseUcoReport=Problem while generating CASE-UCO report",
527 "PortableCaseReportModule.generateCaseUcoReport.startCaseUcoReportGeneration=Creating a CASE-UCO report of the portable case",
528 "PortableCaseReportModule.generateCaseUcoReport.successCaseUcoReportGeneration=Successfully created a CASE-UCO report of the portable case"
532 Path reportsDirectory = Paths.get(caseFolder.toString(),
"Reports");
533 if (!reportsDirectory.toFile().mkdir()) {
534 logger.log(Level.SEVERE,
"Could not make the report folder... skipping "
535 +
"CASE-UCO report generation for the portable case");
539 Path reportFile = reportsDirectory.resolve(CASE_UCO_FILE_NAME);
541 progressPanel.
updateStatusLabel(Bundle.PortableCaseReportModule_generateCaseUcoReport_startCaseUcoReportGeneration());
542 try (OutputStream stream =
new FileOutputStream(reportFile.toFile());
543 JsonWriter reportWriter =
new JsonWriter(
new OutputStreamWriter(stream,
"UTF-8"))) {
544 Gson gson =
new GsonBuilder().setPrettyPrinting().create();
545 reportWriter.setIndent(
" ");
546 reportWriter.beginObject();
547 reportWriter.name(
"@graph");
548 reportWriter.beginArray();
556 Path tmpDir = Paths.get(caseTempDirectory, CASE_UCO_TMP_DIR);
557 FileUtils.deleteDirectory(tmpDir.toFile());
558 Files.createDirectory(tmpDir);
560 CaseUcoExporter exporter =
new CaseUcoExporter(currentCase.
getSleuthkitCase());
561 for (JsonElement element : exporter.exportSleuthkitCase()) {
562 gson.toJson(element, reportWriter);
571 for (DataSource dataSource : currentCase.
getSleuthkitCase().getDataSources()) {
574 boolean dataSourceHasBeenIncluded =
false;
577 for (TagName tagName : tagNames) {
580 dataSource, tmpDir, gson, exporter, reportWriter, dataSourceHasBeenIncluded);
584 dataSource, tmpDir, gson, exporter, reportWriter, dataSourceHasBeenIncluded);
588 for (BlackboardArtifact bArt : artifactsWithSetName.get(dataSource.getId())) {
589 Content sourceContent = bArt.getParent();
590 dataSourceHasBeenIncluded |=
addUniqueFile(sourceContent, dataSource,
591 tmpDir, gson, exporter, reportWriter, dataSourceHasBeenIncluded);
596 reportWriter.endArray();
597 reportWriter.endObject();
598 progressPanel.
updateStatusLabel(Bundle.PortableCaseReportModule_generateCaseUcoReport_successCaseUcoReportGeneration());
599 }
catch (IOException | TskCoreException ex) {
600 progressPanel.
updateStatusLabel(Bundle.PortableCaseReportModule_generateCaseUcoReport_errorGeneratingCaseUcoReport());
601 logger.log(Level.SEVERE,
"Error encountered while trying to create "
602 +
"CASE-UCO output for portable case.. the portable case will be "
603 +
"completed without a CASE-UCO report.", ex);
615 @SuppressWarnings(
"deprecation")
617 Multimap<Long, BlackboardArtifact> artifactsWithSetName = ArrayListMultimap.create();
618 if (!setNames.isEmpty()) {
619 List<BlackboardArtifact> allArtifacts = skCase.getBlackboardArtifacts(
620 BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT);
621 allArtifacts.addAll(skCase.getBlackboardArtifacts(
622 BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT));
623 allArtifacts.addAll(skCase.getBlackboardArtifacts(
624 BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM));
626 for (BlackboardArtifact bArt : allArtifacts) {
627 BlackboardAttribute setAttr = bArt.getAttribute(
628 new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
629 if (setNames.contains(setAttr.getValueString())) {
630 artifactsWithSetName.put(bArt.getDataSource().getId(), bArt);
634 return artifactsWithSetName;
658 Path tmpDir, Gson gson, CaseUcoExporter exporter, JsonWriter reportWriter,
659 boolean dataSourceHasBeenIncluded)
throws IOException, TskCoreException {
660 if (content instanceof AbstractFile && !(content instanceof DataSource)) {
661 AbstractFile absFile = (AbstractFile) content;
662 Path filePath = tmpDir.resolve(Long.toString(absFile.getId()));
663 if (!absFile.isDir() && !Files.exists(filePath)) {
664 if (!dataSourceHasBeenIncluded) {
665 for (JsonElement element : exporter.exportDataSource(dataSource)) {
666 gson.toJson(element, reportWriter);
671 for (JsonElement element : exporter.exportAbstractFile(absFile, Paths.get(FILE_FOLDER_NAME, subFolder, fileName).toString())) {
672 gson.toJson(element, reportWriter);
674 Files.createFile(filePath);
685 @SuppressWarnings(
"deprecation")
689 List<String> setNames =
new ArrayList<>();
690 Map<String, Long> setCounts;
694 String innerSelect =
"SELECT (value_text) AS set_name FROM blackboard_attributes WHERE (artifact_type_id = '"
695 + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() +
"' OR artifact_type_id = '"
696 + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID() +
"' OR artifact_type_id = '"
697 + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() +
"') AND attribute_type_id = '"
698 + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() +
"'";
701 String query =
"set_name, count(1) AS set_count FROM (" + innerSelect +
") set_names GROUP BY set_name";
706 setNames.addAll(setCounts.keySet());
718 "# {0} - case folder",
719 "PortableCaseReportModule.createCase.caseDirExists=Case folder {0} already exists",
720 "PortableCaseReportModule.createCase.errorCreatingCase=Error creating case",
722 "PortableCaseReportModule.createCase.errorCreatingFolder=Error creating folder {0}",
723 "PortableCaseReportModule.createCase.errorStoringMaxIds=Error storing maximum database IDs",})
727 caseFolder = Paths.get(outputDir.toString(),
caseName).toFile();
729 if (caseFolder.exists()) {
730 handleError(
"Case folder " + caseFolder.toString() +
" already exists",
731 Bundle.PortableCaseReportModule_createCase_caseDirExists(caseFolder.toString()), null, progressPanel);
738 }
catch (TskCoreException ex) {
739 handleError(
"Error creating case " + caseName +
" in folder " + caseFolder.toString(),
740 Bundle.PortableCaseReportModule_createCase_errorCreatingCase(), ex, progressPanel);
747 }
catch (TskCoreException ex) {
749 Bundle.PortableCaseReportModule_createCase_errorStoringMaxIds(), ex, progressPanel);
754 copiedFilesFolder = Paths.get(caseFolder.toString(),
FILE_FOLDER_NAME).toFile();
755 if (!copiedFilesFolder.mkdir()) {
756 handleError(
"Error creating folder " + copiedFilesFolder.toString(),
757 Bundle.PortableCaseReportModule_createCase_errorCreatingFolder(copiedFilesFolder.toString()), null, progressPanel);
763 File subFolder = Paths.get(copiedFilesFolder.toString(), cat.getDisplayName()).toFile();
764 if (!subFolder.mkdir()) {
765 handleError(
"Error creating folder " + subFolder.toString(),
766 Bundle.PortableCaseReportModule_createCase_errorCreatingFolder(subFolder.toString()), null, progressPanel);
771 if (!unknownTypeFolder.mkdir()) {
772 handleError(
"Error creating folder " + unknownTypeFolder.toString(),
773 Bundle.PortableCaseReportModule_createCase_errorCreatingFolder(unknownTypeFolder.toString()), null, progressPanel);
786 CaseDbAccessManager currentCaseDbManager = currentCase.
getSleuthkitCase().getCaseDbAccessManager();
788 String tableSchema =
"( table_name TEXT PRIMARY KEY, "
791 portableSkCase.getCaseDbAccessManager().createTable(MAX_ID_TABLE_NAME, tableSchema);
793 currentCaseDbManager.select(
"max(obj_id) as max_id from tsk_objects",
new StoreMaxIdCallback(
"tsk_objects"));
794 currentCaseDbManager.select(
"max(tag_id) as max_id from content_tags",
new StoreMaxIdCallback(
"content_tags"));
795 currentCaseDbManager.select(
"max(tag_id) as max_id from blackboard_artifact_tags",
new StoreMaxIdCallback(
"blackboard_artifact_tags"));
796 currentCaseDbManager.select(
"max(examiner_id) as max_id from tsk_examiners",
new StoreMaxIdCallback(
"tsk_examiners"));
809 CaseDbAccessManager portableDbAccessManager = portableSkCase.getCaseDbAccessManager();
829 for (ContentTag tag : tags) {
836 Content content = tag.getContent();
837 if (content instanceof AbstractFile) {
842 if (!oldTagNameToNewTagName.containsKey(tag.getName())) {
843 throw new TskCoreException(
"TagName map is missing entry for ID " + tag.getName().getId() +
" with display name " + tag.getName().getDisplayName());
845 ContentTagChange newContentTag = portableSkCase.getTaggingManager().addContentTag(newIdToContent.get(newFileId), oldTagNameToNewTagName.get(tag.getName()), tag.getComment(), tag.getBeginByteOffset(), tag.getEndByteOffset());
850 if (!appData.isEmpty()) {
871 currentCase.
getSleuthkitCase().getCaseDbAccessManager().select(query, callback);
872 return callback.getAppData();
888 appData = rs.getString(
"app_data");
889 }
catch (SQLException ex) {
890 logger.log(Level.WARNING,
"Unable to get app_data from result set", ex);
893 }
catch (SQLException ex) {
894 logger.log(Level.WARNING,
"Failed to get next result for app_data", ex);
903 String getAppData() {
917 String insert =
"(content_tag_id, app_data) VALUES (" + newContentTag.getId() +
", '" + appData +
"')";
934 for (BlackboardArtifactTag tag : tags) {
942 Content content = tag.getContent();
946 BlackboardArtifact newArtifact =
copyArtifact(newContentId, tag.getArtifact());
949 copyAttachments(newArtifact, tag.getArtifact(), portableSkCase.getAbstractFileById(newContentId));
955 if (!oldTagNameToNewTagName.containsKey(tag.getName())) {
956 throw new TskCoreException(
"TagName map is missing entry for ID " + tag.getName().getId() +
" with display name " + tag.getName().getDisplayName());
958 portableSkCase.getTaggingManager().addArtifactTag(newArtifact, oldTagNameToNewTagName.get(tag.getName()), tag.getComment());
974 private BlackboardArtifact
copyArtifact(
long newContentId, BlackboardArtifact artifactToCopy)
throws TskCoreException {
976 if (oldArtifactIdToNewArtifact.containsKey(artifactToCopy.getArtifactID())) {
977 return oldArtifactIdToNewArtifact.get(artifactToCopy.getArtifactID());
981 BlackboardAttribute oldAssociatedAttribute = artifactToCopy.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
982 List<BlackboardAttribute> newAttrs =
new ArrayList<>();
983 if (oldAssociatedAttribute != null) {
984 BlackboardArtifact oldAssociatedArtifact = currentCase.
getSleuthkitCase().getBlackboardArtifact(oldAssociatedAttribute.getValueLong());
985 BlackboardArtifact newAssociatedArtifact =
copyArtifact(newContentId, oldAssociatedArtifact);
986 newAttrs.add(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT,
987 String.join(
",", oldAssociatedAttribute.getSources()), newAssociatedArtifact.getArtifactID()));
990 List<BlackboardAttribute> oldAttrs = artifactToCopy.getAttributes();
993 for (BlackboardAttribute oldAttr : oldAttrs) {
996 if (SPECIALLY_HANDLED_ATTRS.contains(oldAttr.getAttributeType().getTypeID())) {
1001 switch (oldAttr.getValueType()) {
1003 newAttrs.add(
new BlackboardAttribute(newAttributeType, String.join(
",", oldAttr.getSources()),
1004 oldAttr.getValueBytes()));
1007 newAttrs.add(
new BlackboardAttribute(newAttributeType, String.join(
",", oldAttr.getSources()),
1008 oldAttr.getValueDouble()));
1011 newAttrs.add(
new BlackboardAttribute(newAttributeType, String.join(
",", oldAttr.getSources()),
1012 oldAttr.getValueInt()));
1016 newAttrs.add(
new BlackboardAttribute(newAttributeType, String.join(
",", oldAttr.getSources()),
1017 oldAttr.getValueLong()));
1021 newAttrs.add(
new BlackboardAttribute(newAttributeType, String.join(
",", oldAttr.getSources()),
1022 oldAttr.getValueString()));
1025 throw new TskCoreException(
"Unexpected attribute value type found: " + oldAttr.getValueType().getLabel());
1031 Long newDataSourceId;
1032 if (newIdToContent.get(newContentId).getDataSource() != null) {
1035 newDataSourceId = newIdToContent.get(newContentId).getDataSource().getId();
1038 if (artifactToCopy.getDataSource() == null) {
1040 throw new TskCoreException(
"Can not copy artifact with ID: " + artifactToCopy.getArtifactID() +
" because it is not associated with a data source");
1042 newDataSourceId =
copyContent(artifactToCopy.getDataSource());
1047 BlackboardArtifact.Type newArtifactType = portableSkCase.getBlackboard().getArtifactType(newArtifactTypeId);
1048 BlackboardArtifact newArtifact;
1052 if (!((artifactToCopy instanceof AnalysisResult) || (artifactToCopy instanceof DataArtifact))) {
1054 if (newArtifactType.getCategory().equals(BlackboardArtifact.Category.ANALYSIS_RESULT)) {
1055 AnalysisResult ar = currentCase.
getSleuthkitCase().getBlackboard().getAnalysisResultById(artifactToCopy.getId());
1057 artifactToCopy = ar;
1060 DataArtifact da = currentCase.
getSleuthkitCase().getBlackboard().getDataArtifactById(artifactToCopy.getId());
1062 artifactToCopy = da;
1065 }
catch (TskCoreException ex) {
1071 if (artifactToCopy instanceof AnalysisResult) {
1072 AnalysisResult analysisResultToCopy = (AnalysisResult) artifactToCopy;
1073 newArtifact = portableSkCase.getBlackboard().newAnalysisResult(newArtifactType, newContentId,
1074 newDataSourceId, analysisResultToCopy.getScore(),
1075 analysisResultToCopy.getConclusion(), analysisResultToCopy.getConfiguration(),
1076 analysisResultToCopy.getJustification(), newAttrs).getAnalysisResult();
1077 }
else if (artifactToCopy instanceof DataArtifact) {
1078 DataArtifact dataArtifactToCopy = (DataArtifact) artifactToCopy;
1079 Long newOsAccountId = null;
1080 if (dataArtifactToCopy.getOsAccountObjectId().isPresent()) {
1081 copyOsAccount(dataArtifactToCopy.getOsAccountObjectId().get());
1082 newOsAccountId = oldOsAccountIdToNewOsAccount.get((dataArtifactToCopy.getOsAccountObjectId().get())).getId();
1084 newArtifact = portableSkCase.getBlackboard().newDataArtifact(newArtifactType, newContentId,
1086 newAttrs, newOsAccountId);
1088 if (newArtifactType.getCategory().equals(BlackboardArtifact.Category.ANALYSIS_RESULT)) {
1089 newArtifact = portableSkCase.getBlackboard().newAnalysisResult(newArtifactType, newContentId,
1090 newDataSourceId, Score.SCORE_NONE,
1091 null, null, null, newAttrs).getAnalysisResult();
1093 newArtifact = portableSkCase.getBlackboard().newDataArtifact(newArtifactType, newContentId,
1098 }
catch (BlackboardException ex) {
1099 throw new TskCoreException(
"Error copying artifact with ID: " + artifactToCopy.getId());
1102 oldArtifactIdToNewArtifact.put(artifactToCopy.getArtifactID(), newArtifact);
1116 if (oldArtTypeIdToNewArtTypeId.containsKey(oldArtifact.getArtifactTypeID())) {
1117 return oldArtTypeIdToNewArtTypeId.get(oldArtifact.getArtifactTypeID());
1120 BlackboardArtifact.Type oldCustomType = currentCase.
getSleuthkitCase().getBlackboard().getArtifactType(oldArtifact.getArtifactTypeName());
1122 BlackboardArtifact.Type newCustomType = portableSkCase.getBlackboard().getOrAddArtifactType(oldCustomType.getTypeName(), oldCustomType.getDisplayName());
1123 oldArtTypeIdToNewArtTypeId.put(oldArtifact.getArtifactTypeID(), newCustomType.getTypeID());
1124 return newCustomType.getTypeID();
1125 }
catch (BlackboardException ex) {
1126 throw new TskCoreException(
"Error creating new artifact type " + oldCustomType.getTypeName(), ex);
1139 private BlackboardAttribute.Type
getNewAttributeType(BlackboardAttribute oldAttribute)
throws TskCoreException {
1140 BlackboardAttribute.Type oldAttrType = oldAttribute.getAttributeType();
1146 BlackboardAttribute.Type newCustomType = portableSkCase.getBlackboard().getOrAddAttributeType(oldAttrType.getTypeName(),
1147 oldAttrType.getValueType(), oldAttrType.getDisplayName());
1149 return newCustomType;
1150 }
catch (BlackboardException ex) {
1151 throw new TskCoreException(
"Error creating new attribute type " + oldAttrType.getTypeName(), ex);
1165 @NbBundle.Messages({
1166 "# {0} - File name",
1167 "PortableCaseReportModule.copyContentToPortableCase.copyingFile=Copying file {0}",})
1169 progressPanel.
updateStatusLabel(Bundle.PortableCaseReportModule_copyContentToPortableCase_copyingFile(content.getUniquePath()));
1185 if (oldIdToNewContent.containsKey(content.getId())) {
1186 return oldIdToNewContent.get(content.getId()).getId();
1193 if (content.getParent() != null) {
1198 if (content instanceof BlackboardArtifact) {
1199 BlackboardArtifact artifactToCopy = (BlackboardArtifact) content;
1201 }
else if (content instanceof OsAccount) {
1205 Host newHost = null;
1206 if (content instanceof DataSource) {
1207 newHost =
copyHost(((DataSource) content).getHost());
1211 if (content instanceof AbstractFile) {
1212 AbstractFile file = (AbstractFile) content;
1213 if (file.getOsAccountObjectId().isPresent()) {
1222 if (content instanceof Image) {
1223 md5 = ((Image) content).getMd5();
1224 sha1 = ((Image) content).getSha1();
1225 sha256 = ((Image) content).getSha256();
1228 CaseDbTransaction trans = portableSkCase.beginTransaction();
1230 if (content instanceof Image) {
1231 Image image = (Image) content;
1232 newContent = portableSkCase.addImage(image.getType(), image.getSsize(), image.getSize(), image.getName(),
1233 new ArrayList<>(), image.getTimeZone(), md5, sha1, sha256, image.getDeviceId(), newHost, trans);
1234 }
else if (content instanceof VolumeSystem) {
1235 VolumeSystem vs = (VolumeSystem) content;
1236 newContent = portableSkCase.addVolumeSystem(parentId, vs.getType(), vs.getOffset(), vs.getBlockSize(), trans);
1237 }
else if (content instanceof Volume) {
1238 Volume vs = (Volume) content;
1239 newContent = portableSkCase.addVolume(parentId, vs.getAddr(), vs.getStart(), vs.getLength(),
1240 vs.getDescription(), vs.getFlags(), trans);
1241 }
else if (content instanceof Pool) {
1242 Pool pool = (Pool) content;
1243 newContent = portableSkCase.addPool(parentId, pool.getType(), trans);
1244 }
else if (content instanceof FileSystem) {
1245 FileSystem fs = (FileSystem) content;
1246 newContent = portableSkCase.addFileSystem(parentId, fs.getImageOffset(), fs.getFsType(), fs.getBlock_size(),
1247 fs.getBlock_count(), fs.getRoot_inum(), fs.getFirst_inum(), fs.getLastInum(),
1248 fs.getName(), trans);
1249 }
else if (content instanceof BlackboardArtifact) {
1250 BlackboardArtifact artifactToCopy = (BlackboardArtifact) content;
1252 }
else if (content instanceof AbstractFile) {
1253 AbstractFile abstractFile = (AbstractFile) content;
1255 if (abstractFile instanceof LocalFilesDataSource) {
1256 LocalFilesDataSource localFilesDS = (LocalFilesDataSource) abstractFile;
1257 newContent = portableSkCase.addLocalFilesDataSource(localFilesDS.getDeviceId(), localFilesDS.getName(), localFilesDS.getTimeZone(), newHost, trans);
1259 if (abstractFile.isDir()) {
1260 newContent = portableSkCase.addLocalDirectory(parentId, abstractFile.getName(), trans);
1266 File exportFolder = Paths.get(copiedFilesFolder.toString(), exportSubFolder).toFile();
1267 File localFile =
new File(exportFolder, fileName);
1271 Content oldParent = abstractFile.getParent();
1272 if (!oldIdToNewContent.containsKey(oldParent.getId())) {
1273 throw new TskCoreException(
"Parent of file with ID " + abstractFile.getId() +
" has not been created");
1275 Content newParent = oldIdToNewContent.get(oldParent.getId());
1278 String relativePath = FILE_FOLDER_NAME + File.separator + exportSubFolder + File.separator + fileName;
1280 Long newOsAccountId = null;
1281 if (abstractFile.getOsAccountObjectId().isPresent()) {
1282 newOsAccountId = oldOsAccountIdToNewOsAccount.get(abstractFile.getOsAccountObjectId().get()).getId();
1285 newContent = portableSkCase.addLocalFile(abstractFile.getName(), relativePath, abstractFile.getSize(),
1286 abstractFile.getCtime(), abstractFile.getCrtime(), abstractFile.getAtime(), abstractFile.getMtime(),
1287 abstractFile.getMd5Hash(), abstractFile.getSha256Hash(), abstractFile.getKnown(), abstractFile.getMIMEType(),
1288 true, TskData.EncodingType.NONE,
1289 newOsAccountId, abstractFile.getOwnerUid().orElse(null),
1291 }
catch (IOException ex) {
1292 throw new TskCoreException(
"Error copying file " + abstractFile.getName() +
" with original obj ID "
1293 + abstractFile.getId(), ex);
1298 throw new TskCoreException(
"Trying to copy unexpected Content type " + content.getClass().getName());
1301 }
catch (TskCoreException ex) {
1308 oldIdToNewContent.put(content.getId(), newContent);
1309 newIdToContent.put(newContent.getId(), newContent);
1310 return oldIdToNewContent.get(content.getId()).getId();
1323 private Host
copyHost(Host oldHost)
throws TskCoreException {
1325 if (oldHostIdToNewHost.containsKey(oldHost.getHostId())) {
1326 newHost = oldHostIdToNewHost.get(oldHost.getHostId());
1328 newHost = portableSkCase.getHostManager().newHost(oldHost.getName());
1329 oldHostIdToNewHost.put(oldHost.getHostId(), newHost);
1342 if (oldOsAccountIdToNewOsAccount.containsKey(oldOsAccountId)) {
1343 return oldOsAccountIdToNewOsAccount.get(oldOsAccountId);
1347 OsAccountManager oldOsAcctManager = currentCase.
getSleuthkitCase().getOsAccountManager();
1348 OsAccount oldOsAccount = oldOsAcctManager.getOsAccountByObjectId(oldOsAccountId);
1351 OsAccountRealmManager oldRealmManager = currentCase.
getSleuthkitCase().getOsAccountRealmManager();
1352 OsAccountRealm oldRealm = oldRealmManager.getRealmByRealmId(oldOsAccount.getRealmId());
1355 if (!oldRealmIdToNewRealm.containsKey(oldOsAccount.getRealmId())) {
1356 OsAccountRealmManager newRealmManager = portableSkCase.getOsAccountRealmManager();
1358 Host newHost = null;
1359 if (oldRealm.getScopeHost().isPresent()) {
1360 Host host = oldRealm.getScopeHost().get();
1363 if (oldRealm.getScope().equals(OsAccountRealm.RealmScope.DOMAIN)) {
1367 throw new TskCoreException(
"Failed to copy OsAccountRealm with ID=" + oldOsAccount.getRealmId() +
" - can not currently handle domain-scoped hosts");
1369 throw new TskCoreException(
"Failed to copy OsAccountRealm with ID=" + oldOsAccount.getRealmId() +
" because it is non-domain scoped but has no scope host");
1374 String realmName = null;
1375 List<String> names = oldRealm.getRealmNames();
1376 if (!names.isEmpty()) {
1377 realmName = names.get(0);
1381 OsAccountRealm newRealm = newRealmManager.newWindowsRealm(oldOsAccount.getAddr().orElse(null), realmName, newHost, oldRealm.getScope());
1382 oldRealmIdToNewRealm.put(oldOsAccount.getRealmId(), newRealm);
1383 }
catch (NotUserSIDException ex) {
1384 throw new TskCoreException(
"Failed to copy OsAccountRealm with ID=" + oldOsAccount.getRealmId(), ex);
1388 OsAccountManager newOsAcctManager = portableSkCase.getOsAccountManager();
1390 OsAccount newOsAccount = newOsAcctManager.newWindowsOsAccount(oldOsAccount.getAddr().orElse(null),
1391 oldOsAccount.getLoginName().orElse(null), oldRealmIdToNewRealm.get(oldOsAccount.getRealmId()));
1392 oldOsAccountIdToNewOsAccount.put(oldOsAccountId, newOsAccount);
1393 return newOsAccount;
1394 }
catch (NotUserSIDException ex) {
1395 throw new TskCoreException(
"Failed to copy OsAccount with ID=" + oldOsAccount.getId(), ex);
1408 private void copyPathID(BlackboardArtifact newArtifact, BlackboardArtifact oldArtifact)
throws TskCoreException {
1410 BlackboardAttribute oldPathIdAttr = oldArtifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID));
1411 if (oldPathIdAttr != null) {
1413 long oldContentId = oldPathIdAttr.getValueLong();
1414 if (oldContentId > 0) {
1415 Content oldContent = currentCase.
getSleuthkitCase().getContentById(oldContentId);
1417 newArtifact.addAttribute(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID,
1418 String.join(
",", oldPathIdAttr.getSources()), newContentId));
1434 private void copyAttachments(BlackboardArtifact newArtifact, BlackboardArtifact oldArtifact, AbstractFile newFile)
throws TskCoreException {
1436 BlackboardAttribute attachmentsAttr = oldArtifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ATTACHMENTS));
1437 if (attachmentsAttr != null) {
1439 MessageAttachments msgAttachments = BlackboardJsonAttrUtil.fromAttribute(attachmentsAttr, MessageAttachments.class);
1441 Collection<MessageAttachments.FileAttachment> oldFileAttachments = msgAttachments.getFileAttachments();
1442 List<MessageAttachments.FileAttachment> newFileAttachments =
new ArrayList<>();
1443 for (MessageAttachments.FileAttachment oldFileAttachment : oldFileAttachments) {
1444 long attachedFileObjId = oldFileAttachment.getObjectId();
1445 if (attachedFileObjId >= 0) {
1447 AbstractFile attachedFile = currentCase.
getSleuthkitCase().getAbstractFileById(attachedFileObjId);
1448 if (attachedFile == null) {
1449 throw new TskCoreException(
"Error loading file with object ID " + attachedFileObjId +
" from portable case");
1452 newFileAttachments.add(
new MessageAttachments.FileAttachment(portableSkCase.getAbstractFileById(newFileID)));
1457 String newSourceStr =
"";
1458 List<String> oldSources = attachmentsAttr.getSources();
1459 if (!oldSources.isEmpty()) {
1460 newSourceStr = String.join(
",", oldSources);
1464 CommunicationArtifactsHelper communicationArtifactsHelper =
new CommunicationArtifactsHelper(currentCase.
getSleuthkitCase(),
1465 newSourceStr, newFile, Account.Type.EMAIL, null);
1466 communicationArtifactsHelper.addAttachments(newArtifact,
new MessageAttachments(newFileAttachments, msgAttachments.getUrlAttachments()));
1467 }
catch (BlackboardJsonAttrUtil.InvalidJsonException ex) {
1468 throw new TskCoreException(String.format(
"Unable to parse json for MessageAttachments object in artifact: %s", oldArtifact.getName()), ex);
1471 for (Content childContent : oldArtifact.getChildren()) {
1472 if (childContent instanceof AbstractFile) {
1487 if (abstractFile.getMIMEType() == null || abstractFile.getMIMEType().isEmpty()) {
1492 if (cat.getMediaTypes().contains(abstractFile.getMIMEType())) {
1493 return cat.getDisplayName();
1518 return Paths.get(installPath,
"bin", exeName);
1528 return appName +
"64.exe";
1539 private void copyApplication(Path sourceFolder, String destBaseFolder)
throws IOException {
1543 if (!destAppFolder.toFile().exists() && !destAppFolder.toFile().mkdirs()) {
1544 throw new IOException(
"Failed to create directory " + destAppFolder.toString());
1548 FileUtils.copyDirectory(sourceFolder.toFile(), destAppFolder.toFile());
1559 Path filePath = Paths.get(destBaseFolder,
"open.bat");
1562 String casePath =
"..\\" +
caseName;
1563 try (FileWriter writer =
new FileWriter(filePath.toFile())) {
1564 writer.write(exePath +
" \"" + casePath +
"\"");
1572 oldIdToNewContent.clear();
1573 newIdToContent.clear();
1574 oldTagNameToNewTagName.clear();
1575 oldArtTypeIdToNewArtTypeId.clear();
1577 oldArtifactIdToNewArtifact.clear();
1578 oldOsAccountIdToNewOsAccount.clear();
1579 oldRealmIdToNewRealm.clear();
1580 oldHostIdToNewHost.clear();
1586 copiedFilesFolder = null;
1593 if (portableSkCase != null) {
1594 portableSkCase.close();
1595 portableSkCase = null;
1617 Long maxId = rs.getLong(
"max_id");
1618 String query =
" (table_name, max_id) VALUES ('" + tableName +
"', '" + maxId +
"')";
1619 portableSkCase.getCaseDbAccessManager().insert(MAX_ID_TABLE_NAME, query);
1621 }
catch (SQLException ex) {
1622 logger.log(Level.WARNING,
"Unable to get maximum ID from result set", ex);
1623 }
catch (TskCoreException ex) {
1624 logger.log(Level.WARNING,
"Unable to save maximum ID from result set", ex);
1628 }
catch (SQLException ex) {
1629 logger.log(Level.WARNING,
"Failed to get maximum ID from result set", ex);
1634 @NbBundle.Messages({
1635 "PortableCaseReportModule.compressCase.errorFinding7zip=Could not locate 7-Zip executable",
1636 "# {0} - Temp folder path",
1637 "PortableCaseReportModule.compressCase.errorCreatingTempFolder=Could not create temporary folder {0}",
1638 "PortableCaseReportModule.compressCase.errorCompressingCase=Error compressing case",
1639 "PortableCaseReportModule.compressCase.canceled=Compression canceled by user",})
1645 Path dirToCompress = Paths.get(folderToCompress);
1646 File tempZipFolder = Paths.get(dirToCompress.getParent().toString(),
"temp",
"portableCase" + System.currentTimeMillis()).toFile();
1647 if (!tempZipFolder.mkdirs()) {
1648 handleError(
"Error creating temporary folder " + tempZipFolder.toString(),
1649 Bundle.PortableCaseReportModule_compressCase_errorCreatingTempFolder(tempZipFolder.toString()), null, progressPanel);
1655 if (sevenZipExe == null) {
1656 handleError(
"Error finding 7-Zip exectuable", Bundle.PortableCaseReportModule_compressCase_errorFinding7zip(), null, progressPanel);
1661 String chunkOption =
"";
1666 File zipFile = Paths.get(tempZipFolder.getAbsolutePath(), caseName +
".zip").toFile();
1667 ProcessBuilder procBuilder =
new ProcessBuilder();
1668 procBuilder.command(
1669 sevenZipExe.getAbsolutePath(),
1671 zipFile.getAbsolutePath(),
1672 dirToCompress.toAbsolutePath().toString(),
1677 Process process = procBuilder.start();
1679 while (process.isAlive()) {
1686 int exitCode = process.exitValue();
1687 if (exitCode != 0) {
1689 StringBuilder sb =
new StringBuilder();
1690 try (BufferedReader br =
new BufferedReader(
new InputStreamReader(process.getErrorStream()))) {
1692 while ((line = br.readLine()) != null) {
1693 sb.append(line).append(System.getProperty(
"line.separator"));
1697 handleError(
"Error compressing case\n7-Zip output: " + sb.toString(), Bundle.PortableCaseReportModule_compressCase_errorCompressingCase(), null, progressPanel);
1700 }
catch (IOException | InterruptedException ex) {
1701 handleError(
"Error compressing case", Bundle.PortableCaseReportModule_compressCase_errorCompressingCase(), ex, progressPanel);
1707 FileUtils.cleanDirectory(dirToCompress.toFile());
1708 FileUtils.copyDirectory(tempZipFolder, dirToCompress.toFile());
1709 FileUtils.deleteDirectory(
new File(tempZipFolder.getParent()));
1710 }
catch (IOException ex) {
1711 handleError(
"Error compressing case", Bundle.PortableCaseReportModule_compressCase_errorCompressingCase(), ex, progressPanel);
1728 String executableToFindName = Paths.get(
"7-Zip",
"7z.exe").toString();
1730 if (null == exeFile) {
1734 if (!exeFile.canExecute()) {
1747 private final Map<String, Long>
setCounts =
new HashMap<>();
1754 Long setCount = rs.getLong(
"set_count");
1755 String setName = rs.getString(
"set_name");
1757 setCounts.put(setName, setCount);
1759 }
catch (SQLException ex) {
1760 logger.log(Level.WARNING,
"Unable to get data_source_obj_id or value from result set", ex);
1763 }
catch (SQLException ex) {
1764 logger.log(Level.WARNING,
"Failed to get next result for values by datasource", ex);
static final List< Integer > SPECIALLY_HANDLED_ATTRS
boolean includeApplication()
final Map< Integer, Integer > oldArtTypeIdToNewArtTypeId
void handleError(String logWarning, String dialogWarning, Exception ex, ReportProgressPanel progressPanel)
long copyContent(Content content)
static final Logger logger
Host copyHost(Host oldHost)
int getNewArtifactTypeId(BlackboardArtifact oldArtifact)
static final List< FileTypeCategory > FILE_TYPE_CATEGORIES
static final String MAX_ID_TABLE_NAME
void process(ResultSet rs)
final Map< TagName, TagName > oldTagNameToNewTagName
OsAccount copyOsAccount(Long oldOsAccountId)
final Map< Long, Content > oldIdToNewContent
final Map< Long, BlackboardArtifact > oldArtifactIdToNewArtifact
PortableCaseReportModule()
final Map< Long, OsAccount > oldOsAccountIdToNewOsAccount
String getTempDirectory()
String getAutopsyExeName()
long copyContentToPortableCase(Content content, ReportProgressPanel progressPanel)
void addArtifactsToPortableCase(TagName oldTagName, ReportProgressPanel progressPanel)
static final String FILE_FOLDER_NAME
final Map< Integer, BlackboardAttribute.Type > oldAttrTypeIdToNewAttrType
static String getAppName()
void process(ResultSet rs)
void complete(ReportStatus reportStatus)
List< TagName > getSelectedTagNames()
Map< String, Long > getSetCountMap()
static File locate7ZipExecutable()
void copyAttachments(BlackboardArtifact newArtifact, BlackboardArtifact oldArtifact, AbstractFile newFile)
Multimap< Long, BlackboardArtifact > getInterestingArtifactsBySetName(SleuthkitCase skCase, List< String > setNames)
static< T > long writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, Future< T > worker, boolean source)
void closePortableCaseDatabase()
List< String > getAllInterestingItemsSets()
void createAppLaunchBatFile(String destBaseFolder)
final Map< Long, OsAccountRealm > oldRealmIdToNewRealm
static final String UNKNOWN_FILE_TYPE_FOLDER
Logger(String name, String resourceBundleName)
void setIndeterminate(boolean indeterminate)
BlackboardAttribute.Type getNewAttributeType(BlackboardAttribute oldAttribute)
void copyPathID(BlackboardArtifact newArtifact, BlackboardArtifact oldArtifact)
void addFilesToPortableCase(TagName oldTagName, ReportProgressPanel progressPanel)
void generateReport(String reportPath, PortableCaseReportModuleSettings options, ReportProgressPanel progressPanel)
String getRelativeFilePath()
TagsManager getTagsManager()
static final String CASE_UCO_TMP_DIR
void initializeImageTags(ReportProgressPanel progressPanel)
String getExportSubfolder(AbstractFile abstractFile)
final Map< Long, Host > oldHostIdToNewHost
static final String TABLE_SCHEMA_SQLITE
final Map< Long, Content > newIdToContent
SleuthkitCase portableSkCase
static final String TABLE_NAME
final Map< String, Long > setCounts
SleuthkitCase getSleuthkitCase()
List< String > getSelectedSetNames()
BlackboardArtifact copyArtifact(long newContentId, BlackboardArtifact artifactToCopy)
void generateCaseUcoReport(List< TagName > tagNames, List< String > setNames, ReportProgressPanel progressPanel)
void copyApplication(Path sourceFolder, String destBaseFolder)
SleuthkitCase createPortableCase(String caseName, File portableCaseFolder)
boolean areAllTagsSelected()
boolean addUniqueFile(Content content, DataSource dataSource, Path tmpDir, Gson gson, CaseUcoExporter exporter, JsonWriter reportWriter, boolean dataSourceHasBeenIncluded)
static String escapeFileName(String fileName)
boolean compressCase(ReportProgressPanel progressPanel, String folderToCompress)
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
void updateStatusLabel(String statusMessage)
String getImageTagDataForContentTag(ContentTag tag)
static final String CASE_UCO_FILE_NAME
String getSevenZipParam()
boolean areAllSetsSelected()
void addImageTagToPortableCase(ContentTag newContentTag, String appData)
void handleCancellation(ReportProgressPanel progressPanel)
Path getApplicationBasePath()
void createCase(File outputDir, ReportProgressPanel progressPanel)
void process(ResultSet rs)
PortableCaseReportModuleSettings settings