19 package org.sleuthkit.autopsy.report;
 
   21 import org.openide.util.lookup.ServiceProvider;
 
   22 import javax.swing.JPanel;
 
   23 import java.util.logging.Level;
 
   25 import java.io.IOException;
 
   26 import java.nio.file.Paths;
 
   27 import java.sql.ResultSet;
 
   28 import java.sql.SQLException;
 
   29 import java.util.ArrayList;
 
   30 import java.util.Arrays;
 
   31 import java.util.HashMap;
 
   32 import java.util.List;
 
   34 import org.openide.util.NbBundle;
 
   53 import org.
sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction;
 
   64 @ServiceProvider(service = GeneralReportModule.class)
 
   67     private static final String FILE_FOLDER_NAME = 
"PortableCaseFiles";
 
   68     private static final String UNKNOWN_FILE_TYPE_FOLDER = 
"Other";
 
   69     private static final String MAX_ID_TABLE_NAME = 
"portable_case_max_ids";
 
   76     private Case currentCase = null;
 
   77     private SleuthkitCase portableSkCase = null;
 
   78     private File caseFolder = null;
 
   79     private File copiedFilesFolder = null;
 
   82     private final Map<Long, Content> oldIdToNewContent = 
new HashMap<>();
 
   85     private final Map<Long, Content> newIdToContent = 
new HashMap<>();
 
   88     private final Map<TagName, TagName> oldTagNameToNewTagName = 
new HashMap<>();
 
   91     private final Map<Integer, Integer> oldArtTypeIdToNewArtTypeId = 
new HashMap<>();
 
   94     private final Map<Integer, BlackboardAttribute.Type> oldAttrTypeIdToNewAttrType = 
new HashMap<>();
 
   97     private final Map<Long, BlackboardArtifact> oldArtifactIdToNewArtifact = 
new HashMap<>();
 
  104         "CreatePortableCaseModule.getName.name=Portable Case" 
  108         return Bundle.CreatePortableCaseModule_getName_name();
 
  112         "CreatePortableCaseModule.getDescription.description=Copies selected tagged items to a new single-user case that will work anywhere" 
  116         return Bundle.CreatePortableCaseModule_getDescription_description();
 
  136             logger.log(Level.WARNING, logWarning);
 
  138             logger.log(Level.SEVERE, logWarning, ex);
 
  147         "CreatePortableCaseModule.generateReport.verifying=Verifying selected parameters...",
 
  148         "CreatePortableCaseModule.generateReport.creatingCase=Creating portable case database...",
 
  149         "CreatePortableCaseModule.generateReport.copyingTags=Copying tags...",
 
  151         "CreatePortableCaseModule.generateReport.copyingFiles=Copying files tagged as {0}...",
 
  153         "CreatePortableCaseModule.generateReport.copyingArtifacts=Copying artifacts tagged as {0}...",
 
  154         "# {0} - output folder",
 
  155         "CreatePortableCaseModule.generateReport.outputDirDoesNotExist=Output folder {0} does not exist",
 
  156         "# {0} - output folder",
 
  157         "CreatePortableCaseModule.generateReport.outputDirIsNotDir=Output folder {0} is not a folder",
 
  158         "CreatePortableCaseModule.generateReport.noTagsSelected=No tags selected for export.",
 
  159         "CreatePortableCaseModule.generateReport.caseClosed=Current case has been closed",
 
  160         "CreatePortableCaseModule.generateReport.errorCopyingTags=Error copying tags",
 
  161         "CreatePortableCaseModule.generateReport.errorCopyingFiles=Error copying tagged files",
 
  162         "CreatePortableCaseModule.generateReport.errorCopyingArtifacts=Error copying tagged artifacts",
 
  163         "# {0} - attribute type name",
 
  164         "CreatePortableCaseModule.generateReport.errorLookingUpAttrType=Error looking up attribute type {0}",
 
  169         progressPanel.
start();
 
  170         progressPanel.
updateStatusLabel(Bundle.CreatePortableCaseModule_generateReport_verifying());
 
  176         File outputDir = 
