Setup up context menu for slack files.

Don't skip slack files in file type ID
This commit is contained in:
Ann Priestman 2016-11-07 09:45:50 -05:00
parent 00a95a272d
commit d0ffab6caa
14 changed files with 195 additions and 10 deletions

View File

@ -111,7 +111,7 @@ abstract class AbstractContentChildren<T> extends Keys<T> {
@Override @Override
public AbstractContentNode<? extends Content> visit(SlackFile sf) { public AbstractContentNode<? extends Content> visit(SlackFile sf) {
return new FileNode(sf); return new SlackFileNode(sf);
} }
@Override @Override

View File

@ -224,6 +224,8 @@ ReportNode.reportNameProperty.desc=Name of the report
ReportsListNode.displayName=Reports ReportsListNode.displayName=Reports
SlackFileFilterNode.selectionContext.dataSources=Data Sources SlackFileFilterNode.selectionContext.dataSources=Data Sources
SlackFileFilterNode.selectionContext.views=Views SlackFileFilterNode.selectionContext.views=Views
SlackFileNode.getActions.viewInNewWin.text=View in New Window
SlackFileNode.getActions.viewFileInDir.text=View File in Directory
TagNameNode.namePlusTags.text={0} Tags TagNameNode.namePlusTags.text={0} Tags
TagNameNode.contentTagTypeNodeKey.text=Content Tags TagNameNode.contentTagTypeNodeKey.text=Content Tags
TagNameNode.bbArtTagTypeNodeKey.text=Result Tags TagNameNode.bbArtTagTypeNodeKey.text=Result Tags

View File

@ -42,6 +42,8 @@ interface ContentNodeVisitor<T> {
T visit(LocalFileNode dfn); T visit(LocalFileNode dfn);
T visit(SlackFileNode sfn);
/** /**
* Visitor with an implementable default behavior for all types. Override * Visitor with an implementable default behavior for all types. Override
* specific visit types to not use the default behavior. * specific visit types to not use the default behavior.
@ -93,5 +95,10 @@ interface ContentNodeVisitor<T> {
public T visit(VirtualDirectoryNode ldn) { public T visit(VirtualDirectoryNode ldn) {
return defaultVisit(ldn); return defaultVisit(ldn);
} }
@Override
public T visit(SlackFileNode sfn) {
return defaultVisit(sfn);
}
} }
} }

View File

@ -43,6 +43,7 @@ import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.ReadContentInputStream;
import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.datamodel.VirtualDirectory;
@ -356,6 +357,18 @@ public final class ContentUtils {
return null; return null;
} }
@Override
public Void visit(SlackFile f) {
try {
ContentUtils.writeToFile(f, dest, progress, worker, source);
} catch (IOException ex) {
logger.log(Level.SEVERE,
"Trouble extracting slack file to " + dest.getAbsolutePath(), //NON-NLS
ex);
}
return null;
}
@Override @Override
public Void visit(Directory dir) { public Void visit(Directory dir) {
return visitDir(dir); return visitDir(dir);

View File

@ -37,6 +37,7 @@ import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.datamodel.VirtualDirectory;
/** /**
@ -81,6 +82,23 @@ public class DataModelActionsFactory {
return actions; return actions;
} }
public static List<Action> getActions(SlackFile slackFile, boolean isArtifactSource) {
List<Action> actions = new ArrayList<>();
actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), slackFile));
final SlackFileNode slackFileNode = new SlackFileNode(slackFile);
actions.add(null); // creates a menu separator
actions.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, slackFileNode));
actions.add(null); // creates a menu separator
actions.add(ExtractAction.getInstance());
actions.add(null); // creates a menu separator
actions.add(AddContentTagAction.getInstance());
if (isArtifactSource) {
actions.add(AddBlackboardArtifactTagAction.getInstance());
}
actions.addAll(ContextMenuExtensionPoint.getActions());
return actions;
}
public static List<Action> getActions(LayoutFile file, boolean isArtifactSource) { public static List<Action> getActions(LayoutFile file, boolean isArtifactSource) {
List<Action> actions = new ArrayList<>(); List<Action> actions = new ArrayList<>();
actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file)); actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file));
@ -184,6 +202,8 @@ public class DataModelActionsFactory {
return getActions((LocalFile) content, isArtifactSource); return getActions((LocalFile) content, isArtifactSource);
} else if (content instanceof DerivedFile) { } else if (content instanceof DerivedFile) {
return getActions((DerivedFile) content, isArtifactSource); return getActions((DerivedFile) content, isArtifactSource);
} else if (content instanceof SlackFile) {
return getActions((SlackFile) content, isArtifactSource);
} else { } else {
return new ArrayList<>(); return new ArrayList<>();
} }

View File

@ -49,6 +49,9 @@ public interface DisplayableItemNodeVisitor<T> {
T visit(VolumeNode vn); T visit(VolumeNode vn);
T visit(SlackFileNode sfn);
/* /*
* Views Area * Views Area
*/ */
@ -177,6 +180,11 @@ public interface DisplayableItemNodeVisitor<T> {
return defaultVisit(vn); return defaultVisit(vn);
} }
@Override
public T visit(SlackFileNode sfn) {
return defaultVisit(sfn);
}
@Override @Override
public T visit(BlackboardArtifactNode ban) { public T visit(BlackboardArtifactNode ban) {
return defaultVisit(ban); return defaultVisit(ban);

View File

@ -0,0 +1,115 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datamodel;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Action;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.actions.AddContentTagAction;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.directorytree.ExtractAction;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM;
/**
* This class is the Node for an AbstractFile. It may have derived files
* children.
*/
public class SlackFileNode extends AbstractFsContentNode<AbstractFile> {
/**
* Constructor
*
* @param file underlying Content
*/
public SlackFileNode(AbstractFile file) {
this(file, true);
setIcon(file);
}
public SlackFileNode(AbstractFile file, boolean directoryBrowseMode) {
super(file, directoryBrowseMode);
setIcon(file);
}
private void setIcon(AbstractFile file) {
// set name, display name, and icon
if (file.isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM.UNALLOC)) {
if (file.getType().equals(TSK_DB_FILES_TYPE_ENUM.CARVED)) {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/carved-file-icon-16.png"); //NON-NLS
} else {
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); //NON-NLS
}
} else {
this.setIconBaseWithExtension(getIconForFileType(file));
}
}
@Override
public Action[] getActions(boolean popup) {
List<Action> actionsList = new ArrayList<>();
for (Action a : super.getActions(true)) {
actionsList.add(a);
}
if (!this.getDirectoryBrowseMode()) {
actionsList.add(new ViewContextAction(NbBundle.getMessage(this.getClass(), "SlackFileNode.viewFileInDir.text"), this.content));
actionsList.add(null); // creates a menu separator
}
actionsList.add(new NewWindowViewAction(
NbBundle.getMessage(this.getClass(), "SlackFileNode.getActions.viewInNewWin.text"), this));
actionsList.add(null); // creates a menu separator
actionsList.add(ExtractAction.getInstance());
actionsList.add(null); // creates a menu separator
actionsList.add(AddContentTagAction.getInstance());
actionsList.addAll(ContextMenuExtensionPoint.getActions());
return actionsList.toArray(new Action[actionsList.size()]);
}
@Override
public <T> T accept(ContentNodeVisitor<T> v) {
return v.visit(this);
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
}
// Given a file, returns the correct icon for said
// file based off it's extension
static String getIconForFileType(AbstractFile file) {
return "org/sleuthkit/autopsy/images/file-icon.png"; //NON-NLS
}
@Override
public boolean isLeafTypeNode() {
// This seems wrong, but it also seems that it is never called
// because the visitor to figure out if there are children or
// not will check if it has children using the Content API
return true;
}
}

View File

@ -45,6 +45,7 @@ import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode;
import org.sleuthkit.autopsy.datamodel.Reports; import org.sleuthkit.autopsy.datamodel.Reports;
import org.sleuthkit.autopsy.datamodel.SlackFileNode;
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
@ -55,6 +56,7 @@ import org.sleuthkit.datamodel.Directory;
import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.SlackFile;
import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.datamodel.VirtualDirectory;
@ -200,6 +202,8 @@ public class DataResultFilterNode extends FilterNode {
} else if ((c = ban.getLookup().lookup(LocalFile.class)) != null } else if ((c = ban.getLookup().lookup(LocalFile.class)) != null
|| (c = ban.getLookup().lookup(DerivedFile.class)) != null) { || (c = ban.getLookup().lookup(DerivedFile.class)) != null) {
n = new LocalFileNode((AbstractFile) c); n = new LocalFileNode((AbstractFile) c);
} else if ((c = ban.getLookup().lookup(SlackFile.class)) != null) {
n = new SlackFileNode((SlackFile) c);
} }
if (n != null) { if (n != null) {
actions.add(null); // creates a menu separator actions.add(null); // creates a menu separator

View File

@ -31,6 +31,7 @@ import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor;
import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.autopsy.datamodel.FileNode;
import org.sleuthkit.autopsy.datamodel.LayoutFileNode; import org.sleuthkit.autopsy.datamodel.LayoutFileNode;
import org.sleuthkit.autopsy.datamodel.LocalFileNode; import org.sleuthkit.autopsy.datamodel.LocalFileNode;
import org.sleuthkit.autopsy.datamodel.SlackFileNode;
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
import org.sleuthkit.autopsy.datamodel.VolumeNode; import org.sleuthkit.autopsy.datamodel.VolumeNode;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
@ -226,6 +227,11 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
return visitDeep(fn); return visitDeep(fn);
} }
@Override
public Boolean visit(SlackFileNode sfn) {
return visitDeep(sfn);
}
@Override @Override
public Boolean visit(VolumeNode vn) { public Boolean visit(VolumeNode vn) {
return isLeafVolume(vn); return isLeafVolume(vn);
@ -268,6 +274,11 @@ class DirectoryTreeFilterChildren extends FilterNode.Children {
return ln.hasContentChildren(); return ln.hasContentChildren();
} }
@Override
public Boolean visit(SlackFileNode sfn) {
return sfn.hasContentChildren();
}
@Override @Override
public Boolean visit(VirtualDirectoryNode vdn) { public Boolean visit(VirtualDirectoryNode vdn) {
return true; return true;

View File

@ -30,6 +30,7 @@ import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.datamodel.SlackFileNode;
/** /**
* Extracts a File object to a temporary file in the case directory, and then * Extracts a File object to a temporary file in the case directory, and then
@ -68,7 +69,8 @@ public class ExternalViewerAction extends AbstractAction {
// no point opening a file if it's empty, and java doesn't know how to // no point opening a file if it's empty, and java doesn't know how to
// find an application for files without an extension // find an application for files without an extension
// or if file is executable (for security reasons) // or if file is executable (for security reasons)
if (!(size > 0) || extPos == -1 || isExecutable) { // Also skip slack files since their extension is the original extension + "-slack"
if (!(size > 0) || extPos == -1 || isExecutable || (fileNode instanceof SlackFileNode)) {
this.setEnabled(false); this.setEnabled(false);
} }
} }

View File

@ -119,7 +119,7 @@ final class FileIngestPipeline {
List<IngestModuleError> errors = new ArrayList<>(); List<IngestModuleError> errors = new ArrayList<>();
if (!this.job.isCancelled()) { if (!this.job.isCancelled()) {
AbstractFile file = task.getFile(); AbstractFile file = task.getFile();
if(file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)){ // TEMP TEMP //if(file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)){ // TEMP TEMP
for (PipelineModule module : this.modules) { for (PipelineModule module : this.modules) {
try { try {
FileIngestPipeline.ingestManager.setIngestTaskProgress(task, module.getDisplayName()); FileIngestPipeline.ingestManager.setIngestTaskProgress(task, module.getDisplayName());
@ -142,7 +142,7 @@ final class FileIngestPipeline {
if (!this.job.isCancelled()) { if (!this.job.isCancelled()) {
IngestManager.getInstance().fireFileIngestDone(file); IngestManager.getInstance().fireFileIngestDone(file);
} }
}// END TEMP //}// END TEMP
} }
FileIngestPipeline.ingestManager.setIngestTaskProgressCompleted(task); FileIngestPipeline.ingestManager.setIngestTaskProgressCompleted(task);
return errors; return errors;

View File

@ -207,7 +207,8 @@ public class FileTypeDetector {
if (!file.isFile() || file.getSize() <= 0 if (!file.isFile() || file.getSize() <= 0
|| (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
|| (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS)
|| (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)) { || (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR)
|| (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) {
mimeType = MimeTypes.OCTET_STREAM; mimeType = MimeTypes.OCTET_STREAM;
} }
@ -289,6 +290,7 @@ public class FileTypeDetector {
* posting because general info artifacts are different from other * posting because general info artifacts are different from other
* artifacts, e.g., they are not displayed in the results tree. * artifacts, e.g., they are not displayed in the results tree.
*/ */
BlackboardArtifact getInfoArt = file.getGenInfoArtifact(); BlackboardArtifact getInfoArt = file.getGenInfoArtifact();
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType); BlackboardAttribute batt = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG, FileTypeIdModuleFactory.getModuleName(), mimeType);

View File

@ -86,11 +86,6 @@ public class FileTypeIdIngestModule implements FileIngestModule {
@Override @Override
public ProcessResult process(AbstractFile file) { public ProcessResult process(AbstractFile file) {
//skip slack files
if (file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) {
return ProcessResult.OK;
}
/** /**
* Attempt to detect the file type. Do it within an exception firewall, * Attempt to detect the file type. Do it within an exception firewall,
* so that any issues with reading file content or complaints from tika * so that any issues with reading file content or complaints from tika

View File

@ -24,6 +24,7 @@ import org.openide.util.NbBundle;
import org.openide.util.actions.SystemAction; import org.openide.util.actions.SystemAction;
import org.sleuthkit.autopsy.timeline.OpenTimelineAction; import org.sleuthkit.autopsy.timeline.OpenTimelineAction;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskData;
/** /**
* An action to prompt the user to pick an timestamp/event associated with the * An action to prompt the user to pick an timestamp/event associated with the
@ -38,6 +39,11 @@ public final class ViewFileInTimelineAction extends AbstractAction {
private ViewFileInTimelineAction(AbstractFile file, String displayName) { private ViewFileInTimelineAction(AbstractFile file, String displayName) {
super(displayName); super(displayName);
this.file = file; this.file = file;
if(file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)
|| file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)){
this.setEnabled(false);
}
} }
@NbBundle.Messages({"ViewFileInTimelineAction.viewFile.displayName=View File in Timeline... "}) @NbBundle.Messages({"ViewFileInTimelineAction.viewFile.displayName=View File in Timeline... "})