new File(configPanel.getOutputFolder());
 
  177         if (! outputDir.exists()) {
 
  178             handleError(
"Output folder " + outputDir.toString() + 
" does not exist",
 
  179                     Bundle.CreatePortableCaseModule_generateReport_outputDirDoesNotExist(outputDir.toString()), null, progressPanel);
 
  183         if (! outputDir.isDirectory()) {
 
  184             handleError(
"Output folder " + outputDir.toString() + 
" is not a folder",
 
  185                     Bundle.CreatePortableCaseModule_generateReport_outputDirIsNotDir(outputDir.toString()), null, progressPanel);
 
  189         List<TagName> tagNames = configPanel.getSelectedTagNames();
 
  190         if (tagNames.isEmpty()) {
 
  191             handleError(
"No tags selected for export",
 
  192                     Bundle.CreatePortableCaseModule_generateReport_noTagsSelected(), null, progressPanel);
 
  200             handleError(
"Current case has been closed",
 
  201                     Bundle.CreatePortableCaseModule_generateReport_caseClosed(), null, progressPanel);
 
  208         progressPanel.
updateStatusLabel(Bundle.CreatePortableCaseModule_generateReport_creatingCase());
 
  209         createCase(outputDir, progressPanel);
 
  210         if (portableSkCase == null) {
 
  222         progressPanel.
updateStatusLabel(Bundle.CreatePortableCaseModule_generateReport_copyingTags());
 
  224             for(TagName tagName:tagNames) {
 
  225                 TagName newTagName = portableSkCase.addOrUpdateTagName(tagName.getDisplayName(), tagName.getDescription(), tagName.getColor(), tagName.getKnownStatus());
 
  226                 oldTagNameToNewTagName.put(tagName, newTagName);
 
  228         } 
catch (TskCoreException ex) {
 
  229             handleError(
"Error copying tags", Bundle.CreatePortableCaseModule_generateReport_errorCopyingTags(), ex, progressPanel);
 
  235             for(TagName tagName:tagNames) {
 
  240                 progressPanel.
updateStatusLabel(Bundle.CreatePortableCaseModule_generateReport_copyingFiles(tagName.getDisplayName()));
 
  241                 addFilesToPortableCase(tagName, progressPanel);
 
  243         } 
catch (TskCoreException ex) {
 
  244             handleError(
"Error copying tagged files", Bundle.CreatePortableCaseModule_generateReport_errorCopyingFiles(), ex, progressPanel);
 
  249         for (BlackboardArtifact.ARTIFACT_TYPE type:BlackboardArtifact.ARTIFACT_TYPE.values()) {
 
  250             oldArtTypeIdToNewArtTypeId.put(type.getTypeID(), type.getTypeID());
 
  252         for (BlackboardAttribute.ATTRIBUTE_TYPE type:BlackboardAttribute.ATTRIBUTE_TYPE.values()) {
 
  254                 oldAttrTypeIdToNewAttrType.put(type.getTypeID(), portableSkCase.getAttributeType(type.getLabel()));
 
  255             } 
catch (TskCoreException ex) {
 
  256                 handleError(
"Error looking up attribute name " + type.getLabel(),
 
  257                         Bundle.CreatePortableCaseModule_generateReport_errorLookingUpAttrType(type.getLabel()),
 
  264             for(TagName tagName:tagNames) {
 
  269                 progressPanel.
updateStatusLabel(Bundle.CreatePortableCaseModule_generateReport_copyingArtifacts(tagName.getDisplayName()));
 
  270                 addArtifactsToPortableCase(tagName, progressPanel);
 
  272         } 
catch (TskCoreException ex) {
 
  273             handleError(
"Error copying tagged artifacts", Bundle.CreatePortableCaseModule_generateReport_errorCopyingArtifacts(), ex, progressPanel);
 
  292         "# {0} - case folder",
 
  293         "CreatePortableCaseModule.createCase.caseDirExists=Case folder {0} already exists",
 
  294         "CreatePortableCaseModule.createCase.errorCreatingCase=Error creating case",
 
  296         "CreatePortableCaseModule.createCase.errorCreatingFolder=Error creating folder {0}",
 
  297         "CreatePortableCaseModule.createCase.errorStoringMaxIds=Error storing maximum database IDs",
 
  303         caseFolder = Paths.get(outputDir.toString(), caseName).toFile();
 
  305         if (caseFolder.exists()) {
 
  306             handleError(
"Case folder " + caseFolder.toString() + 
" already exists",
 
  307                 Bundle.CreatePortableCaseModule_createCase_caseDirExists(caseFolder.toString()), null, progressPanel);  
 
  314         } 
catch (TskCoreException ex) {
 
  315             handleError(
"Error creating case " + caseName + 
" in folder " + caseFolder.toString(),
 
  316                 Bundle.CreatePortableCaseModule_createCase_errorCreatingCase(), ex, progressPanel);  
 
  323         } 
catch (TskCoreException ex) {
 
  324             handleError(
"Error storing maximum database IDs",
 
  325                 Bundle.CreatePortableCaseModule_createCase_errorStoringMaxIds(), ex, progressPanel);  
 
  330         copiedFilesFolder = Paths.get(caseFolder.toString(), FILE_FOLDER_NAME).toFile();
 
  331         if (! copiedFilesFolder.mkdir()) {
 
  332             handleError(
"Error creating folder " + copiedFilesFolder.toString(),
 
  333                     Bundle.CreatePortableCaseModule_createCase_errorCreatingFolder(copiedFilesFolder.toString()), null, progressPanel);
 
  339             File subFolder = Paths.get(copiedFilesFolder.toString(), cat.getDisplayName()).toFile();
 
  340             if (! subFolder.mkdir()) {
 
  341                 handleError(
"Error creating folder " + subFolder.toString(),
 
  342                     Bundle.CreatePortableCaseModule_createCase_errorCreatingFolder(subFolder.toString()), null, progressPanel);   
 
  346         File unknownTypeFolder = Paths.get(copiedFilesFolder.toString(), UNKNOWN_FILE_TYPE_FOLDER).toFile();
 
  347         if (! unknownTypeFolder.mkdir()) {
 
  348             handleError(
"Error creating folder " + unknownTypeFolder.toString(),
 
  349                 Bundle.CreatePortableCaseModule_createCase_errorCreatingFolder(unknownTypeFolder.toString()), null, progressPanel);   
 
  362         CaseDbAccessManager currentCaseDbManager = currentCase.
getSleuthkitCase().getCaseDbAccessManager();
 
  364         String tableSchema = 
"( table_name TEXT PRIMARY KEY, " 
  367         portableSkCase.getCaseDbAccessManager().createTable(MAX_ID_TABLE_NAME, tableSchema);
 
  369         currentCaseDbManager.select(
"max(obj_id) as max_id from tsk_objects", 
new StoreMaxIdCallback(
"tsk_objects"));
 
  370         currentCaseDbManager.select(
"max(tag_id) as max_id from content_tags", 
new StoreMaxIdCallback(
"content_tags"));
 
  371         currentCaseDbManager.select(
"max(tag_id) as max_id from blackboard_artifact_tags", 
new StoreMaxIdCallback(
"blackboard_artifact_tags")); 
 
  372         currentCaseDbManager.select(
"max(examiner_id) as max_id from tsk_examiners", 
new StoreMaxIdCallback(
"tsk_examiners")); 
 
  389         for (ContentTag tag : tags) {
 
  396             Content content = tag.getContent();
 
  397             if (content instanceof AbstractFile) {
 
  398                 long newFileId = copyContentToPortableCase(content, progressPanel);
 
  401                 if (! oldTagNameToNewTagName.containsKey(tag.getName())) {
 
  402                     throw new TskCoreException(
"TagName map is missing entry for ID " + tag.getName().getId() + 
" with display name " + tag.getName().getDisplayName());
 
  404                 portableSkCase.addContentTag(newIdToContent.get(newFileId), oldTagNameToNewTagName.get(tag.getName()), tag.getComment(), tag.getBeginByteOffset(), tag.getEndByteOffset());
 
  422         for (BlackboardArtifactTag tag : tags) {
 
  430             Content content = tag.getContent();
 
  431             long newContentId = copyContentToPortableCase(content, progressPanel);
 
  434             BlackboardArtifact newArtifact = copyArtifact(newContentId, tag.getArtifact());
 
  437             if (! oldTagNameToNewTagName.containsKey(tag.getName())) {
 
  438                 throw new TskCoreException(
"TagName map is missing entry for ID " + tag.getName().getId() + 
" with display name " + tag.getName().getDisplayName());
 
  440             portableSkCase.addBlackboardArtifactTag(newArtifact, oldTagNameToNewTagName.get(tag.getName()), tag.getComment());
 
  454     private BlackboardArtifact 
copyArtifact(
long newContentId, BlackboardArtifact artifactToCopy) 
throws TskCoreException {
 
  456         if (oldArtifactIdToNewArtifact.containsKey(artifactToCopy.getArtifactID())) {
 
  457             return oldArtifactIdToNewArtifact.get(artifactToCopy.getArtifactID());
 
  461         BlackboardAttribute oldAssociatedAttribute = artifactToCopy.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
 
  462         List<BlackboardAttribute> newAttrs = 
new ArrayList<>();
 
  463         if (oldAssociatedAttribute != null) {
 
  464             BlackboardArtifact oldAssociatedArtifact = currentCase.
getSleuthkitCase().getBlackboardArtifact(oldAssociatedAttribute.getValueLong());
 
  465             BlackboardArtifact newAssociatedArtifact = copyArtifact(newContentId, oldAssociatedArtifact);
 
  466             newAttrs.add(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, 
 
  467                         String.join(
",", oldAssociatedAttribute.getSources()), newAssociatedArtifact.getArtifactID()));
 
  471         int newArtifactTypeId = getNewArtifactTypeId(artifactToCopy);
 
  472         BlackboardArtifact newArtifact = portableSkCase.newBlackboardArtifact(newArtifactTypeId, newContentId);
 
  473         List<BlackboardAttribute> oldAttrs = artifactToCopy.getAttributes();
 
  476         for (BlackboardAttribute oldAttr:oldAttrs) {
 
  479             if (oldAttr.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
 
  483             BlackboardAttribute.Type newAttributeType = getNewAttributeType(oldAttr);
 
  484             switch (oldAttr.getValueType()) {
 
  486                     newAttrs.add(
new BlackboardAttribute(newAttributeType, String.join(
",", oldAttr.getSources()),
 
  487                             oldAttr.getValueBytes()));
 
  490                     newAttrs.add(
new BlackboardAttribute(newAttributeType, String.join(
",", oldAttr.getSources()),
 
  491                             oldAttr.getValueDouble()));
 
  494                     newAttrs.add(
new BlackboardAttribute(newAttributeType, String.join(
",", oldAttr.getSources()),
 
  495                             oldAttr.getValueInt()));
 
  499                     newAttrs.add(
new BlackboardAttribute(newAttributeType, String.join(
",", oldAttr.getSources()),
 
  500                             oldAttr.getValueLong()));
 
  503                     newAttrs.add(
new BlackboardAttribute(newAttributeType, String.join(
",", oldAttr.getSources()),
 
  504                             oldAttr.getValueString()));
 
  507                     throw new TskCoreException(
"Unexpected attribute value type found: " + oldAttr.getValueType().getLabel());
 
  511         newArtifact.addAttributes(newAttrs);
 
  513         oldArtifactIdToNewArtifact.put(artifactToCopy.getArtifactID(), newArtifact);
 
  526         if (oldArtTypeIdToNewArtTypeId.containsKey(oldArtifact.getArtifactTypeID())) {
 
  527             return oldArtTypeIdToNewArtTypeId.get(oldArtifact.getArtifactTypeID());
 
  530         BlackboardArtifact.Type oldCustomType = currentCase.
getSleuthkitCase().getArtifactType(oldArtifact.getArtifactTypeName());
 
  532             BlackboardArtifact.Type newCustomType = portableSkCase.addBlackboardArtifactType(oldCustomType.getTypeName(), oldCustomType.getDisplayName());
 
  533             oldArtTypeIdToNewArtTypeId.put(oldArtifact.getArtifactTypeID(), newCustomType.getTypeID());
 
  534             return newCustomType.getTypeID();
 
  535         } 
catch (TskDataException ex) {
 
  536             throw new TskCoreException(
"Error creating new artifact type " + oldCustomType.getTypeName(), ex);
 
  548     private BlackboardAttribute.Type 
getNewAttributeType(BlackboardAttribute oldAttribute) 
throws TskCoreException {
 
  549         BlackboardAttribute.Type oldAttrType = oldAttribute.getAttributeType();
 
  550         if (oldAttrTypeIdToNewAttrType.containsKey(oldAttrType.getTypeID())) {
 
  551             return oldAttrTypeIdToNewAttrType.get(oldAttrType.getTypeID());
 
  555             BlackboardAttribute.Type newCustomType = portableSkCase.addArtifactAttributeType(oldAttrType.getTypeName(), 
 
  556                     oldAttrType.getValueType(), oldAttrType.getDisplayName());
 
  557             oldAttrTypeIdToNewAttrType.put(oldAttribute.getAttributeType().getTypeID(), newCustomType);
 
  558             return newCustomType;
 
  559         } 
catch (TskDataException ex) {
 
  560             throw new TskCoreException(
"Error creating new attribute type " + oldAttrType.getTypeName(), ex);
 
  576         "CreatePortableCaseModule.copyContentToPortableCase.copyingFile=Copying file {0}",  
 
  579         progressPanel.
updateStatusLabel(Bundle.CreatePortableCaseModule_copyContentToPortableCase_copyingFile(content.getUniquePath()));
 
  582         CaseDbTransaction trans = portableSkCase.beginTransaction();
 
  584             newFileId = copyContent(content, trans);
 
  587         } 
catch (TskCoreException ex) {
 
  603     private long copyContent(Content content, CaseDbTransaction trans) 
throws TskCoreException {
 
  606         if (oldIdToNewContent.containsKey(content.getId())) {
 
  607             return oldIdToNewContent.get(content.getId()).getId();
 
  614         if (content.getParent() != null) {
 
  615             parentId = copyContent(content.getParent(), trans);
 
  619         if (content instanceof Image) {
 
  620             Image image = (Image)content;
 
  621             newContent = portableSkCase.addImage(image.getType(), image.getSsize(), image.getSize(), image.getName(), 
 
  622                     new ArrayList<>(), image.getTimeZone(), image.getMd5(), image.getSha1(), image.getSha256(), image.getDeviceId(), trans);
 
  623         } 
else if (content instanceof VolumeSystem) {
 
  624             VolumeSystem vs = (VolumeSystem)content;
 
  625             newContent = portableSkCase.addVolumeSystem(parentId, vs.getType(), vs.getOffset(), vs.getBlockSize(), trans);
 
  626         } 
else if (content instanceof Volume) {
 
  627             Volume vs = (Volume)content;
 
  628             newContent = portableSkCase.addVolume(parentId, vs.getAddr(), vs.getStart(), vs.getLength(), 
 
  629                     vs.getDescription(), vs.getFlags(), trans);
 
  630         } 
else if (content instanceof FileSystem) {
 
  631             FileSystem fs = (FileSystem)content;
 
  632             newContent = portableSkCase.addFileSystem(parentId, fs.getImageOffset(), fs.getFsType(), fs.getBlock_size(), 
 
  633                     fs.getBlock_count(), fs.getRoot_inum(), fs.getFirst_inum(), fs.getLastInum(), 
 
  634                     fs.getName(), trans);
 
  635         } 
else if (content instanceof AbstractFile) {
 
  636             AbstractFile abstractFile = (AbstractFile)content;
 
  638             if (abstractFile instanceof LocalFilesDataSource) {
 
  639                 LocalFilesDataSource localFilesDS = (LocalFilesDataSource)abstractFile;
 
  640                 newContent = portableSkCase.addLocalFilesDataSource(localFilesDS.getDeviceId(), localFilesDS.getName(), localFilesDS.getTimeZone(), trans);    
 
  642                 if (abstractFile.isDir()) {
 
  643                     newContent = portableSkCase.addLocalDirectory(parentId, abstractFile.getName(), trans);
 
  648                         String exportSubFolder = getExportSubfolder(abstractFile);
 
  649                         File exportFolder = Paths.get(copiedFilesFolder.toString(), exportSubFolder).toFile();
 
  650                         File localFile = 
new File(exportFolder, fileName);
 
  654                         Content oldParent = abstractFile.getParent();
 
  655                         if (! oldIdToNewContent.containsKey(oldParent.getId())) {
 
  656                             throw new TskCoreException(
"Parent of file with ID " + abstractFile.getId() + 
" has not been created");
 
  658                         Content newParent = oldIdToNewContent.get(oldParent.getId());
 
  661                         String relativePath = FILE_FOLDER_NAME + File.separator +  exportSubFolder + File.separator + fileName;
 
  663                         newContent = portableSkCase.addLocalFile(abstractFile.getName(), relativePath, abstractFile.getSize(),
 
  664                                 abstractFile.getCtime(), abstractFile.getCrtime(), abstractFile.getAtime(), abstractFile.getMtime(),
 
  665                                 abstractFile.getMd5Hash(), abstractFile.getKnown(), abstractFile.getMIMEType(),
 
  666                                 true, TskData.EncodingType.NONE, 
 
  668                     } 
catch (IOException ex) {
 
  669                         throw new TskCoreException(
"Error copying file " + abstractFile.getName() + 
" with original obj ID "  
  670                                 + abstractFile.getId(), ex);
 
  675             throw new TskCoreException(
"Trying to copy unexpected Content type " + content.getClass().getName());
 
  679         oldIdToNewContent.put(content.getId(), newContent);
 
  680         newIdToContent.put(newContent.getId(), newContent);
 
  681         return oldIdToNewContent.get(content.getId()).getId();
 
  692         if (abstractFile.getMIMEType() == null || abstractFile.getMIMEType().isEmpty()) {
 
  693             return UNKNOWN_FILE_TYPE_FOLDER;
 
  697             if (cat.getMediaTypes().contains(abstractFile.getMIMEType())) {
 
  698                 return cat.getDisplayName();
 
  701         return UNKNOWN_FILE_TYPE_FOLDER;
 
  708         oldIdToNewContent.clear();
 
  709         newIdToContent.clear();
 
  710         oldTagNameToNewTagName.clear();
 
  711         oldArtTypeIdToNewArtTypeId.clear();
 
  712         oldAttrTypeIdToNewAttrType.clear();
 
  713         oldArtifactIdToNewArtifact.clear();
 
  716         if (portableSkCase != null) {
 
  717             portableSkCase.
close();
 
  718             portableSkCase = null;
 
  721         copiedFilesFolder = null;
 
  726         configPanel = 
new CreatePortableCasePanel();
 
  735             this.tableName = tableName;
 
  744                         Long maxId = rs.getLong(
"max_id");
 
  745                         String query = 
" (table_name, max_id) VALUES ('" + tableName + 
"', '" + maxId + 
"')";
 
  746                         portableSkCase.getCaseDbAccessManager().insert(MAX_ID_TABLE_NAME, query);
 
  748                     } 
catch (SQLException ex) {
 
  749                         logger.log(Level.WARNING, 
"Unable to get maximum ID from result set", ex);
 
  750                     } 
catch (TskCoreException ex) {
 
  751                         logger.log(Level.WARNING, 
"Unable to save maximum ID from result set", ex);
 
  755             } 
catch (SQLException ex) {
 
  756                 logger.log(Level.WARNING, 
"Failed to get maximum ID from result set", ex);
 
int getNewArtifactTypeId(BlackboardArtifact oldArtifact)
BlackboardArtifact copyArtifact(long newContentId, BlackboardArtifact artifactToCopy)
void process(ResultSet rs)
void addFilesToPortableCase(TagName oldTagName, ReportProgressPanel progressPanel)
void complete(ReportStatus reportStatus)
CreatePortableCasePanel configPanel
static< T > long writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, Future< T > worker, boolean source)
void handleError(String logWarning, String dialogWarning, Exception ex, ReportProgressPanel progressPanel)
CreatePortableCaseModule()
void setIndeterminate(boolean indeterminate)
TagsManager getTagsManager()
void generateReport(String reportPath, ReportProgressPanel progressPanel)
void createCase(File outputDir, ReportProgressPanel progressPanel)
String getRelativeFilePath()
SleuthkitCase getSleuthkitCase()
String getExportSubfolder(AbstractFile abstractFile)
SleuthkitCase createPortableCase(String caseName, File portableCaseFolder)
static String escapeFileName(String fileName)
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
void updateStatusLabel(String statusMessage)
long copyContentToPortableCase(Content content, ReportProgressPanel progressPanel)
JPanel getConfigurationPanel()
long copyContent(Content content, CaseDbTransaction trans)
BlackboardAttribute.Type getNewAttributeType(BlackboardAttribute oldAttribute)
static void error(String message)
void addArtifactsToPortableCase(TagName oldTagName, ReportProgressPanel progressPanel)