diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageAction.java index 8b4ef96f1d..cdfb561ae0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageAction.java @@ -109,7 +109,7 @@ public final class AddImageAction extends CallableSystemAction implements Presen Logger.noteAction(AddImageAction.class); final IngestConfigurator ingestConfig = Lookup.getDefault().lookup(IngestConfigurator.class); - if (ingestConfig.isIngestRunning()) { + if (null != ingestConfig && ingestConfig.isIngestRunning()) { final String msg = "Ingest is ongoing on another data source. Adding a new source now might slow down the current ingest.
Do you want to proceed and add a new data source now?"; if (JOptionPane.showConfirmDialog(null, msg, "Ingest in progress", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.NO_OPTION) { return; @@ -128,7 +128,6 @@ public final class AddImageAction extends CallableSystemAction implements Presen dialog.setVisible(true); dialog.toFront(); - // Do any cleanup that needs to happen (potentially: stopping the //add-image process, reverting an image) runCleanupTasks(); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/GeneralIngestConfigurator.java b/Core/src/org/sleuthkit/autopsy/casemodule/GeneralIngestConfigurator.java new file mode 100644 index 0000000000..3ce1571150 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/casemodule/GeneralIngestConfigurator.java @@ -0,0 +1,151 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013 Basis Technology Corp. + * Contact: carrier sleuthkit 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.casemodule; + +import java.util.ArrayList; +import java.util.List; +import javax.swing.JPanel; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.coreutils.ModuleSettings; +import org.sleuthkit.autopsy.ingest.IngestDialogPanel; +import static org.sleuthkit.autopsy.ingest.IngestDialogPanel.DISABLED_MOD; +import static org.sleuthkit.autopsy.ingest.IngestDialogPanel.PARSE_UNALLOC; +import org.sleuthkit.autopsy.ingest.IngestManager; +import org.sleuthkit.autopsy.ingest.IngestModuleAbstract; +import org.sleuthkit.datamodel.Content; + +@ServiceProvider(service = IngestConfigurator.class) +public class GeneralIngestConfigurator implements IngestConfigurator { + private List contentToIngest; + private IngestManager manager; + private IngestDialogPanel ingestDialogPanel; + private String moduleContext; + + public GeneralIngestConfigurator() { + this.moduleContext = IngestManager.MODULE_PROPERTIES; // Hard-code this for now. + ingestDialogPanel = new IngestDialogPanel(); + manager = IngestManager.getDefault(); + loadSettings(); + } + + @Override + public JPanel getIngestConfigPanel() { + return ingestDialogPanel; + } + + @Override + public void setContent(List inputContent) { + this.contentToIngest = inputContent; + } + + @Override + public void start() { + // Get the list of ingest modules selected by the user. + List modulesToStart = ingestDialogPanel.getModulesToStart(); + + // Get the user's selection of whether or not to process unallocated space. + manager.setProcessUnallocSpace(ingestDialogPanel.processUnallocSpaceEnabled()); + + // Start the ingest. + if (!modulesToStart.isEmpty()) { + manager.execute(modulesToStart, contentToIngest); + } + } + + @Override + public void save() { + // Save the user's configuration of the currently selected module. + IngestModuleAbstract currentModule = ingestDialogPanel.getCurrentIngestModule(); + if (currentModule != null && currentModule.hasSimpleConfiguration()) { + currentModule.saveSimpleConfiguration(); + } + + // Create a list of the modules the user wants to be disabled. + List disabledModules = IngestManager.getDefault().enumerateAllModules(); + disabledModules.removeAll(ingestDialogPanel.getModulesToStart()); + String disabledModulesCsv = moduleListToCsv(disabledModules); + + // Save the user's general ingest configuration. + ModuleSettings.setConfigSetting(moduleContext, DISABLED_MOD, disabledModulesCsv); + String processUnalloc = Boolean.toString(ingestDialogPanel.processUnallocSpaceEnabled()); + ModuleSettings.setConfigSetting(moduleContext, PARSE_UNALLOC, processUnalloc); + } + + @Override + public void reload() { + loadSettings(); + } + + @Override + public boolean isIngestRunning() { + return manager.isIngestRunning(); + } + + private static String moduleListToCsv(List lst) { + if (lst == null || lst.isEmpty()) { + return ""; + } + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < lst.size() - 1; ++i) { + sb.append(lst.get(i).getName()).append(", "); + } + + // and the last one + sb.append(lst.get(lst.size() - 1).getName()); + + return sb.toString(); + } + + private static List csvToModuleList(String csv) { + List modules = new ArrayList<>(); + + if (csv == null || csv.isEmpty()) { + return modules; + } + + String[] moduleNames = csv.split(", "); + List allModules = IngestManager.getDefault().enumerateAllModules(); + for (String moduleName : moduleNames) { + for (IngestModuleAbstract module : allModules) { + if (moduleName.equals(module.getName())) { + modules.add(module); + break; + } + } + } + + return modules; + } + + private void loadSettings() { + // get the csv list of disabled modules + String disabledModulesCsv = ModuleSettings.getConfigSetting(moduleContext, DISABLED_MOD); + + // create a list of modules from it + List disabledModules = csvToModuleList(disabledModulesCsv); + + // tell the ingestDialogPanel to unselect these modules + ingestDialogPanel.setDisabledModules(disabledModules); + + boolean processUnalloc = Boolean.parseBoolean(ModuleSettings.getConfigSetting(moduleContext, PARSE_UNALLOC)); + ingestDialogPanel.setProcessUnallocSpaceEnabled(processUnalloc); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/IngestConfigurator.java b/Core/src/org/sleuthkit/autopsy/casemodule/IngestConfigurator.java index cca3e2d064..45f6a8e80d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/IngestConfigurator.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/IngestConfigurator.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -59,5 +59,5 @@ public interface IngestConfigurator { * @return true if ingest process is running, false otherwise */ boolean isIngestRunning(); - + } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java index 3387065d1d..942bbbd242 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java @@ -81,21 +81,17 @@ public abstract class AbstractDataResultViewer extends JPanel implements // change the cursor to "waiting cursor" for this operation setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); try { - Node selectedNode = getSelectedNode(); - - nodeSelected(selectedNode); - - - - if (selectedNode != null) { + Node[] selectedNodes = getExplorerManager().getSelectedNodes(); + if (selectedNodes.length == 1) { + nodeSelected(selectedNodes[0]); + // there's a new/changed node to display - Node newSelectedNode = selectedNode; // get the selected Node on the table // push the node to default "DataContent" //TODO only the active viewer should be calling setNode //not all of them, otherwise it results in multiple setNode() invocations //alternative is to use a single instance of the event listener //, per top component and not the tab perhaps - contentViewer.setNode(newSelectedNode); + contentViewer.setNode(selectedNodes[0]); } else { // clear the node viewer contentViewer.setNode(null); @@ -131,6 +127,7 @@ public abstract class AbstractDataResultViewer extends JPanel implements } } + @Deprecated public Node getSelectedNode() { Node result = null; Node[] selectedNodes = this.getExplorerManager().getSelectedNodes(); diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java index ecdf121466..dc4fbb6d8f 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.List; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResult; import java.util.logging.Level; +import org.openide.explorer.ExplorerUtils; import org.openide.util.NbBundle; import org.openide.windows.TopComponent; import org.openide.nodes.Node; @@ -96,9 +97,9 @@ public class DataResultTopComponent extends TopComponent implements DataResult { initComponents(); customizeComponent(isMain, name);; - + } - + private void customizeComponent(boolean isMain, String title) { this.isMain = isMain; this.customModeName = null; @@ -260,6 +261,14 @@ public class DataResultTopComponent extends TopComponent implements DataResult { super.componentOpened(); this.dataResultPanel.open(); + + List resultViewers = this.dataResultPanel.getViewers(); + for (DataResultViewer viewer : resultViewers) { + if (viewer instanceof DataResultViewerTable) { + associateLookup(ExplorerUtils.createLookup(((DataResultViewerTable)viewer).getExplorerManager(), getActionMap())); + break; + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 9ab0d40dea..6f5368578b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -62,7 +62,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { ov.setAllowedDropActions(DnDConstants.ACTION_NONE); // only allow one item to be selected at a time - ov.getOutline().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + ov.getOutline().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); // don't show the root node ov.getOutline().setRootVisible(false); diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/ModuleSettings.java b/Core/src/org/sleuthkit/autopsy/coreutils/ModuleSettings.java index 117c5eb4ab..4eff288380 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/ModuleSettings.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/ModuleSettings.java @@ -19,12 +19,17 @@ package org.sleuthkit.autopsy.coreutils; -import java.io.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.logging.Level; + /** * This class contains the framework to read, add, update, and remove * from the property files located at %USERDIR%/Config/x.properties @@ -33,15 +38,11 @@ public class ModuleSettings { // The directory where the properties file is lcoated private final static String moduleDirPath = PlatformUtil.getUserConfigDirectory(); - public static final String MAIN_SETTINGS="Case"; + public static final String MAIN_SETTINGS = "Case"; - /** the constructor */ - private ModuleSettings() { - - } - - + private ModuleSettings() {} + /** * Makes a new config file of the specified name. Do not include the extension. * @param moduleName - The name of the config file to make @@ -161,9 +162,7 @@ public class ModuleSettings { return null; } } - - - + /** * Sets the given properties file to the given setting map. * @param moduleName - The name of the module to be written to. @@ -215,14 +214,12 @@ public class ModuleSettings { Logger.getLogger(ModuleSettings.class.getName()).log(Level.WARNING, "Property file exists for [" + moduleName + "] at [" + getPropertyPath(moduleName) + "] but could not be loaded.", e); } } - /** * Removes the given key from the given properties file. * @param moduleName - The name of the properties file to be modified. * @param key - the name of the key to remove. */ - public static synchronized void removeProperty(String moduleName, String key){ try{ if(getConfigSetting(moduleName, key) != null){ @@ -268,5 +265,4 @@ public class ModuleSettings { return new File(getPropertyPath(moduleName)); } } - } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DirectoryNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/DirectoryNode.java old mode 100644 new mode 100755 index a364071ac7..3c4d33c253 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DirectoryNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DirectoryNode.java @@ -1,97 +1,97 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011 Basis Technology Corp. - * Contact: carrier sleuthkit 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.sleuthkit.autopsy.directorytree.ExtractAction; -import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; -import org.sleuthkit.autopsy.directorytree.TagAction; -import org.sleuthkit.autopsy.directorytree.ViewContextAction; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.Directory; -import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM; - -/** - * This class is used to represent the "Node" for the directory. Its children - * are more directories. - */ -public class DirectoryNode extends AbstractFsContentNode { - - public static final String DOTDOTDIR = "[parent folder]"; - public static final String DOTDIR = "[current folder]"; - - public DirectoryNode(Directory dir) { - this(dir, true); - - setIcon(dir); - } - - public DirectoryNode(AbstractFile dir, boolean directoryBrowseMode) { - super(dir, directoryBrowseMode); - - setIcon(dir); - } - - private void setIcon(AbstractFile dir) { - // set name, display name, and icon - if (dir.isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM.UNALLOC)) { - this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-deleted.png"); - } else { - this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/Folder-icon.png"); - } - } - - /** - * Right click action for this node - * - * @param popup - * @return - */ - @Override - public Action[] getActions(boolean popup) { - List actions = new ArrayList(); - if (!getDirectoryBrowseMode()) { - actions.add(new ViewContextAction("View File in Directory", this)); - actions.add(null); // creates a menu separator - } - actions.add(new NewWindowViewAction("View in New Window", this)); - actions.add(null); // creates a menu separator - actions.add(new ExtractAction("Extract Directory", this)); - actions.add(null); // creates a menu separator - actions.add(new TagAction(this)); - return actions.toArray(new Action[0]); - } - - @Override - public T accept(ContentNodeVisitor v) { - return v.visit(this); - } - - @Override - public T accept(DisplayableItemNodeVisitor v) { - return v.visit(this); - } - - @Override - public TYPE getDisplayableItemNodeType() { - return TYPE.CONTENT; - } -} +/* + * Autopsy Forensic Browser + * + * Copyright 2011 Basis Technology Corp. + * Contact: carrier sleuthkit 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.sleuthkit.autopsy.directorytree.ExtractAction; +import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; +import org.sleuthkit.autopsy.directorytree.TagAbstractFileAction; +import org.sleuthkit.autopsy.directorytree.ViewContextAction; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.Directory; +import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM; + +/** + * This class is used to represent the "Node" for the directory. Its children + * are more directories. + */ +public class DirectoryNode extends AbstractFsContentNode { + + public static final String DOTDOTDIR = "[parent folder]"; + public static final String DOTDIR = "[current folder]"; + + public DirectoryNode(Directory dir) { + this(dir, true); + + setIcon(dir); + } + + public DirectoryNode(AbstractFile dir, boolean directoryBrowseMode) { + super(dir, directoryBrowseMode); + + setIcon(dir); + } + + private void setIcon(AbstractFile dir) { + // set name, display name, and icon + if (dir.isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM.UNALLOC)) { + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/folder-icon-deleted.png"); + } else { + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/Folder-icon.png"); + } + } + + /** + * Right click action for this node + * + * @param popup + * @return + */ + @Override + public Action[] getActions(boolean popup) { + List actions = new ArrayList<>(); + if (!getDirectoryBrowseMode()) { + actions.add(new ViewContextAction("View File in Directory", this)); + actions.add(null); // creates a menu separator + } + actions.add(new NewWindowViewAction("View in New Window", this)); + actions.add(null); // creates a menu separator + actions.add(ExtractAction.getInstance()); + actions.add(null); // creates a menu separator + actions.add(TagAbstractFileAction.getInstance()); + return actions.toArray(new Action[0]); + } + + @Override + public T accept(ContentNodeVisitor v) { + return v.visit(this); + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + public TYPE getDisplayableItemNodeType() { + return TYPE.CONTENT; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java old mode 100644 new mode 100755 index 6c3f739624..9ca87fd8a7 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileNode.java @@ -1,181 +1,180 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011 Basis Technology Corp. - * Contact: carrier sleuthkit 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.sleuthkit.autopsy.directorytree.ExternalViewerAction; -import org.sleuthkit.autopsy.directorytree.ExtractAction; -import org.sleuthkit.autopsy.directorytree.HashSearchAction; -import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; -import org.sleuthkit.autopsy.directorytree.TagAction; -import org.sleuthkit.autopsy.directorytree.ViewContextAction; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.FsContent; -import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM; -import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM; - -/** - * This class is used to represent the "Node" for the file. It may have derived - * files children. - */ -public class FileNode extends AbstractFsContentNode { - - /** - * @param file underlying Content - */ - public FileNode(AbstractFile file) { - this(file, true); - - setIcon(file); - } - - public FileNode(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"); - } else { - this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); - } - } else { - this.setIconBaseWithExtension(getIconForFileType(file)); - } - } - - /** - * Right click action for this node - * - * @param popup - * @return - */ - @Override - public Action[] getActions(boolean popup) { - List actionsList = new ArrayList(); - if (!this.getDirectoryBrowseMode()) { - actionsList.add(new ViewContextAction("View File in Directory", this)); - actionsList.add(null); // creates a menu separator - } - actionsList.add(new NewWindowViewAction("View in New Window", this)); - actionsList.add(new ExternalViewerAction("Open in External Viewer", this)); - actionsList.add(null); // creates a menu separator - actionsList.add(new ExtractAction("Extract File", this)); - actionsList.add(new HashSearchAction("Search for files with the same MD5 hash", this)); - actionsList.add(null); // creates a menu separator - actionsList.add(new TagAction(this)); - return actionsList.toArray(new Action[0]); - } - - @Override - public T accept(ContentNodeVisitor< T> v) { - return v.visit(this); - } - - @Override - public 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) { - // Get the name, extension - String name = file.getName(); - int dotIndex = name.lastIndexOf("."); - if (dotIndex == -1) { - return "org/sleuthkit/autopsy/images/file-icon.png"; - } - String ext = name.substring(dotIndex).toLowerCase(); - - // Images - for (String s : FileTypeExtensions.getImageExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/image-file.png"; - } - } - // Videos - for (String s : FileTypeExtensions.getVideoExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/video-file.png"; - } - } - // Audio Files - for (String s : FileTypeExtensions.getAudioExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/audio-file.png"; - } - } - // Documents - for (String s : FileTypeExtensions.getDocumentExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/doc-file.png"; - } - } - // Executables / System Files - for (String s : FileTypeExtensions.getExecutableExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/exe-file.png"; - } - } - // Text Files - for (String s : FileTypeExtensions.getTextExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/text-file.png"; - } - } - // Web Files - for (String s : FileTypeExtensions.getWebExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/web-file.png"; - } - } - // PDFs - for (String s : FileTypeExtensions.getPDFExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/pdf-file.png"; - } - } - // Archives - for (String s : FileTypeExtensions.getArchiveExtensions()) { - if (ext.equals(s)) { - return "org/sleuthkit/autopsy/images/archive-file.png"; - } - } - // Else return the default - return "org/sleuthkit/autopsy/images/file-icon.png"; - - } - - @Override - public TYPE getDisplayableItemNodeType() { - return TYPE.CONTENT; - } - - @Override - public boolean isLeafTypeNode() { - return true; //false; - } -} +/* + * Autopsy Forensic Browser + * + * Copyright 2011 Basis Technology Corp. + * Contact: carrier sleuthkit 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.sleuthkit.autopsy.directorytree.ExternalViewerAction; +import org.sleuthkit.autopsy.directorytree.ExtractAction; +import org.sleuthkit.autopsy.directorytree.HashSearchAction; +import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; +import org.sleuthkit.autopsy.directorytree.TagAbstractFileAction; +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 used to represent the "Node" for the file. It may have derived + * files children. + */ +public class FileNode extends AbstractFsContentNode { + + /** + * @param file underlying Content + */ + public FileNode(AbstractFile file) { + this(file, true); + + setIcon(file); + } + + public FileNode(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"); + } else { + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); + } + } else { + this.setIconBaseWithExtension(getIconForFileType(file)); + } + } + + /** + * Right click action for this node + * + * @param popup + * @return + */ + @Override + public Action[] getActions(boolean popup) { + List actionsList = new ArrayList<>(); + if (!this.getDirectoryBrowseMode()) { + actionsList.add(new ViewContextAction("View File in Directory", this)); + actionsList.add(null); // creates a menu separator + } + actionsList.add(new NewWindowViewAction("View in New Window", this)); + actionsList.add(new ExternalViewerAction("Open in External Viewer", this)); + actionsList.add(null); // creates a menu separator + actionsList.add(ExtractAction.getInstance()); + actionsList.add(new HashSearchAction("Search for files with the same MD5 hash", this)); + actionsList.add(null); // creates a menu separator + actionsList.add(TagAbstractFileAction.getInstance()); + return actionsList.toArray(new Action[0]); + } + + @Override + public T accept(ContentNodeVisitor< T> v) { + return v.visit(this); + } + + @Override + public 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) { + // Get the name, extension + String name = file.getName(); + int dotIndex = name.lastIndexOf("."); + if (dotIndex == -1) { + return "org/sleuthkit/autopsy/images/file-icon.png"; + } + String ext = name.substring(dotIndex).toLowerCase(); + + // Images + for (String s : FileTypeExtensions.getImageExtensions()) { + if (ext.equals(s)) { + return "org/sleuthkit/autopsy/images/image-file.png"; + } + } + // Videos + for (String s : FileTypeExtensions.getVideoExtensions()) { + if (ext.equals(s)) { + return "org/sleuthkit/autopsy/images/video-file.png"; + } + } + // Audio Files + for (String s : FileTypeExtensions.getAudioExtensions()) { + if (ext.equals(s)) { + return "org/sleuthkit/autopsy/images/audio-file.png"; + } + } + // Documents + for (String s : FileTypeExtensions.getDocumentExtensions()) { + if (ext.equals(s)) { + return "org/sleuthkit/autopsy/images/doc-file.png"; + } + } + // Executables / System Files + for (String s : FileTypeExtensions.getExecutableExtensions()) { + if (ext.equals(s)) { + return "org/sleuthkit/autopsy/images/exe-file.png"; + } + } + // Text Files + for (String s : FileTypeExtensions.getTextExtensions()) { + if (ext.equals(s)) { + return "org/sleuthkit/autopsy/images/text-file.png"; + } + } + // Web Files + for (String s : FileTypeExtensions.getWebExtensions()) { + if (ext.equals(s)) { + return "org/sleuthkit/autopsy/images/web-file.png"; + } + } + // PDFs + for (String s : FileTypeExtensions.getPDFExtensions()) { + if (ext.equals(s)) { + return "org/sleuthkit/autopsy/images/pdf-file.png"; + } + } + // Archives + for (String s : FileTypeExtensions.getArchiveExtensions()) { + if (ext.equals(s)) { + return "org/sleuthkit/autopsy/images/archive-file.png"; + } + } + // Else return the default + return "org/sleuthkit/autopsy/images/file-icon.png"; + + } + + @Override + public TYPE getDisplayableItemNodeType() { + return TYPE.CONTENT; + } + + @Override + public boolean isLeafTypeNode() { + return true; //false; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java index 36f2fc8c02..9224131ad6 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/LayoutFileNode.java @@ -24,11 +24,10 @@ import java.util.List; import java.util.Map; import javax.swing.Action; import org.openide.nodes.Sheet; -import org.sleuthkit.autopsy.directorytree.ExplorerNodeActionVisitor; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; -import org.sleuthkit.autopsy.directorytree.TagAction; +import org.sleuthkit.autopsy.directorytree.TagAbstractFileAction; import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.TskData; @@ -104,14 +103,12 @@ public class LayoutFileNode extends AbstractAbstractFileNode { @Override public Action[] getActions(boolean context) { List actionsList = new ArrayList(); - actionsList.add(new NewWindowViewAction("View in New Window", this)); actionsList.add(new ExternalViewerAction("Open in External Viewer", this)); actionsList.add(null); // creates a menu separator - actionsList.add(new ExtractAction("Extract File", content)); + actionsList.add(ExtractAction.getInstance()); actionsList.add(null); // creates a menu separator - actionsList.add(new TagAction(content)); - + actionsList.add(TagAbstractFileAction.getInstance()); return actionsList.toArray(new Action[0]); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java index f2dc17d9a0..78711736b9 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/LocalFileNode.java @@ -30,9 +30,8 @@ import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.HashSearchAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; -import org.sleuthkit.autopsy.directorytree.TagAction; +import org.sleuthkit.autopsy.directorytree.TagAbstractFileAction; import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.LocalFile; /** * A Node for a LocalFile or DerivedFile content object. @@ -86,16 +85,14 @@ public class LocalFileNode extends AbstractAbstractFileNode { @Override public Action[] getActions(boolean context) { - List actionsList = new ArrayList(); - + List actionsList = new ArrayList<>(); actionsList.add(new NewWindowViewAction("View in New Window", this)); actionsList.add(new ExternalViewerAction("Open in External Viewer", this)); actionsList.add(null); // creates a menu separator - actionsList.add(new ExtractAction("Extract", content)); //might not need this actions - already local file + actionsList.add(ExtractAction.getInstance()); actionsList.add(new HashSearchAction("Search for files with the same MD5 hash", this)); actionsList.add(null); // creates a menu separator - actionsList.add(new TagAction(content)); - + actionsList.add(TagAbstractFileAction.getInstance()); return actionsList.toArray(new Action[0]); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index 319d36e737..064f953660 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -22,7 +22,6 @@ import java.awt.event.ActionEvent; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; -import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; import java.util.HashSet; @@ -656,36 +655,4 @@ public class Tags implements AutopsyVisitableItem { return tagNames; } - - public interface Taggable { - void createTag(String name, String comment); - } - - public static class TaggableFile implements Taggable { - - private AbstractFile file; - - public TaggableFile(AbstractFile file) { - this.file = file; - } - - @Override - public void createTag(String name, String comment) { - Tags.createTag(file, name, comment); - } - } - - public static class TaggableBlackboardArtifact implements Taggable { - - private BlackboardArtifact bba; - - public TaggableBlackboardArtifact(BlackboardArtifact bba) { - this.bba = bba; - } - - @Override - public void createTag(String name, String comment) { - Tags.createTag(bba, name, comment); - } - } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java index 59e523ff81..756a376d11 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/VirtualDirectoryNode.java @@ -27,7 +27,7 @@ import org.openide.nodes.Sheet; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; -import org.sleuthkit.autopsy.directorytree.TagAction; +import org.sleuthkit.autopsy.directorytree.TagAbstractFileAction; import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.datamodel.TskData; @@ -76,16 +76,15 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode actions = new ArrayList(); - + List actions = new ArrayList<>(); actions.add(new NewWindowViewAction("View in New Window", this)); actions.add(null); // creates a menu separator - actions.add(new ExtractAction("Extract Directory", this)); + actions.add(ExtractAction.getInstance()); actions.add(null); // creates a menu separator - actions.add(new TagAction(this)); + actions.add(TagAbstractFileAction.getInstance()); return actions.toArray(new Action[0]); } - + @Override protected Sheet createSheet() { Sheet s = super.createSheet(); diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java old mode 100644 new mode 100755 index a439a066bf..e30e9b56b1 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -1,520 +1,520 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011 Basis Technology Corp. - * Contact: carrier sleuthkit 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.directorytree; - -import java.awt.event.ActionEvent; -import java.beans.PropertyVetoException; -import java.util.ArrayList; -import java.util.List; -import org.sleuthkit.autopsy.datamodel.VolumeNode; -import org.sleuthkit.autopsy.datamodel.DirectoryNode; -import java.util.logging.Level; -import org.sleuthkit.autopsy.coreutils.Logger; -import javax.swing.AbstractAction; -import javax.swing.Action; -import org.openide.explorer.ExplorerManager; -import org.openide.nodes.AbstractNode; -import org.openide.nodes.FilterNode; -import org.openide.nodes.Node; -import org.openide.nodes.Sheet; -import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType; -import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode; -import org.sleuthkit.autopsy.datamodel.ArtifactTypeNode; -import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; -import org.sleuthkit.autopsy.datamodel.LocalFileNode; -import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.DeletedContentNode; -import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode; -import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; -import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; -import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedAccountNode; -import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedFolderNode; -import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedRootNode; -import org.sleuthkit.autopsy.datamodel.ExtractedContentNode; -import org.sleuthkit.autopsy.datamodel.FileNode; -import org.sleuthkit.autopsy.datamodel.FileSearchFilterNode; -import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode; -import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode; -import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsRootNode; -import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsSetNode; -import org.sleuthkit.autopsy.datamodel.ImageNode; -import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsKeywordNode; -import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsListNode; -import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsRootNode; -import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; -import org.sleuthkit.autopsy.datamodel.LayoutFileNode; -import org.sleuthkit.autopsy.datamodel.RecentFilesFilterNode; -import org.sleuthkit.autopsy.datamodel.RecentFilesNode; -import org.sleuthkit.autopsy.datamodel.SearchFiltersNode; -import org.sleuthkit.autopsy.datamodel.Tags.TagNodeRoot; -import org.sleuthkit.autopsy.datamodel.Tags.TagsNodeRoot; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.DerivedFile; -import org.sleuthkit.datamodel.Directory; -import org.sleuthkit.datamodel.File; -import org.sleuthkit.datamodel.LayoutFile; -import org.sleuthkit.datamodel.LocalFile; -import org.sleuthkit.datamodel.TskException; -import org.sleuthkit.datamodel.VirtualDirectory; - -/** - * This class wraps nodes as they are passed to the DataResult viewers. It - * defines the actions that the node should have. - */ -public class DataResultFilterNode extends FilterNode { - - private ExplorerManager sourceEm; - private final DisplayableItemNodeVisitor> getActionsDIV; - private final DisplayableItemNodeVisitor getPreferredActionsDIV; - - /** - * the constructor - */ - public DataResultFilterNode(Node node, ExplorerManager em) { - super(node, new DataResultFilterChildren(node, em)); - this.sourceEm = em; - getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor(); - getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor(); - } - - /** - * Right click action for the nodes that we want to pass to the directory - * table and the output view. - * - * @param popup - * @return actions - */ - @Override - public Action[] getActions(boolean popup) { - - List actions = new ArrayList(); - - final DisplayableItemNode originalNode = (DisplayableItemNode) this.getOriginal(); - actions.addAll(originalNode.accept(getActionsDIV)); - - //actions.add(new IndexContentFilesAction(nodeContent, "Index")); - - return actions.toArray(new Action[actions.size()]); - } - - /** - * Double click action for the nodes that we want to pass to the directory - * table and the output view. - * - * @return action - */ - @Override - public Action getPreferredAction() { - // double click action(s) for volume node or directory node - - final DisplayableItemNode originalNode; - originalNode = (DisplayableItemNode) this.getOriginal(); - - return originalNode.accept(getPreferredActionsDIV); - } - - @Override - public Node.PropertySet[] getPropertySets() { - Node.PropertySet[] propertySets = super.getPropertySets(); - - for (int i = 0; i < propertySets.length; i++) { - Node.PropertySet ps = propertySets[i]; - - if (ps.getName().equals(Sheet.PROPERTIES)) { - Sheet.Set newPs = new Sheet.Set(); - newPs.setName(ps.getName()); - newPs.setDisplayName(ps.getDisplayName()); - newPs.setShortDescription(ps.getShortDescription()); - - newPs.put(ps.getProperties()); - if (newPs.remove(AbstractFsContentNode.HIDE_PARENT) != null) { - newPs.remove(AbstractFilePropertyType.LOCATION.toString()); - } - propertySets[i] = newPs; - } - } - - return propertySets; - } - - /** - * Uses the default nodes actions per node, adds some custom ones and - * returns them per visited node type - */ - private static class GetPopupActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default> { - - @Override - public List visit(BlackboardArtifactNode ban) { - //set up actions for artifact node based on its Content object - //TODO all actions need to be consolidated in single place! - //they should be set in individual Node subclass and using a utility to get Actions per Content sub-type - - List actions = new ArrayList(); - - //merge predefined specific node actions if bban subclasses have their own - for (Action a : ban.getActions(true)) { - actions.add(a); - } - BlackboardArtifact ba = ban.getLookup().lookup(BlackboardArtifact.class); - final int artifactTypeID = ba.getArtifactTypeID(); - - if (artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() - || artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { - actions.add(new ViewContextAction("View File in Directory", ban)); - } else { - Content c = findLinked(ban); - if (c != null) { - actions.add(new ViewContextAction("View File in Directory", c)); - } - actions.add(new ViewContextAction("View Source File in Directory", ban)); - } - File f = ban.getLookup().lookup(File.class); - LayoutFile lf = null; - AbstractFile locF = null; - Directory d = null; - VirtualDirectory vd = null; - if (f != null) { - final FileNode fn = new FileNode(f); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction("View in New Window", fn)); - actions.add(new ExternalViewerAction("Open in External Viewer", fn)); - actions.add(null); // creates a menu separator - actions.add(new ExtractAction("Extract File", new FileNode(f))); - actions.add(new HashSearchAction("Search for files with the same MD5 hash", fn)); - - //add file/result tag if itself is not a tag - if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() - && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { - actions.add(null); // creates a menu separator - actions.add(new TagAction(f)); - actions.add(new TagAction(ba)); - } - } - if ((d = ban.getLookup().lookup(Directory.class)) != null) { - DirectoryNode dn = new DirectoryNode(d); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction("View in New Window", dn)); - actions.add(new ExternalViewerAction("Open in External Viewer", dn)); - actions.add(null); // creates a menu separator - actions.add(new ExtractAction("Extract Directory", dn)); - - //add file/result tag if itself is not a tag - if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() - && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { - actions.add(null); // creates a menu separator - actions.add(new TagAction(d)); - actions.add(new TagAction(ba)); - } - } - if ((vd = ban.getLookup().lookup(VirtualDirectory.class)) != null) { - VirtualDirectoryNode dn = new VirtualDirectoryNode(vd); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction("View in New Window", dn)); - actions.add(new ExternalViewerAction("Open in External Viewer", dn)); - actions.add(null); // creates a menu separator - actions.add(new ExtractAction("Extract Directory", dn)); - - //add file/result tag if itself is not a tag - if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() - && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { - actions.add(null); // creates a menu separator - actions.add(new TagAction(d)); - actions.add(new TagAction(ba)); - } - } else if ((lf = ban.getLookup().lookup(LayoutFile.class)) != null) { - LayoutFileNode lfn = new LayoutFileNode(lf); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction("View in New Window", lfn)); - actions.add(new ExternalViewerAction("Open in External Viewer", lfn)); - actions.add(null); // creates a menu separator - actions.add(new ExtractAction("Extract File", lfn)); - - //add tag if itself is not a tag - if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() - && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { - actions.add(null); // creates a menu separator - actions.add(new TagAction(lf)); - actions.add(new TagAction(ba)); - } - } else if ((locF = ban.getLookup().lookup(LocalFile.class)) != null - || (locF = ban.getLookup().lookup(DerivedFile.class)) != null) { - final LocalFileNode locfn = new LocalFileNode(locF); - actions.add(null); // creates a menu separator - actions.add(new NewWindowViewAction("View in New Window", locfn)); - actions.add(new ExternalViewerAction("Open in External Viewer", locfn)); - actions.add(null); // creates a menu separator - actions.add(new ExtractAction("Extract File", locfn)); - - //add tag if itself is not a tag - if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() - && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { - actions.add(null); // creates a menu separator - actions.add(new TagAction(lf)); - actions.add(new TagAction(ba)); - } - } - - return actions; - } - - @Override - protected List defaultVisit(DisplayableItemNode ditem) { - //preserve the default node's actions - List actions = new ArrayList(); - - for (Action action : ditem.getActions(true)) { - actions.add(action); - } - - return actions; - } - - private Content findLinked(BlackboardArtifactNode ba) { - BlackboardArtifact art = ba.getLookup().lookup(BlackboardArtifact.class); - Content c = null; - try { - for (BlackboardAttribute attr : art.getAttributes()) { - if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { - switch (attr.getValueType()) { - case INTEGER: - int i = attr.getValueInt(); - if (i != -1) { - c = art.getSleuthkitCase().getContentById(i); - } - break; - case LONG: - long l = attr.getValueLong(); - if (l != -1) { - c = art.getSleuthkitCase().getContentById(l); - } - break; - } - } - } - } catch (TskException ex) { - Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Error getting linked file", ex); - } - return c; - } - } - - private class GetPreferredActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default { - - @Override - public AbstractAction visit(ImageNode in) { - return openChild(in); - } - - @Override - public AbstractAction visit(VolumeNode vn) { - return openChild(vn); - } - - @Override - public AbstractAction visit(ExtractedContentNode ecn) { - return openChild(ecn); - } - - @Override - public AbstractAction visit(KeywordHitsRootNode khrn) { - return openChild(khrn); - } - - @Override - public AbstractAction visit(HashsetHitsRootNode hhrn) { - return openChild(hhrn); - } - - @Override - public AbstractAction visit(HashsetHitsSetNode hhsn) { - return openChild(hhsn); - } - - @Override - public AbstractAction visit(EmailExtractedRootNode eern) { - return openChild(eern); - } - - @Override - public AbstractAction visit(EmailExtractedAccountNode eean) { - return openChild(eean); - } - - @Override - public AbstractAction visit(EmailExtractedFolderNode eefn) { - return openChild(eefn); - } - - @Override - public AbstractAction visit(RecentFilesNode rfn) { - return openChild(rfn); - } - - @Override - public AbstractAction visit(DeletedContentsNode dcn) { - return openChild(dcn); - } - - @Override - public AbstractAction visit(DeletedContentNode dcn) { - return openChild(dcn); - } - - @Override - public AbstractAction visit(FileSizeRootNode fsrn) { - return openChild(fsrn); - } - - @Override - public AbstractAction visit(FileSizeNode fsn) { - return openChild(fsn); - } - - @Override - public AbstractAction visit(BlackboardArtifactNode ban) { - return new ViewContextAction("View in Directory", ban); - } - - @Override - public AbstractAction visit(ArtifactTypeNode atn) { - return openChild(atn); - } - - @Override - public AbstractAction visit(TagNodeRoot tnr) { - return openChild(tnr); - } - - @Override - public AbstractAction visit(TagsNodeRoot tnr) { - return openChild(tnr); - } - - @Override - public AbstractAction visit(DirectoryNode dn) { - if (dn.getDisplayName().equals(DirectoryNode.DOTDOTDIR)) { - return openParent(dn); - } else if (!dn.getDisplayName().equals(DirectoryNode.DOTDIR)) { - return openChild(dn); - } else { - return null; - } - } - - @Override - public AbstractAction visit(VirtualDirectoryNode ldn) { - return openChild(ldn); - } - - @Override - public AbstractAction visit(FileNode fn) { - if (fn.hasContentChildren()) { - return openChild(fn); - } else { - return null; - } - } - - @Override - public AbstractAction visit(LocalFileNode dfn) { - if (dfn.hasContentChildren()) { - return openChild(dfn); - } else { - return null; - } - } - - @Override - public AbstractAction visit(FileSearchFilterNode fsfn) { - return openChild(fsfn); - } - - @Override - public AbstractAction visit(SearchFiltersNode sfn) { - return openChild(sfn); - } - - @Override - public AbstractAction visit(RecentFilesFilterNode rffn) { - return openChild(rffn); - } - - @Override - public AbstractAction visit(KeywordHitsListNode khsn) { - return openChild(khsn); - } - - @Override - public AbstractAction visit(KeywordHitsKeywordNode khmln) { - return openChild(khmln); - } - - @Override - protected AbstractAction defaultVisit(DisplayableItemNode c) { - return null; - } - - private AbstractAction openChild(AbstractNode node) { - final Node[] parentNode = sourceEm.getSelectedNodes(); - final Node parentContext = parentNode[0]; - final Node original = node; - - return new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - if (parentContext != null) { - final int childrenNodesCount = parentContext.getChildren().getNodesCount(); - for (int i = 0; i < childrenNodesCount; i++) { - Node selectedNode = parentContext.getChildren().getNodeAt(i); - if (selectedNode != null && selectedNode.getName().equals(original.getName())) { - try { - sourceEm.setExploredContextAndSelection(selectedNode, new Node[]{selectedNode}); - } catch (PropertyVetoException ex) { - // throw an error here - Logger logger = Logger.getLogger(DataResultFilterNode.class.getName()); - logger.log(Level.WARNING, "Error: can't open the selected directory.", ex); - } - } - } - } - } - }; - } - - private AbstractAction openParent(AbstractNode node) { - Node[] selectedNode = sourceEm.getSelectedNodes(); - Node selectedContext = selectedNode[0]; - final Node parentNode = selectedContext.getParentNode(); - - return new AbstractAction() { - @Override - public void actionPerformed(ActionEvent e) { - try { - sourceEm.setSelectedNodes(new Node[]{parentNode}); - } catch (PropertyVetoException ex) { - Logger logger = Logger.getLogger(DataResultFilterNode.class.getName()); - logger.log(Level.WARNING, "Error: can't open the parent directory.", ex); - } - } - }; - } - } +/* + * Autopsy Forensic Browser + * + * Copyright 2011 Basis Technology Corp. + * Contact: carrier sleuthkit 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.directorytree; + +import java.awt.event.ActionEvent; +import java.beans.PropertyVetoException; +import java.util.ArrayList; +import java.util.List; +import org.sleuthkit.autopsy.datamodel.VolumeNode; +import org.sleuthkit.autopsy.datamodel.DirectoryNode; +import java.util.logging.Level; +import org.sleuthkit.autopsy.coreutils.Logger; +import javax.swing.AbstractAction; +import javax.swing.Action; +import org.openide.explorer.ExplorerManager; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.FilterNode; +import org.openide.nodes.Node; +import org.openide.nodes.Sheet; +import org.sleuthkit.autopsy.datamodel.AbstractAbstractFileNode.AbstractFilePropertyType; +import org.sleuthkit.autopsy.datamodel.AbstractFsContentNode; +import org.sleuthkit.autopsy.datamodel.ArtifactTypeNode; +import org.sleuthkit.autopsy.datamodel.BlackboardArtifactNode; +import org.sleuthkit.autopsy.datamodel.LocalFileNode; +import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsChildren.DeletedContentNode; +import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode; +import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; +import org.sleuthkit.autopsy.datamodel.DisplayableItemNodeVisitor; +import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedAccountNode; +import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedFolderNode; +import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedRootNode; +import org.sleuthkit.autopsy.datamodel.ExtractedContentNode; +import org.sleuthkit.autopsy.datamodel.FileNode; +import org.sleuthkit.autopsy.datamodel.FileSearchFilterNode; +import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode; +import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode; +import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsRootNode; +import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsSetNode; +import org.sleuthkit.autopsy.datamodel.ImageNode; +import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsKeywordNode; +import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsListNode; +import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsRootNode; +import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; +import org.sleuthkit.autopsy.datamodel.LayoutFileNode; +import org.sleuthkit.autopsy.datamodel.RecentFilesFilterNode; +import org.sleuthkit.autopsy.datamodel.RecentFilesNode; +import org.sleuthkit.autopsy.datamodel.SearchFiltersNode; +import org.sleuthkit.autopsy.datamodel.Tags.TagNodeRoot; +import org.sleuthkit.autopsy.datamodel.Tags.TagsNodeRoot; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.DerivedFile; +import org.sleuthkit.datamodel.Directory; +import org.sleuthkit.datamodel.File; +import org.sleuthkit.datamodel.LayoutFile; +import org.sleuthkit.datamodel.LocalFile; +import org.sleuthkit.datamodel.TskException; +import org.sleuthkit.datamodel.VirtualDirectory; + +/** + * This class wraps nodes as they are passed to the DataResult viewers. It + * defines the actions that the node should have. + */ +public class DataResultFilterNode extends FilterNode { + + private ExplorerManager sourceEm; + private final DisplayableItemNodeVisitor> getActionsDIV; + private final DisplayableItemNodeVisitor getPreferredActionsDIV; + + /** + * the constructor + */ + public DataResultFilterNode(Node node, ExplorerManager em) { + super(node, new DataResultFilterChildren(node, em)); + this.sourceEm = em; + getActionsDIV = new GetPopupActionsDisplayableItemNodeVisitor(); + getPreferredActionsDIV = new GetPreferredActionsDisplayableItemNodeVisitor(); + } + + /** + * Right click action for the nodes that we want to pass to the directory + * table and the output view. + * + * @param popup + * @return actions + */ + @Override + public Action[] getActions(boolean popup) { + + List actions = new ArrayList<>(); + + final DisplayableItemNode originalNode = (DisplayableItemNode) this.getOriginal(); + actions.addAll(originalNode.accept(getActionsDIV)); + + //actions.add(new IndexContentFilesAction(nodeContent, "Index")); + + return actions.toArray(new Action[actions.size()]); + } + + /** + * Double click action for the nodes that we want to pass to the directory + * table and the output view. + * + * @return action + */ + @Override + public Action getPreferredAction() { + // double click action(s) for volume node or directory node + + final DisplayableItemNode originalNode; + originalNode = (DisplayableItemNode) this.getOriginal(); + + return originalNode.accept(getPreferredActionsDIV); + } + + @Override + public Node.PropertySet[] getPropertySets() { + Node.PropertySet[] propertySets = super.getPropertySets(); + + for (int i = 0; i < propertySets.length; i++) { + Node.PropertySet ps = propertySets[i]; + + if (ps.getName().equals(Sheet.PROPERTIES)) { + Sheet.Set newPs = new Sheet.Set(); + newPs.setName(ps.getName()); + newPs.setDisplayName(ps.getDisplayName()); + newPs.setShortDescription(ps.getShortDescription()); + + newPs.put(ps.getProperties()); + if (newPs.remove(AbstractFsContentNode.HIDE_PARENT) != null) { + newPs.remove(AbstractFilePropertyType.LOCATION.toString()); + } + propertySets[i] = newPs; + } + } + + return propertySets; + } + + /** + * Uses the default nodes actions per node, adds some custom ones and + * returns them per visited node type + */ + private static class GetPopupActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default> { + + @Override + public List visit(BlackboardArtifactNode ban) { + //set up actions for artifact node based on its Content object + //TODO all actions need to be consolidated in single place! + //they should be set in individual Node subclass and using a utility to get Actions per Content sub-type + + List actions = new ArrayList<>(); + + //merge predefined specific node actions if bban subclasses have their own + for (Action a : ban.getActions(true)) { + actions.add(a); + } + BlackboardArtifact ba = ban.getLookup().lookup(BlackboardArtifact.class); + final int artifactTypeID = ba.getArtifactTypeID(); + + if (artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() + || artifactTypeID == BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { + actions.add(new ViewContextAction("View File in Directory", ban)); + } else { + Content c = findLinked(ban); + if (c != null) { + actions.add(new ViewContextAction("View File in Directory", c)); + } + actions.add(new ViewContextAction("View Source File in Directory", ban)); + } + File f = ban.getLookup().lookup(File.class); + LayoutFile lf = null; + AbstractFile locF = null; + Directory d = null; + VirtualDirectory vd = null; + if (f != null) { + final FileNode fn = new FileNode(f); + actions.add(null); // creates a menu separator + actions.add(new NewWindowViewAction("View in New Window", fn)); + actions.add(new ExternalViewerAction("Open in External Viewer", fn)); + actions.add(null); // creates a menu separator + actions.add(ExtractAction.getInstance()); + actions.add(new HashSearchAction("Search for files with the same MD5 hash", fn)); + + //add file/result tag if itself is not a tag + if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() + && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { + actions.add(null); // creates a menu separator + actions.add(TagAbstractFileAction.getInstance()); + actions.add(TagBlackboardArtifactAction.getInstance()); + } + } + if ((d = ban.getLookup().lookup(Directory.class)) != null) { + DirectoryNode dn = new DirectoryNode(d); + actions.add(null); // creates a menu separator + actions.add(new NewWindowViewAction("View in New Window", dn)); + actions.add(new ExternalViewerAction("Open in External Viewer", dn)); + actions.add(null); // creates a menu separator + actions.add(ExtractAction.getInstance()); + + //add file/result tag if itself is not a tag + if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() + && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { + actions.add(null); // creates a menu separator + actions.add(TagAbstractFileAction.getInstance()); + actions.add(TagBlackboardArtifactAction.getInstance()); + } + } + if ((vd = ban.getLookup().lookup(VirtualDirectory.class)) != null) { + VirtualDirectoryNode dn = new VirtualDirectoryNode(vd); + actions.add(null); // creates a menu separator + actions.add(new NewWindowViewAction("View in New Window", dn)); + actions.add(new ExternalViewerAction("Open in External Viewer", dn)); + actions.add(null); // creates a menu separator + actions.add(ExtractAction.getInstance()); + + //add file/result tag if itself is not a tag + if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() + && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { + actions.add(null); // creates a menu separator + actions.add(TagAbstractFileAction.getInstance()); + actions.add(TagBlackboardArtifactAction.getInstance()); + } + } else if ((lf = ban.getLookup().lookup(LayoutFile.class)) != null) { + LayoutFileNode lfn = new LayoutFileNode(lf); + actions.add(null); // creates a menu separator + actions.add(new NewWindowViewAction("View in New Window", lfn)); + actions.add(new ExternalViewerAction("Open in External Viewer", lfn)); + actions.add(null); // creates a menu separator + actions.add(ExtractAction.getInstance()); + + //add tag if itself is not a tag + if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() + && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { + actions.add(null); // creates a menu separator + actions.add(TagAbstractFileAction.getInstance()); + actions.add(TagBlackboardArtifactAction.getInstance()); + } + } else if ((locF = ban.getLookup().lookup(LocalFile.class)) != null + || (locF = ban.getLookup().lookup(DerivedFile.class)) != null) { + final LocalFileNode locfn = new LocalFileNode(locF); + actions.add(null); // creates a menu separator + actions.add(new NewWindowViewAction("View in New Window", locfn)); + actions.add(new ExternalViewerAction("Open in External Viewer", locfn)); + actions.add(null); // creates a menu separator + actions.add(ExtractAction.getInstance()); + + //add tag if itself is not a tag + if (artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() + && artifactTypeID != BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()) { + actions.add(null); // creates a menu separator + actions.add(TagAbstractFileAction.getInstance()); + actions.add(TagBlackboardArtifactAction.getInstance()); + } + } + + return actions; + } + + @Override + protected List defaultVisit(DisplayableItemNode ditem) { + //preserve the default node's actions + List actions = new ArrayList<>(); + + for (Action action : ditem.getActions(true)) { + actions.add(action); + } + + return actions; + } + + private Content findLinked(BlackboardArtifactNode ba) { + BlackboardArtifact art = ba.getLookup().lookup(BlackboardArtifact.class); + Content c = null; + try { + for (BlackboardAttribute attr : art.getAttributes()) { + if (attr.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID.getTypeID()) { + switch (attr.getValueType()) { + case INTEGER: + int i = attr.getValueInt(); + if (i != -1) { + c = art.getSleuthkitCase().getContentById(i); + } + break; + case LONG: + long l = attr.getValueLong(); + if (l != -1) { + c = art.getSleuthkitCase().getContentById(l); + } + break; + } + } + } + } catch (TskException ex) { + Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Error getting linked file", ex); + } + return c; + } + } + + private class GetPreferredActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default { + + @Override + public AbstractAction visit(ImageNode in) { + return openChild(in); + } + + @Override + public AbstractAction visit(VolumeNode vn) { + return openChild(vn); + } + + @Override + public AbstractAction visit(ExtractedContentNode ecn) { + return openChild(ecn); + } + + @Override + public AbstractAction visit(KeywordHitsRootNode khrn) { + return openChild(khrn); + } + + @Override + public AbstractAction visit(HashsetHitsRootNode hhrn) { + return openChild(hhrn); + } + + @Override + public AbstractAction visit(HashsetHitsSetNode hhsn) { + return openChild(hhsn); + } + + @Override + public AbstractAction visit(EmailExtractedRootNode eern) { + return openChild(eern); + } + + @Override + public AbstractAction visit(EmailExtractedAccountNode eean) { + return openChild(eean); + } + + @Override + public AbstractAction visit(EmailExtractedFolderNode eefn) { + return openChild(eefn); + } + + @Override + public AbstractAction visit(RecentFilesNode rfn) { + return openChild(rfn); + } + + @Override + public AbstractAction visit(DeletedContentsNode dcn) { + return openChild(dcn); + } + + @Override + public AbstractAction visit(DeletedContentNode dcn) { + return openChild(dcn); + } + + @Override + public AbstractAction visit(FileSizeRootNode fsrn) { + return openChild(fsrn); + } + + @Override + public AbstractAction visit(FileSizeNode fsn) { + return openChild(fsn); + } + + @Override + public AbstractAction visit(BlackboardArtifactNode ban) { + return new ViewContextAction("View in Directory", ban); + } + + @Override + public AbstractAction visit(ArtifactTypeNode atn) { + return openChild(atn); + } + + @Override + public AbstractAction visit(TagNodeRoot tnr) { + return openChild(tnr); + } + + @Override + public AbstractAction visit(TagsNodeRoot tnr) { + return openChild(tnr); + } + + @Override + public AbstractAction visit(DirectoryNode dn) { + if (dn.getDisplayName().equals(DirectoryNode.DOTDOTDIR)) { + return openParent(dn); + } else if (!dn.getDisplayName().equals(DirectoryNode.DOTDIR)) { + return openChild(dn); + } else { + return null; + } + } + + @Override + public AbstractAction visit(VirtualDirectoryNode ldn) { + return openChild(ldn); + } + + @Override + public AbstractAction visit(FileNode fn) { + if (fn.hasContentChildren()) { + return openChild(fn); + } else { + return null; + } + } + + @Override + public AbstractAction visit(LocalFileNode dfn) { + if (dfn.hasContentChildren()) { + return openChild(dfn); + } else { + return null; + } + } + + @Override + public AbstractAction visit(FileSearchFilterNode fsfn) { + return openChild(fsfn); + } + + @Override + public AbstractAction visit(SearchFiltersNode sfn) { + return openChild(sfn); + } + + @Override + public AbstractAction visit(RecentFilesFilterNode rffn) { + return openChild(rffn); + } + + @Override + public AbstractAction visit(KeywordHitsListNode khsn) { + return openChild(khsn); + } + + @Override + public AbstractAction visit(KeywordHitsKeywordNode khmln) { + return openChild(khmln); + } + + @Override + protected AbstractAction defaultVisit(DisplayableItemNode c) { + return null; + } + + private AbstractAction openChild(AbstractNode node) { + final Node[] parentNode = sourceEm.getSelectedNodes(); + final Node parentContext = parentNode[0]; + final Node original = node; + + return new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + if (parentContext != null) { + final int childrenNodesCount = parentContext.getChildren().getNodesCount(); + for (int i = 0; i < childrenNodesCount; i++) { + Node selectedNode = parentContext.getChildren().getNodeAt(i); + if (selectedNode != null && selectedNode.getName().equals(original.getName())) { + try { + sourceEm.setExploredContextAndSelection(selectedNode, new Node[]{selectedNode}); + } catch (PropertyVetoException ex) { + // throw an error here + Logger logger = Logger.getLogger(DataResultFilterNode.class.getName()); + logger.log(Level.WARNING, "Error: can't open the selected directory.", ex); + } + } + } + } + } + }; + } + + private AbstractAction openParent(AbstractNode node) { + Node[] selectedNode = sourceEm.getSelectedNodes(); + Node selectedContext = selectedNode[0]; + final Node parentNode = selectedContext.getParentNode(); + + return new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + try { + sourceEm.setSelectedNodes(new Node[]{parentNode}); + } catch (PropertyVetoException ex) { + Logger logger = Logger.getLogger(DataResultFilterNode.class.getName()); + logger.log(Level.WARNING, "Error: can't open the parent directory.", ex); + } + } + }; + } + } } \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterNode.java old mode 100644 new mode 100755 index 018679ae2c..d71ea25216 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeFilterNode.java @@ -1,160 +1,159 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011 Basis Technology Corp. - * Contact: carrier sleuthkit 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.directorytree; - -import java.awt.event.ActionEvent; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.logging.Level; -import javax.swing.AbstractAction; -import javax.swing.Action; -import org.openide.nodes.FilterNode; -import org.openide.nodes.Node; -import org.openide.util.lookup.Lookups; -import org.openide.util.lookup.ProxyLookup; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.datamodel.AbstractContentNode; -import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; -import org.sleuthkit.autopsy.ingest.IngestDialog; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.Directory; -import org.sleuthkit.datamodel.Image; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * This class sets the actions for the nodes in the directory tree and creates - * the children filter so that files and such are hidden from the tree. - * - */ -class DirectoryTreeFilterNode extends FilterNode { - - private static final Action collapseAll = new CollapseAction("Collapse All"); - private static final Logger logger = Logger.getLogger(DirectoryTreeFilterNode.class.getName()); - - /** - * the constructor - */ - DirectoryTreeFilterNode(Node arg, boolean createChildren) { - super(arg, DirectoryTreeFilterChildren.createInstance(arg, createChildren), - new ProxyLookup(Lookups.singleton(new OriginalNode(arg)), - arg.getLookup())); - } - - @Override - public String getDisplayName() { - final Node orig = getOriginal(); - - String name = orig.getDisplayName(); - - //do not show children counts for non content nodes - if (orig instanceof AbstractContentNode) { - //show only for file content nodes - AbstractFile file = getLookup().lookup(AbstractFile.class); - if (file != null) { - try { - final int numChildren = file.getChildrenCount(); - name = name + " (" + numChildren + ")"; - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting children count to display for file: " + file, ex); - } - - } - } - - return name; - } - - /** - * Right click action for the nodes in the directory tree. - * - * @param popup - * @return - */ - @Override - public Action[] getActions(boolean popup) { - List actions = new ArrayList(); - - final Content content = this.getLookup().lookup(Content.class); - if (content != null) { - actions.addAll(DirectoryTreeFilterNode.getDetailActions(content)); - - //extract dir action - Directory dir = this.getLookup().lookup(Directory.class); - if (dir != null) { - actions.add(new ExtractAction("Extract Directory", - getOriginal())); - } - - // file search action - final Image img = this.getLookup().lookup(Image.class); - if (img != null) { - actions.add(new FileSearchAction("Open File Search by Attributes")); - } - - //ingest action - actions.add(new AbstractAction("Run Ingest Modules") { - @Override - public void actionPerformed(ActionEvent e) { - final IngestDialog ingestDialog = new IngestDialog(); - ingestDialog.setContent(Collections.singletonList(content)); - ingestDialog.display(); - } - }); - } - - //check if delete actions should be added - final Node orig = getOriginal(); - //TODO add a mechanism to determine if DisplayableItemNode - if (orig instanceof DisplayableItemNode) { - actions.addAll(getDeleteActions((DisplayableItemNode) orig)); - } - - actions.add(collapseAll); - return actions.toArray(new Action[actions.size()]); - } - - private static List getDeleteActions(DisplayableItemNode original) { - List actions = new ArrayList(); - //actions.addAll(original.accept(getDeleteActionVisitor)); - return actions; - } - - private static List getDetailActions(Content c) { - List actions = new ArrayList(); - - actions.addAll(ExplorerNodeActionVisitor.getActions(c)); - - return actions; - } -} - -class OriginalNode { - - private Node original; - - OriginalNode(Node original) { - this.original = original; - } - - Node getNode() { - return original; - } +/* + * Autopsy Forensic Browser + * + * Copyright 2011 Basis Technology Corp. + * Contact: carrier sleuthkit 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.directorytree; + +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import javax.swing.AbstractAction; +import javax.swing.Action; +import org.openide.nodes.FilterNode; +import org.openide.nodes.Node; +import org.openide.util.lookup.Lookups; +import org.openide.util.lookup.ProxyLookup; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.AbstractContentNode; +import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; +import org.sleuthkit.autopsy.ingest.IngestDialog; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.Directory; +import org.sleuthkit.datamodel.Image; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * This class sets the actions for the nodes in the directory tree and creates + * the children filter so that files and such are hidden from the tree. + * + */ +class DirectoryTreeFilterNode extends FilterNode { + + private static final Action collapseAll = new CollapseAction("Collapse All"); + private static final Logger logger = Logger.getLogger(DirectoryTreeFilterNode.class.getName()); + + /** + * the constructor + */ + DirectoryTreeFilterNode(Node arg, boolean createChildren) { + super(arg, DirectoryTreeFilterChildren.createInstance(arg, createChildren), + new ProxyLookup(Lookups.singleton(new OriginalNode(arg)), + arg.getLookup())); + } + + @Override + public String getDisplayName() { + final Node orig = getOriginal(); + + String name = orig.getDisplayName(); + + //do not show children counts for non content nodes + if (orig instanceof AbstractContentNode) { + //show only for file content nodes + AbstractFile file = getLookup().lookup(AbstractFile.class); + if (file != null) { + try { + final int numChildren = file.getChildrenCount(); + name = name + " (" + numChildren + ")"; + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting children count to display for file: " + file, ex); + } + + } + } + + return name; + } + + /** + * Right click action for the nodes in the directory tree. + * + * @param popup + * @return + */ + @Override + public Action[] getActions(boolean popup) { + List actions = new ArrayList(); + + final Content content = this.getLookup().lookup(Content.class); + if (content != null) { + actions.addAll(DirectoryTreeFilterNode.getDetailActions(content)); + + //extract dir action + Directory dir = this.getLookup().lookup(Directory.class); + if (dir != null) { + actions.add(ExtractAction.getInstance()); + } + + // file search action + final Image img = this.getLookup().lookup(Image.class); + if (img != null) { + actions.add(new FileSearchAction("Open File Search by Attributes")); + } + + //ingest action + actions.add(new AbstractAction("Run Ingest Modules") { + @Override + public void actionPerformed(ActionEvent e) { + final IngestDialog ingestDialog = new IngestDialog(); + ingestDialog.setContent(Collections.singletonList(content)); + ingestDialog.display(); + } + }); + } + + //check if delete actions should be added + final Node orig = getOriginal(); + //TODO add a mechanism to determine if DisplayableItemNode + if (orig instanceof DisplayableItemNode) { + actions.addAll(getDeleteActions((DisplayableItemNode) orig)); + } + + actions.add(collapseAll); + return actions.toArray(new Action[actions.size()]); + } + + private static List getDeleteActions(DisplayableItemNode original) { + List actions = new ArrayList(); + //actions.addAll(original.accept(getDeleteActionVisitor)); + return actions; + } + + private static List getDetailActions(Content c) { + List actions = new ArrayList(); + + actions.addAll(ExplorerNodeActionVisitor.getActions(c)); + + return actions; + } +} + +class OriginalNode { + + private Node original; + + OriginalNode(Node original) { + this.original = original; + } + + Node getNode() { + return original; + } } \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExplorerNodeActionVisitor.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExplorerNodeActionVisitor.java old mode 100644 new mode 100755 index 28479e83c3..90c1eded2e --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExplorerNodeActionVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExplorerNodeActionVisitor.java @@ -1,383 +1,383 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011 Basis Technology Corp. - * Contact: carrier sleuthkit 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.directorytree; - -import java.awt.Toolkit; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.logging.Level; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.table.DefaultTableModel; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.ContentVisitor; -import org.sleuthkit.datamodel.DerivedFile; -import org.sleuthkit.datamodel.Directory; -import org.sleuthkit.datamodel.FileSystem; -import org.sleuthkit.datamodel.Image; -import org.sleuthkit.datamodel.LocalFile; -import org.sleuthkit.datamodel.VirtualDirectory; -import org.sleuthkit.datamodel.Volume; - -public class ExplorerNodeActionVisitor extends ContentVisitor.Default> { - - private static ExplorerNodeActionVisitor instance = new ExplorerNodeActionVisitor(); - - public static List getActions(Content c) { - List actions = new ArrayList(); - - actions.addAll(c.accept(instance)); - //TODO: fix this - /* - while (c.isOnto()) { - try { - List children = c.getChildren(); - if (!children.isEmpty()) { - c = c.getChildren().get(0); - } else { - return actions; - } - } catch (TskException ex) { - Log.get(ExplorerNodeActionVisitor.class).log(Level.WARNING, "Error getting show detail actions.", ex); - return actions; - } - actions.addAll(c.accept(instance)); - }*/ - return actions; - } - - ExplorerNodeActionVisitor() { - } - - @Override - public List visit(final Image img) { - List lst = new ArrayList(); - lst.add(new ImageDetails("Image Details", img)); - //TODO lst.add(new ExtractAction("Extract Image", img)); - lst.add(new ExtractUnallocAction("Extract Unallocated Space to Single Files", img)); - return lst; - } - - @Override - public List visit(final FileSystem fs) { - return Collections.singletonList(new FileSystemDetails("File System Details", fs)); - } - - @Override - public List visit(final Volume vol) { - List lst = new ArrayList(); - lst.add(new VolumeDetails("Volume Details", vol)); - lst.add(new ExtractUnallocAction("Extract Unallocated Space to Single File", vol)); - return lst; - } - - @Override - public List visit(final Directory d) { - List actions = new ArrayList(); - actions.add(new TagAction(d)); - return actions; - } - - @Override - public List visit(final VirtualDirectory d) { - List actions = new ArrayList(); - actions.add(new TagAction(d)); - actions.add(new ExtractAction("Extract Directory", d)); - return actions; - } - - @Override - public List visit(final DerivedFile d) { - List actions = new ArrayList(); - actions.add(new ExtractAction("Extract File", d)); - actions.add(new TagAction(d)); - return actions; - } - - @Override - public List visit(final LocalFile d) { - List actions = new ArrayList(); - actions.add(new ExtractAction("Extract File", d)); - actions.add(new TagAction(d)); - return actions; - } - - @Override - public List visit(final org.sleuthkit.datamodel.File d) { - List actions = new ArrayList(); - actions.add(new ExtractAction("Extract File", d)); - actions.add(new TagAction(d)); - return actions; - } - - @Override - protected List defaultVisit(Content di) { - return Collections.emptyList(); - } - - //Below here are classes regarding node-specific actions - /** - * VolumeDetails class - */ - private class VolumeDetails extends AbstractAction { - - private final String title; - private final Volume vol; - - VolumeDetails(String title, Volume vol) { - super(title); - this.title = title; - this.vol = vol; - } - - @Override - public void actionPerformed(ActionEvent e) { - Logger.noteAction(ExplorerNodeActionVisitor.class); - - final JFrame frame = new JFrame(title); - final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal - - - Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); - - // set the popUp window / JFrame - popUpWindow.setSize(800, 400); - - int w = popUpWindow.getSize().width; - int h = popUpWindow.getSize().height; - - // set the location of the popUp Window on the center of the screen - popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2); - - VolumeDetailsPanel volumeDetailPanel = new VolumeDetailsPanel(); - Boolean counter = false; - - volumeDetailPanel.setVolumeIDValue(Long.toString(vol.getAddr())); - volumeDetailPanel.setStartValue(Long.toString(vol.getStart())); - volumeDetailPanel.setLengthValue(Long.toString(vol.getLength())); - volumeDetailPanel.setDescValue(vol.getDescription()); - volumeDetailPanel.setFlagsValue(vol.getFlagsAsString()); - counter = true; - - if (counter) { - // add the volume detail panel to the popUp window - popUpWindow.add(volumeDetailPanel); - } else { - // error handler if no volume matches - JLabel error = new JLabel("Error: No Volume Matches."); - error.setFont(new Font("Arial", Font.BOLD, 24)); - popUpWindow.add(error); - } - - // add the command to close the window to the button on the Volume Detail Panel - volumeDetailPanel.setOKButtonActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - popUpWindow.dispose(); - } - }); - popUpWindow.pack(); - popUpWindow.setResizable(false); - popUpWindow.setVisible(true); - - } - } - - /** - * ImageDetails panel class - */ - private class ImageDetails extends AbstractAction { - - final String title; - final Image img; - - ImageDetails(String title, Image img) { - super(title); - this.title = title; - this.img = img; - } - - @Override - public void actionPerformed(ActionEvent e) { - Logger.noteAction(ExplorerNodeActionVisitor.class); - - final JFrame frame = new JFrame(title); - final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal - // if we select the Image Details menu - - Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); - - // set the popUp window / JFrame - popUpWindow.setSize(750, 400); - - int w = popUpWindow.getSize().width; - int h = popUpWindow.getSize().height; - - // set the location of the popUp Window on the center of the screen - popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2); - - ImageDetailsPanel imgDetailPanel = new ImageDetailsPanel(); - Boolean counter = false; - - imgDetailPanel.setImgNameValue(img.getName()); - imgDetailPanel.setImgTypeValue(Image.imageTypeToString(img.getType())); - imgDetailPanel.setImgSectorSizeValue(Long.toString(img.getSsize())); - counter = true; - - if (counter) { - // add the volume detail panel to the popUp window - popUpWindow.add(imgDetailPanel); - } else { - // error handler if no volume matches - JLabel error = new JLabel("Error: No Volume Matches."); - error.setFont(new Font("Arial", Font.BOLD, 24)); - popUpWindow.add(error); - } - - // add the command to close the window to the button on the Volume Detail Panel - imgDetailPanel.setOKButtonActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - popUpWindow.dispose(); - } - }); - - - popUpWindow.pack(); - popUpWindow.setResizable(false); - popUpWindow.setVisible(true); - } - } - - /** - * FileSystemDetails class - */ - private class FileSystemDetails extends AbstractAction { - - private final FileSystem fs; - private final String title; - - FileSystemDetails(String title, FileSystem fs) { - super(title); - this.title = title; - this.fs = fs; - } - - @Override - public void actionPerformed(ActionEvent e) { - Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); - - Logger.noteAction(ExplorerNodeActionVisitor.class); - - final JFrame frame = new JFrame(title); - final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal - - // set the popUp window / JFrame - - popUpWindow.setSize(1000, 500); - - int w = popUpWindow.getSize().width; - int h = popUpWindow.getSize().height; - - // set the location of the popUp Window on the center of the screen - popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2); - - String[] columnNames = new String[]{ - "fs_id", - "img_offset", - "par_id", - "fs_type", - "block_size", - "block_count", - "root_inum", - "first_inum", - "last_inum" - }; - - Object[][] rowValues = new Object[1][9]; - - Content parent = null; - try { - parent = fs.getParent(); - } catch (Exception ex) { - throw new RuntimeException("Problem getting parent from " + FileSystem.class.getName() + ": " + fs, ex); - } - long id = -1; - if (parent != null) { - id = parent.getId(); - } - - Arrays.fill(rowValues, 0, 1, new Object[]{ - fs.getId(), - fs.getImageOffset(), - id, - fs.getFsType(), - fs.getBlock_size(), - fs.getBlock_count(), - fs.getRoot_inum(), - fs.getFirst_inum(), - fs.getLastInum() - }); - - - JTable table = new JTable(new DefaultTableModel(rowValues, columnNames)); - - FileSystemDetailsPanel fsdPanel = new FileSystemDetailsPanel(); - - // add the command to close the window to the button on the Volume Detail Panel - fsdPanel.setOKButtonActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - popUpWindow.dispose(); - } - }); - - try { - fsdPanel.setFileSystemTypeValue(table.getValueAt(0, 3).toString()); - fsdPanel.setImageOffsetValue(table.getValueAt(0, 1).toString()); - fsdPanel.setVolumeIDValue(table.getValueAt(0, 2).toString()); //TODO: fix this to parent id, not vol id - fsdPanel.setBlockSizeValue(table.getValueAt(0, 4).toString()); - fsdPanel.setBlockCountValue(table.getValueAt(0, 5).toString()); - fsdPanel.setRootInumValue(table.getValueAt(0, 6).toString()); - fsdPanel.setFirstInumValue(table.getValueAt(0, 7).toString()); - fsdPanel.setLastInumValue(table.getValueAt(0, 8).toString()); - - popUpWindow.add(fsdPanel); - } catch (Exception ex) { - Logger.getLogger(ExplorerNodeActionVisitor.class.getName()).log(Level.WARNING, "Error setting up File System Details panel.", ex); - } - - popUpWindow.pack(); - popUpWindow.setResizable(false); - popUpWindow.setVisible(true); - - } - } +/* + * Autopsy Forensic Browser + * + * Copyright 2011 Basis Technology Corp. + * Contact: carrier sleuthkit 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.directorytree; + +import java.awt.Toolkit; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.table.DefaultTableModel; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.ContentVisitor; +import org.sleuthkit.datamodel.DerivedFile; +import org.sleuthkit.datamodel.Directory; +import org.sleuthkit.datamodel.FileSystem; +import org.sleuthkit.datamodel.Image; +import org.sleuthkit.datamodel.LocalFile; +import org.sleuthkit.datamodel.VirtualDirectory; +import org.sleuthkit.datamodel.Volume; + +public class ExplorerNodeActionVisitor extends ContentVisitor.Default> { + + private static ExplorerNodeActionVisitor instance = new ExplorerNodeActionVisitor(); + + public static List getActions(Content c) { + List actions = new ArrayList(); + + actions.addAll(c.accept(instance)); + //TODO: fix this + /* + while (c.isOnto()) { + try { + List children = c.getChildren(); + if (!children.isEmpty()) { + c = c.getChildren().get(0); + } else { + return actions; + } + } catch (TskException ex) { + Log.get(ExplorerNodeActionVisitor.class).log(Level.WARNING, "Error getting show detail actions.", ex); + return actions; + } + actions.addAll(c.accept(instance)); + }*/ + return actions; + } + + ExplorerNodeActionVisitor() { + } + + @Override + public List visit(final Image img) { + List lst = new ArrayList(); + lst.add(new ImageDetails("Image Details", img)); + //TODO lst.add(new ExtractAction("Extract Image", img)); + lst.add(new ExtractUnallocAction("Extract Unallocated Space to Single Files", img)); + return lst; + } + + @Override + public List visit(final FileSystem fs) { + return Collections.singletonList(new FileSystemDetails("File System Details", fs)); + } + + @Override + public List visit(final Volume vol) { + List lst = new ArrayList(); + lst.add(new VolumeDetails("Volume Details", vol)); + lst.add(new ExtractUnallocAction("Extract Unallocated Space to Single File", vol)); + return lst; + } + + @Override + public List visit(final Directory d) { + List actions = new ArrayList(); + actions.add(TagAbstractFileAction.getInstance()); + return actions; + } + + @Override + public List visit(final VirtualDirectory d) { + List actions = new ArrayList(); + actions.add(ExtractAction.getInstance()); + actions.add(TagAbstractFileAction.getInstance()); + return actions; + } + + @Override + public List visit(final DerivedFile d) { + List actions = new ArrayList(); + actions.add(ExtractAction.getInstance()); + actions.add(TagAbstractFileAction.getInstance()); + return actions; + } + + @Override + public List visit(final LocalFile d) { + List actions = new ArrayList(); + actions.add(ExtractAction.getInstance()); + actions.add(TagAbstractFileAction.getInstance()); + return actions; + } + + @Override + public List visit(final org.sleuthkit.datamodel.File d) { + List actions = new ArrayList(); + actions.add(ExtractAction.getInstance()); + actions.add(TagAbstractFileAction.getInstance()); + return actions; + } + + @Override + protected List defaultVisit(Content di) { + return Collections.emptyList(); + } + + //Below here are classes regarding node-specific actions + /** + * VolumeDetails class + */ + private class VolumeDetails extends AbstractAction { + + private final String title; + private final Volume vol; + + VolumeDetails(String title, Volume vol) { + super(title); + this.title = title; + this.vol = vol; + } + + @Override + public void actionPerformed(ActionEvent e) { + Logger.noteAction(ExplorerNodeActionVisitor.class); + + final JFrame frame = new JFrame(title); + final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal + + + Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); + + // set the popUp window / JFrame + popUpWindow.setSize(800, 400); + + int w = popUpWindow.getSize().width; + int h = popUpWindow.getSize().height; + + // set the location of the popUp Window on the center of the screen + popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2); + + VolumeDetailsPanel volumeDetailPanel = new VolumeDetailsPanel(); + Boolean counter = false; + + volumeDetailPanel.setVolumeIDValue(Long.toString(vol.getAddr())); + volumeDetailPanel.setStartValue(Long.toString(vol.getStart())); + volumeDetailPanel.setLengthValue(Long.toString(vol.getLength())); + volumeDetailPanel.setDescValue(vol.getDescription()); + volumeDetailPanel.setFlagsValue(vol.getFlagsAsString()); + counter = true; + + if (counter) { + // add the volume detail panel to the popUp window + popUpWindow.add(volumeDetailPanel); + } else { + // error handler if no volume matches + JLabel error = new JLabel("Error: No Volume Matches."); + error.setFont(new Font("Arial", Font.BOLD, 24)); + popUpWindow.add(error); + } + + // add the command to close the window to the button on the Volume Detail Panel + volumeDetailPanel.setOKButtonActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + popUpWindow.dispose(); + } + }); + popUpWindow.pack(); + popUpWindow.setResizable(false); + popUpWindow.setVisible(true); + + } + } + + /** + * ImageDetails panel class + */ + private class ImageDetails extends AbstractAction { + + final String title; + final Image img; + + ImageDetails(String title, Image img) { + super(title); + this.title = title; + this.img = img; + } + + @Override + public void actionPerformed(ActionEvent e) { + Logger.noteAction(ExplorerNodeActionVisitor.class); + + final JFrame frame = new JFrame(title); + final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal + // if we select the Image Details menu + + Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); + + // set the popUp window / JFrame + popUpWindow.setSize(750, 400); + + int w = popUpWindow.getSize().width; + int h = popUpWindow.getSize().height; + + // set the location of the popUp Window on the center of the screen + popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2); + + ImageDetailsPanel imgDetailPanel = new ImageDetailsPanel(); + Boolean counter = false; + + imgDetailPanel.setImgNameValue(img.getName()); + imgDetailPanel.setImgTypeValue(Image.imageTypeToString(img.getType())); + imgDetailPanel.setImgSectorSizeValue(Long.toString(img.getSsize())); + counter = true; + + if (counter) { + // add the volume detail panel to the popUp window + popUpWindow.add(imgDetailPanel); + } else { + // error handler if no volume matches + JLabel error = new JLabel("Error: No Volume Matches."); + error.setFont(new Font("Arial", Font.BOLD, 24)); + popUpWindow.add(error); + } + + // add the command to close the window to the button on the Volume Detail Panel + imgDetailPanel.setOKButtonActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + popUpWindow.dispose(); + } + }); + + + popUpWindow.pack(); + popUpWindow.setResizable(false); + popUpWindow.setVisible(true); + } + } + + /** + * FileSystemDetails class + */ + private class FileSystemDetails extends AbstractAction { + + private final FileSystem fs; + private final String title; + + FileSystemDetails(String title, FileSystem fs) { + super(title); + this.title = title; + this.fs = fs; + } + + @Override + public void actionPerformed(ActionEvent e) { + Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); + + Logger.noteAction(ExplorerNodeActionVisitor.class); + + final JFrame frame = new JFrame(title); + final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal + + // set the popUp window / JFrame + + popUpWindow.setSize(1000, 500); + + int w = popUpWindow.getSize().width; + int h = popUpWindow.getSize().height; + + // set the location of the popUp Window on the center of the screen + popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2); + + String[] columnNames = new String[]{ + "fs_id", + "img_offset", + "par_id", + "fs_type", + "block_size", + "block_count", + "root_inum", + "first_inum", + "last_inum" + }; + + Object[][] rowValues = new Object[1][9]; + + Content parent = null; + try { + parent = fs.getParent(); + } catch (Exception ex) { + throw new RuntimeException("Problem getting parent from " + FileSystem.class.getName() + ": " + fs, ex); + } + long id = -1; + if (parent != null) { + id = parent.getId(); + } + + Arrays.fill(rowValues, 0, 1, new Object[]{ + fs.getId(), + fs.getImageOffset(), + id, + fs.getFsType(), + fs.getBlock_size(), + fs.getBlock_count(), + fs.getRoot_inum(), + fs.getFirst_inum(), + fs.getLastInum() + }); + + + JTable table = new JTable(new DefaultTableModel(rowValues, columnNames)); + + FileSystemDetailsPanel fsdPanel = new FileSystemDetailsPanel(); + + // add the command to close the window to the button on the Volume Detail Panel + fsdPanel.setOKButtonActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + popUpWindow.dispose(); + } + }); + + try { + fsdPanel.setFileSystemTypeValue(table.getValueAt(0, 3).toString()); + fsdPanel.setImageOffsetValue(table.getValueAt(0, 1).toString()); + fsdPanel.setVolumeIDValue(table.getValueAt(0, 2).toString()); //TODO: fix this to parent id, not vol id + fsdPanel.setBlockSizeValue(table.getValueAt(0, 4).toString()); + fsdPanel.setBlockCountValue(table.getValueAt(0, 5).toString()); + fsdPanel.setRootInumValue(table.getValueAt(0, 6).toString()); + fsdPanel.setFirstInumValue(table.getValueAt(0, 7).toString()); + fsdPanel.setLastInumValue(table.getValueAt(0, 8).toString()); + + popUpWindow.add(fsdPanel); + } catch (Exception ex) { + Logger.getLogger(ExplorerNodeActionVisitor.class.getName()).log(Level.WARNING, "Error setting up File System Details panel.", ex); + } + + popUpWindow.pack(); + popUpWindow.setResizable(false); + popUpWindow.setVisible(true); + + } + } } \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java index 6b183644f1..1442cb57cd 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.directorytree; import java.awt.Component; import java.awt.event.ActionEvent; import java.io.File; +import java.util.Collection; import java.util.concurrent.CancellationException; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; @@ -30,83 +31,37 @@ import javax.swing.JOptionPane; import javax.swing.SwingWorker; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandleFactory; -import org.openide.nodes.Node; import org.openide.util.Cancellable; +import org.openide.util.Utilities; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor; import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.ContentVisitor; -import org.sleuthkit.datamodel.Directory; /** * Exports files and folders */ public final class ExtractAction extends AbstractAction { - - private static final InitializeContentVisitor initializeCV = new InitializeContentVisitor(); - private AbstractFile content; private Logger logger = Logger.getLogger(ExtractAction.class.getName()); - public ExtractAction(String title, Node contentNode) { - super(title); - Content tempContent = contentNode.getLookup().lookup(Content.class); + // This class is a singleton to support multi-selection of nodes, since + // org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every + // node in the array returns a reference to the same action object from Node.getActions(boolean). + private static ExtractAction instance; - this.content = tempContent.accept(initializeCV); - this.setEnabled(content != null); - } - - public ExtractAction(String title, Content content) { - super(title); + public static synchronized ExtractAction getInstance() { + if (null == instance) { + instance = new ExtractAction(); + } - this.content = content.accept(initializeCV); - this.setEnabled(this.content != null); + return instance; } - /** - * Returns the FsContent if it is supported, otherwise null - */ - private static class InitializeContentVisitor extends ContentVisitor.Default { - - @Override - public AbstractFile visit(org.sleuthkit.datamodel.File f) { - return f; - } - - @Override - public AbstractFile visit(org.sleuthkit.datamodel.LayoutFile lf) { - return lf; - } - - @Override - public AbstractFile visit(org.sleuthkit.datamodel.DerivedFile df) { - return df; - } - - @Override - public AbstractFile visit(org.sleuthkit.datamodel.LocalFile lf) { - return lf; - } - - @Override - public AbstractFile visit(org.sleuthkit.datamodel.VirtualDirectory vd) { - return vd; - } - - @Override - public AbstractFile visit(Directory dir) { - return ContentUtils.isDotDirectory(dir) ? null : dir; - } - - @Override - protected AbstractFile defaultVisit(Content cntnt) { - return null; - } + private ExtractAction() { + super("Extract"); } - + /** * Asks user to choose destination, then extracts content/directory to * destination (recursing on directories) @@ -114,10 +69,17 @@ public final class ExtractAction extends AbstractAction { */ @Override public void actionPerformed(ActionEvent e) { + Collection selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class); + for (AbstractFile file : selectedFiles) { + extractFile(e, file); + } + } + + private void extractFile(ActionEvent e, AbstractFile file) { // Get content and check that it's okay to overwrite existing content JFileChooser fc = new JFileChooser(); fc.setCurrentDirectory(new File(Case.getCurrentCase().getCaseDirectory())); - fc.setSelectedFile(new File(this.content.getName())); + fc.setSelectedFile(new File(file.getName())); int returnValue = fc.showSaveDialog((Component) e.getSource()); if (returnValue == JFileChooser.APPROVE_OPTION) { @@ -144,12 +106,12 @@ public final class ExtractAction extends AbstractAction { try { ExtractFileThread extract = new ExtractFileThread(); - extract.init(this.content, e, destination); + extract.init(file, e, destination); extract.execute(); } catch (Exception ex) { logger.log(Level.WARNING, "Unable to start background thread.", ex); } - } + } } private class ExtractFileThread extends SwingWorker { @@ -230,6 +192,5 @@ public final class ExtractAction extends AbstractAction { } } } - } - + } } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/TagAbstractFileAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/TagAbstractFileAction.java new file mode 100755 index 0000000000..657673ac74 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/directorytree/TagAbstractFileAction.java @@ -0,0 +1,70 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013 Basis Technology Corp. + * Contact: carrier sleuthkit 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.directorytree; + +import java.awt.event.ActionEvent; +import java.util.Collection; +import javax.swing.AbstractAction; +import javax.swing.JMenuItem; +import org.openide.util.Utilities; +import org.openide.util.actions.Presenter; +import org.sleuthkit.autopsy.datamodel.Tags; +import org.sleuthkit.datamodel.AbstractFile; + +public class TagAbstractFileAction extends AbstractAction implements Presenter.Popup { + // This class is a singleton to support multi-selection of nodes, since + // org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every + // node in the array returns a reference to the same action object from Node.getActions(boolean). + private static TagAbstractFileAction instance; + + public static synchronized TagAbstractFileAction getInstance() { + if (null == instance) { + instance = new TagAbstractFileAction(); + } + return instance; + } + + private TagAbstractFileAction() { + } + + @Override + public JMenuItem getPopupPresenter() { + return new TagAbstractFileMenu(); + } + + @Override + public void actionPerformed(ActionEvent e) { + // Do nothing - this action should never be performed. + // Submenu actions are invoked instead. + } + + private static class TagAbstractFileMenu extends TagMenu { + public TagAbstractFileMenu() { + super(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class).size() > 1 ? "Tag Files" : "Tag File"); + } + + @Override + protected void applyTag(String tagName, String comment) { + Collection selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class); + for (AbstractFile file : selectedFiles) { + Tags.createTag(file, tagName, comment); + } + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/TagAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/TagAction.java deleted file mode 100644 index 35c755c0e2..0000000000 --- a/Core/src/org/sleuthkit/autopsy/directorytree/TagAction.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2013 Basis Technology Corp. - * Contact: carrier sleuthkit 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.directorytree; - -import java.awt.event.ActionEvent; -import java.util.logging.Level; -import javax.swing.AbstractAction; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import org.openide.nodes.Node; -import org.openide.util.actions.Presenter; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.ContentVisitor; -import org.sleuthkit.datamodel.Directory; - -/** - * Action on a file or artifact that adds a tag and - * reloads the directory tree. Supports tagging of AbstractFiles and - * BlackboardArtifacts. - * - * TODO add use enters description and hierarchy (TSK_TAG_NAME with slashes) - */ -public class TagAction extends AbstractAction implements Presenter.Popup { - - private static final Logger logger = Logger.getLogger(TagAction.class.getName()); - private JMenu tagMenu; - private final InitializeBookmarkFileV initializer = new InitializeBookmarkFileV(); - - public TagAction(Node contentNode) { - AbstractFile file = contentNode.getLookup().lookup(AbstractFile.class); - if (file != null) { - tagMenu = new TagMenu(file); - return; - } - - BlackboardArtifact bba = contentNode.getLookup().lookup(BlackboardArtifact.class); - if (bba != null) { - tagMenu = new TagMenu(bba); - return; - } - - logger.log(Level.SEVERE, "Tried to create a " + TagAction.class.getName() - + " using a Node whose lookup did not contain an AbstractFile or a BlackboardArtifact."); - } - - public TagAction(AbstractFile file) { - tagMenu = new TagMenu(file); - } - - public TagAction(BlackboardArtifact bba) { - tagMenu = new TagMenu(bba); - } - - @Override - public JMenuItem getPopupPresenter() { - return tagMenu; - } - - /** - * Returns the FsContent if it is supported, otherwise null - */ - private static class InitializeBookmarkFileV extends ContentVisitor.Default { - - @Override - public AbstractFile visit(org.sleuthkit.datamodel.File f) { - return f; - } - - @Override - public AbstractFile visit(org.sleuthkit.datamodel.LayoutFile lf) { - return lf; - } - - @Override - public AbstractFile visit(org.sleuthkit.datamodel.DerivedFile lf) { - return lf; - } - - @Override - public AbstractFile visit(org.sleuthkit.datamodel.LocalFile lf) { - return lf; - } - - @Override - public AbstractFile visit(org.sleuthkit.datamodel.VirtualDirectory ld) { - return ld; - } - - @Override - public AbstractFile visit(Directory dir) { - return ContentUtils.isDotDirectory(dir) ? null : dir; - } - - @Override - protected AbstractFile defaultVisit(Content cntnt) { - return null; - } - } - - @Override - public void actionPerformed(ActionEvent e) { - // Do nothing - this action should never be performed - // Submenu actions are invoked instead - } -} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/TagAndCommentDialog.java b/Core/src/org/sleuthkit/autopsy/directorytree/TagAndCommentDialog.java index a36a78809b..6a66e55689 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/TagAndCommentDialog.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/TagAndCommentDialog.java @@ -30,28 +30,50 @@ import javax.swing.JFrame; import javax.swing.KeyStroke; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.datamodel.Tags; -import org.sleuthkit.autopsy.datamodel.Tags.Taggable; -import org.sleuthkit.datamodel.BlackboardArtifact; /** * Tag dialog for tagging files and results. User enters an optional comment. */ public class TagAndCommentDialog extends JDialog { - private static final String TAG_ICON_PATH = "org/sleuthkit/autopsy/images/tag-folder-blue-icon-16.png"; - private static final String BOOKMARK_ICON_PATH = "org/sleuthkit/autopsy/images/star-bookmark-icon-16.png"; - private static final String NO_TAG_MESSAGE = "No Tags"; - - private Taggable taggable; + private static final String NO_TAG_MESSAGE = "No Tags"; + private String tagName = ""; + private String comment = ""; + public static class CommentedTag { + private String name; + private String comment; + + CommentedTag(String name, String comment) { + this.name = name; + this.comment = comment; + } + + public String getName() { + return name; + } + + public String getComment() { + return comment; + } + } + + public static CommentedTag doDialog() { + TagAndCommentDialog dialog = new TagAndCommentDialog(); + if (!dialog.tagName.isEmpty()) { + return new CommentedTag(dialog.tagName, dialog.comment); + } + else { + return null; + } + } + /** * Creates new form TagDialog */ - public TagAndCommentDialog(Taggable taggable) { + private TagAndCommentDialog() { super((JFrame)WindowManager.getDefault().getMainWindow(), "Tag and Comment", true); - this.taggable = taggable; - initComponents(); // Close the dialog when Esc is pressed @@ -60,8 +82,8 @@ public class TagAndCommentDialog extends JDialog { inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName); ActionMap actionMap = getRootPane().getActionMap(); actionMap.put(cancelName, new AbstractAction() { + @Override public void actionPerformed(ActionEvent e) { - //doClose(RET_CANCEL); dispose(); } }); @@ -81,15 +103,10 @@ public class TagAndCommentDialog extends JDialog { //center it this.setLocationRelativeTo(WindowManager.getDefault().getMainWindow()); - - customizeComponent(); setVisible(true); // blocks } - - private void customizeComponent() { - } - + /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -195,22 +212,12 @@ public class TagAndCommentDialog extends JDialog { }// //GEN-END:initComponents private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed - //doClose(RET_OK); - - // get the selected tag and comment - String selectedTag = (String)tagCombo.getSelectedItem(); - String comment = commentText.getText(); - - // create the tag - taggable.createTag(selectedTag, comment); - - refreshDirectoryTree(); - + tagName = (String)tagCombo.getSelectedItem(); + comment = commentText.getText(); dispose(); }//GEN-LAST:event_okButtonActionPerformed private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed - //doClose(RET_CANCEL); dispose(); }//GEN-LAST:event_cancelButtonActionPerformed @@ -218,14 +225,12 @@ public class TagAndCommentDialog extends JDialog { * Closes the dialog */ private void closeDialog(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_closeDialog - //doClose(RET_CANCEL); dispose(); }//GEN-LAST:event_closeDialog private void newTagButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTagButtonActionPerformed String newTagName = CreateTagDialog.getNewTagNameDialog(null); if (newTagName != null) { - //tagsModel.addElement(newTagName); tagCombo.addItem(newTagName); tagCombo.setSelectedItem(newTagName); } @@ -240,12 +245,4 @@ public class TagAndCommentDialog extends JDialog { private javax.swing.JComboBox tagCombo; private javax.swing.JLabel tagLabel; // End of variables declaration//GEN-END:variables - //private int returnStatus = RET_CANCEL; - - private void refreshDirectoryTree() { - //TODO instead should send event to node children, which will call its refresh() / refreshKeys() - DirectoryTreeTopComponent viewer = DirectoryTreeTopComponent.findInstance(); - viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE); - viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT); - } } diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/TagBlackboardArtifactAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/TagBlackboardArtifactAction.java new file mode 100755 index 0000000000..3d1a9641b3 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/directorytree/TagBlackboardArtifactAction.java @@ -0,0 +1,71 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013 Basis Technology Corp. + * Contact: carrier sleuthkit 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.directorytree; + +import java.awt.event.ActionEvent; +import java.util.Collection; +import javax.swing.AbstractAction; +import javax.swing.JMenuItem; +import org.openide.util.Utilities; +import org.openide.util.actions.Presenter; +import org.sleuthkit.autopsy.datamodel.Tags; +import org.sleuthkit.datamodel.BlackboardArtifact; + +public class TagBlackboardArtifactAction extends AbstractAction implements Presenter.Popup { + // This class is a singleton to support multi-selection of nodes, since + // org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every + // node in the array returns a reference to the same action object from Node.getActions(boolean). + private static TagBlackboardArtifactAction instance; + + public static synchronized TagBlackboardArtifactAction getInstance() { + if (null == instance) { + instance = new TagBlackboardArtifactAction(); + } + return instance; + } + + private TagBlackboardArtifactAction() { + } + + @Override + public JMenuItem getPopupPresenter() { + return new TagBlackboardArtifactMenu(); + } + + @Override + public void actionPerformed(ActionEvent e) { + // Do nothing - this action should never be performed. + // Submenu actions are invoked instead. + } + + + private static class TagBlackboardArtifactMenu extends TagMenu { + public TagBlackboardArtifactMenu() { + super(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class).size() > 1 ? "Tag Results" : "Tag Result"); + } + + @Override + protected void applyTag(String tagName, String comment) { + Collection selectedArtifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class); + for (BlackboardArtifact artifact : selectedArtifacts) { + Tags.createTag(artifact, tagName, comment); + } + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/TagMenu.java b/Core/src/org/sleuthkit/autopsy/directorytree/TagMenu.java index af432e199a..e329dde10c 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/TagMenu.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/TagMenu.java @@ -24,38 +24,20 @@ import java.util.List; import javax.swing.JMenu; import javax.swing.JMenuItem; import org.sleuthkit.autopsy.datamodel.Tags; -import org.sleuthkit.autopsy.datamodel.Tags.Taggable; -import org.sleuthkit.autopsy.datamodel.Tags.TaggableBlackboardArtifact; -import org.sleuthkit.autopsy.datamodel.Tags.TaggableFile; -import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; /** * The menu that results when one right-clicks on a file or artifact. */ -public class TagMenu extends JMenu { - - private Taggable tagCreator; - - public TagMenu(AbstractFile file) { - super("Tag File"); - tagCreator = new TaggableFile(file); - init(); - } - - public TagMenu(BlackboardArtifact bba) { - super("Tag Result"); - tagCreator = new TaggableBlackboardArtifact(bba); - init(); - } +public abstract class TagMenu extends JMenu { + public TagMenu(String menuItemText) { + super(menuItemText); - private void init() { - - // create the 'Quick Tag' menu and add it to the 'Tag File' menu + // Create the 'Quick Tag' sub-menu and add it to the tag menu. JMenu quickTagMenu = new JMenu("Quick Tag"); - add(quickTagMenu); - - // create the 'Quick Tag' sub-menu items and add them to the 'Quick Tag' menu + add(quickTagMenu); + + // Get the existing tag names. List tagNames = Tags.getTagNames(); if (tagNames.isEmpty()) { JMenuItem empty = new JMenuItem("No tags"); @@ -63,50 +45,56 @@ public class TagMenu extends JMenu { quickTagMenu.add(empty); } + // Add a menu item for each existing tag name to the 'Quick Tag' menu. for (final String tagName : tagNames) { - JMenuItem tagItem = new JMenuItem(tagName); - tagItem.addActionListener(new ActionListener() { + JMenuItem tagNameItem = new JMenuItem(tagName); + tagNameItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - tagCreator.createTag(tagName, ""); + applyTag(tagName, ""); refreshDirectoryTree(); } }); - quickTagMenu.add(tagItem); + quickTagMenu.add(tagNameItem); } quickTagMenu.addSeparator(); - // create the 'New Tag' menu item + // Create the 'New Tag' menu item and add it to the 'Quick Tag' menu. JMenuItem newTagMenuItem = new JMenuItem("New Tag"); newTagMenuItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - String newTagName = CreateTagDialog.getNewTagNameDialog(null); - if (newTagName != null) { - tagCreator.createTag(newTagName, ""); + String tagName = CreateTagDialog.getNewTagNameDialog(null); + if (tagName != null) { + applyTag(tagName, ""); refreshDirectoryTree(); } } }); - - // add the 'New Tag' menu item to the 'Quick Tag' menu quickTagMenu.add(newTagMenuItem); - JMenuItem newTagItem = new JMenuItem("Tag and Comment"); - newTagItem.addActionListener(new ActionListener() { + // Create the 'Tag and Comment' menu item and add it to the tag menu. + JMenuItem tagAndCommentItem = new JMenuItem("Tag and Comment"); + tagAndCommentItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - new TagAndCommentDialog(tagCreator); + TagAndCommentDialog.CommentedTag commentedTag = TagAndCommentDialog.doDialog(); + if (null != commentedTag) { + applyTag(commentedTag.getName(), commentedTag.getComment()); + refreshDirectoryTree(); + } } }); - add(newTagItem); + add(tagAndCommentItem); } - + private void refreshDirectoryTree() { //TODO instead should send event to node children, which will call its refresh() / refreshKeys() DirectoryTreeTopComponent viewer = DirectoryTreeTopComponent.findInstance(); viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE); viewer.refreshTree(BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT); } + + protected abstract void applyTag(String tagName, String comment); } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestDialog.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestDialog.java index 01cfba4239..598d768e38 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestDialog.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestDialog.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,13 +26,14 @@ import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.List; -import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JPanel; +import org.openide.util.Lookup; import org.sleuthkit.datamodel.Content; +import org.sleuthkit.autopsy.casemodule.IngestConfigurator; /** * IngestDialog shown on Case.CASE_ADD_IMAGE property change @@ -41,21 +42,18 @@ public class IngestDialog extends JDialog { private static final String TITLE = "Ingest Modules"; private static Dimension DIMENSIONS = new Dimension(500, 300); - private IngestDialogPanel panel = null; + private IngestConfigurator ingestConfigurator; - private static final Logger logger = Logger.getLogger(IngestDialog.class.getName()); - public IngestDialog(JFrame frame, String title, boolean modal) { super(frame, title, modal); - panel = new IngestDialogPanel(); + ingestConfigurator = Lookup.getDefault().lookup(IngestConfigurator.class); + ingestConfigurator.reload(); } public IngestDialog(){ this(new JFrame(TITLE), TITLE, true); } - - /** * Shows the Ingest dialog. */ @@ -71,17 +69,14 @@ public class IngestDialog extends JDialog { // set the location of the popUp Window on the center of the screen setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2); - panel.reload(); // reload the simple panel - add(panel, BorderLayout.PAGE_START); + add(ingestConfigurator.getIngestConfigPanel(), BorderLayout.PAGE_START); JButton startButton = new JButton("Start"); JButton closeButton = new JButton("Close"); startButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - - panel.save(); - panel.start(); + ingestConfigurator.start(); close(); } }); @@ -89,7 +84,7 @@ public class IngestDialog extends JDialog { @Override public void actionPerformed(ActionEvent e) { - panel.save(); + ingestConfigurator.save(); close(); } }); @@ -97,7 +92,7 @@ public class IngestDialog extends JDialog { @Override public void windowClosing(WindowEvent e) { - panel.save(); + ingestConfigurator.save(); close(); } }); @@ -113,11 +108,10 @@ public class IngestDialog extends JDialog { setResizable(false); setVisible(true); } - + public void setContent(List inputContent) { - panel.setContent(inputContent); - } - + ingestConfigurator.setContent(inputContent); + } /** * Closes the Ingest dialog @@ -126,6 +120,4 @@ public class IngestDialog extends JDialog { setVisible(false); dispose(); } - - } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.java index d6e65d2bac..98d7c197fe 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,24 +18,15 @@ */ package org.sleuthkit.autopsy.ingest; -import java.awt.Color; import java.awt.Component; -import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; +import java.util.AbstractMap; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.logging.Level; -import org.sleuthkit.autopsy.coreutils.Logger; -import javax.swing.JPanel; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; @@ -43,80 +34,47 @@ import javax.swing.event.ListSelectionListener; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; -import org.openide.util.lookup.ServiceProvider; -import org.sleuthkit.autopsy.casemodule.IngestConfigurator; import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationDialog; -import org.sleuthkit.autopsy.coreutils.ModuleSettings; -import org.sleuthkit.autopsy.ingest.IngestModuleAbstract.ModuleType; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.TskCoreException; /** * main configuration panel for all ingest modules, reusable JPanel component */ -@ServiceProvider(service = IngestConfigurator.class) -public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfigurator { +public class IngestDialogPanel extends javax.swing.JPanel { - private IngestManager manager = null; - private List modules; private IngestModuleAbstract currentModule; - private Map moduleStates; private ModulesTableModel tableModel; - private static final Logger logger = Logger.getLogger(IngestDialogPanel.class.getName()); public static final String DISABLED_MOD = "Disabled_Ingest_Modules"; public static final String PARSE_UNALLOC = "Process_Unallocated_Space"; - // The input content that's just been added to the database - private List inputContent; - // private static IngestDialogPanel instance = null; /** * Creates new form IngestDialogPanel */ public IngestDialogPanel() { tableModel = new ModulesTableModel(); - modules = new ArrayList(); - moduleStates = new HashMap(); initComponents(); customizeComponents(); } - private void loadModules() { - this.modules.clear(); - //this.moduleStates.clear(); maintain the state - Collection imageModules = manager.enumerateDataSourceModules(); - for (final IngestModuleDataSource module : imageModules) { - addModule(module); - } - Collection fsModules = manager.enumerateAbstractFileModules(); - for (final IngestModuleAbstractFile module : fsModules) { - addModule(module); - } + public IngestModuleAbstract getCurrentIngestModule() { + return currentModule; + } + + public List getModulesToStart() { + return tableModel.getSelectedModules(); + } + + public boolean processUnallocSpaceEnabled() { + return processUnallocCheckbox.isSelected(); } private void customizeComponents() { modulesTable.setModel(tableModel); - this.manager = IngestManager.getDefault(); - - loadModules(); - try { - IngestModuleLoader.getDefault().addModulesReloadedListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getPropertyName().equals(IngestModuleLoader.Event.ModulesReloaded.toString())) { - loadModules(); - } - } - }); - } catch (IngestModuleLoaderException ex) { - logger.log(Level.SEVERE, "Could not initialize ingest module loader to listen for module config changes", ex); - } - modulesTable.setTableHeader(null); modulesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); //custom renderer for tooltips - ModulesTableRenderer renderer = new ModulesTableRenderer(); + //customize column witdhs final int width = modulesScrollPane.getPreferredSize().width; TableColumn column = null; @@ -135,40 +93,30 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi public void valueChanged(ListSelectionEvent e) { ListSelectionModel listSelectionModel = (ListSelectionModel) e.getSource(); if (!listSelectionModel.isSelectionEmpty()) { - save(); int index = listSelectionModel.getMinSelectionIndex(); - currentModule = modules.get(index); - reload(); + currentModule = tableModel.getModule(index); + + // add the module-specific configuration panel, if there is one + simplePanel.removeAll(); + if (currentModule.hasSimpleConfiguration()) { + simplePanel.add(currentModule.getSimpleConfiguration()); + } + simplePanel.revalidate(); + simplePanel.repaint(); advancedButton.setEnabled(currentModule.hasAdvancedConfiguration()); } else { currentModule = null; } } }); - - processUnallocCheckbox.setSelected(manager.getProcessUnallocSpace()); - } - private void setProcessUnallocSpaceEnabled(boolean enabled) { - processUnallocCheckbox.setEnabled(enabled); + public void setProcessUnallocSpaceEnabled(final boolean enabled) { + processUnallocCheckbox.setSelected(enabled); } - - @Override - public void paint(Graphics g) { - super.paint(g); - if (manager.isIngestRunning()) { - setProcessUnallocSpaceEnabled(false); - - } else { - setProcessUnallocSpaceEnabled(true); - } - } - - private void addModule(IngestModuleAbstract module) { - final String moduleName = module.getName(); - modules.add(module); - moduleStates.put(moduleName, true); + + public void setDisabledModules(List disabledModules) { + tableModel.setUnselectedModules(disabledModules); } /** @@ -311,22 +259,19 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi public void actionPerformed(ActionEvent e) { dialog.close(); currentModule.saveAdvancedConfiguration(); - reload(); } }); dialog.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { dialog.close(); - reload(); } }); - save(); // save the simple panel - dialog.display(currentModule.getAdvancedConfiguration(null)); + dialog.display(currentModule.getAdvancedConfiguration()); }//GEN-LAST:event_advancedButtonActionPerformed private void processUnallocCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_processUnallocCheckboxActionPerformed - // TODO add your handling code here: + // nothing to do here }//GEN-LAST:event_processUnallocCheckboxActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton advancedButton; @@ -342,10 +287,19 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi // End of variables declaration//GEN-END:variables private class ModulesTableModel extends AbstractTableModel { + + private List>moduleData = new ArrayList<>(); + + public ModulesTableModel() { + List modules = IngestManager.getDefault().enumerateAllModules(); + for (IngestModuleAbstract ingestModuleAbstract : modules) { + moduleData.add(new AbstractMap.SimpleEntry<>(ingestModuleAbstract, Boolean.TRUE)); + } + } @Override public int getRowCount() { - return modules.size(); + return moduleData.size(); } @Override @@ -355,11 +309,11 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi @Override public Object getValueAt(int rowIndex, int columnIndex) { - String name = modules.get(rowIndex).getName(); + Map.Entry entry = moduleData.get(rowIndex); if (columnIndex == 0) { - return moduleStates.get(name); + return entry.getValue(); } else { - return name; + return entry.getKey().getName(); } } @@ -371,8 +325,7 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { if (columnIndex == 0) { - moduleStates.put((String) getValueAt(rowIndex, 1), (Boolean) aValue); - + moduleData.get(rowIndex).setValue((Boolean)aValue); } } @@ -380,183 +333,96 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } - } - - List getModulesToStart() { - List modulesToStart = new ArrayList(); - for (IngestModuleAbstract module : modules) { - boolean moduleEnabled = moduleStates.get(module.getName()); - if (moduleEnabled) { - modulesToStart.add(module); - } - } - return modulesToStart; - } - - private boolean processUnallocSpaceEnabled() { - return processUnallocCheckbox.isEnabled(); - } - - /** - * To be called whenever the next, close, or start buttons are pressed. - * - */ - @Override - public void save() { - // Save the current module - if (currentModule != null && currentModule.hasSimpleConfiguration()) { - currentModule.saveSimpleConfiguration(); - } - // Save this panel - List modulesDisabled = new ArrayList(); - for (int i = 0; i < modulesTable.getRowCount(); i++) { - // Column 0 is always the module's checkbox (which is retreived as a boolean) - Boolean enabled = (Boolean) modulesTable.getValueAt(i, 0); - if (!enabled) { - // Column 1 is always the module name - String moduleName = (String) modulesTable.getValueAt(i, 1); - modulesDisabled.add(moduleName); - } - } - // Add all the enabled modules to the properties separated by a coma - String list = ""; - for (int i = 0; i < modulesDisabled.size(); i++) { - list += modulesDisabled.get(i); - if (i + 1 < modulesDisabled.size()) { - list += ", "; - } - } - ModuleSettings.setConfigSetting(IngestManager.MODULE_PROPERTIES, DISABLED_MOD, list); - String processUnalloc = Boolean.toString(processUnallocCheckbox.isSelected()); - ModuleSettings.setConfigSetting(IngestManager.MODULE_PROPERTIES, PARSE_UNALLOC, processUnalloc); - - } - - /** - * Called when the dialog needs to be reloaded. Most commonly used to - * refresh the simple panel. - * - * Called every time this panel is displayed. - */ - @Override - public void reload() { - // Reload the simple panel - if (this.modulesTable.getSelectedRow() != -1) { - simplePanel.removeAll(); - if (currentModule.hasSimpleConfiguration()) { - simplePanel.add(currentModule.getSimpleConfiguration(null)); - } - simplePanel.revalidate(); - simplePanel.repaint(); - } - // Reload this panel - String list = ModuleSettings.getConfigSetting(IngestManager.MODULE_PROPERTIES, DISABLED_MOD); - if (list != null) { // if no property is found, list will be null - List modulesDisabled = new ArrayList(Arrays.asList(list.split(", "))); - // For every row, see if that module name is in the ArrayList - for (int i = 0; i < modulesTable.getRowCount(); i++) { - String moduleName = (String) modulesTable.getValueAt(i, 1); - if (modulesDisabled.contains(moduleName)) { - modulesTable.setValueAt(false, i, 0); // we found it, disable the module - } else { - modulesTable.setValueAt(true, i, 0); // not on disabled list, or a new module, enable it + + public List getSelectedModules() { + List selectedModules = new ArrayList<>(); + for (Map.Entry entry : moduleData) { + if (entry.getValue().booleanValue()) { + selectedModules.add(entry.getKey()); } } + return selectedModules; } - String processUnalloc = ModuleSettings.getConfigSetting(IngestManager.MODULE_PROPERTIES, PARSE_UNALLOC); - if (processUnalloc != null) { - processUnallocCheckbox.setSelected(Boolean.parseBoolean(processUnalloc)); + + /** + * Sets the given modules as selected in the modules table + * @param selectedModules + */ + public void setSelectedModules(List selectedModules) { + // unselect all modules + for (Map.Entry entry : moduleData) { + entry.setValue(Boolean.FALSE); + } + + // select only the given modules + for (IngestModuleAbstract selectedModule : selectedModules) { + getEntryForModule(selectedModule).setValue(Boolean.TRUE); + } + + // tell everyone about it + fireTableDataChanged(); } - } - - @Override - public JPanel getIngestConfigPanel() { - this.reload(); - return this; - } - - @Override - public void setContent(List inputContent) { - this.inputContent = inputContent; - } - - @Override - public void start() { - //pick the modules - List modulesToStart = getModulesToStart(); - - //update ingest proc. unalloc space - if (processUnallocSpaceEnabled()) { - manager.setProcessUnallocSpace(processUnallocCheckbox.isSelected()); + + /** + * Sets the given modules as NOT selected in the modules table + * @param selectedModules + */ + public void setUnselectedModules(List unselectedModules) { + // select all modules + for (Map.Entry entry : moduleData) { + entry.setValue(Boolean.TRUE); + } + + // unselect only the given modules + for (IngestModuleAbstract unselectedModule : unselectedModules) { + getEntryForModule(unselectedModule).setValue(Boolean.FALSE); + } + + // tell everyone about it + fireTableDataChanged(); } - - if (!modulesToStart.isEmpty()) { - manager.execute(modulesToStart, inputContent); + + public IngestModuleAbstract getModule(int row) { + return moduleData.get(row).getKey(); + } + + private Map.Entry getEntryForModule(IngestModuleAbstract module) { + Map.Entry entry = null; + for (Map.Entry anEntry : moduleData) { + if (anEntry.getKey().equals(module)) { + entry = anEntry; + break; + } + } + return entry; } - - } - - @Override - public boolean isIngestRunning() { - return manager.isIngestRunning(); } /** * Custom cell renderer for tooltips with module description */ private class ModulesTableRenderer extends DefaultTableCellRenderer { + + List tooltips = new ArrayList<>(); + + public ModulesTableRenderer() { + List modules = IngestManager.getDefault().enumerateAllModules(); + for (IngestModuleAbstract ingestModuleAbstract : modules) { + tooltips.add(ingestModuleAbstract.getDescription()); + } + } @Override public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, - int row, int column) { - - final Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + int row, int column) { + super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (column == 1) { - //String moduleName = (String) table.getModel().getValueAt(row, column); - IngestModuleAbstract module = modules.get(row); - String moduleDescr = module.getDescription(); - String toolTip = moduleDescr; - - if (inputContent != null && module.getType().equals(ModuleType.DataSource)) { - - //DataSource module accepts only data source, does not work on any child - //show warning to user and set fg red for that module - boolean isDataSource = true; - for (Content content : inputContent) { - try { - if (content.getParent() != null) { - isDataSource = false; - break; - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error checking if module input content is parentless data source", e); - } - - } - - if (! isDataSource ) { - cell.setForeground(Color.red); - toolTip = toolTip + "
WARNING: this module will not run on current selection because it operates only on root-level data-source (such as Image, Filesets)."; - } - else { - cell.setForeground(Color.black); - } - - - - } //end data source - else { - cell.setForeground(Color.black); - } - // - - setToolTipText("" + toolTip+ ""); + setToolTipText(tooltips.get(row)); } - - return cell; + return this; } } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java index a1ddb6e3d2..3d6e73ef3a 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012 Basis Technology Corp. + * Copyright 2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -154,8 +154,6 @@ public class IngestManager { } catch (IngestModuleLoaderException ex) { logger.log(Level.SEVERE, "Error getting module loader"); } - - } /** @@ -243,7 +241,6 @@ public class IngestManager { if (ui != null) { ui.restoreMessages(); } - } /** @@ -346,8 +343,6 @@ public class IngestManager { } } } - //} - //AbstractFile ingester boolean startAbstractFileIngester = false; @@ -421,7 +416,6 @@ public class IngestManager { List toStop = new ArrayList(); toStop.addAll(dataSourceIngesters); - for (IngestDataSourceThread dataSourceWorker : toStop) { IngestModuleDataSource s = dataSourceWorker.getModule(); @@ -440,7 +434,6 @@ public class IngestManager { logger.log(Level.WARNING, "Exception while stopping module: " + s.getName(), e); } } - } logger.log(Level.INFO, "stopped all"); @@ -545,7 +538,6 @@ public class IngestManager { return module.hasBackgroundJobsRunning(); } - } else { //data source module synchronized (this) { @@ -570,10 +562,7 @@ public class IngestManager { return false; } } - } - - } /** @@ -607,7 +596,7 @@ public class IngestManager { * * @param processUnallocSpace */ - void setProcessUnallocSpace(boolean processUnallocSpace) { + public void setProcessUnallocSpace(boolean processUnallocSpace) { this.processUnallocSpace = processUnallocSpace; } @@ -671,6 +660,13 @@ public class IngestManager { public List enumerateAbstractFileModules() { return moduleLoader.getAbstractFileIngestModules(); } + + public List enumerateAllModules() { + List modules = new ArrayList<>(); + modules.addAll(enumerateDataSourceModules()); + modules.addAll(enumerateAbstractFileModules()); + return modules; + } //data source worker to remove itself when complete or interrupted void removeDataSourceIngestWorker(IngestDataSourceThread worker) { @@ -697,7 +693,6 @@ public class IngestManager { IngestManagerStats() { errors = new HashMap(); - } /** @@ -775,19 +770,8 @@ public class IngestManager { public String toHtmlString() { StringBuilder sb = new StringBuilder(); sb.append(""); - sb.append("Ingest time: ").append(getTotalTimeString()).append("
"); sb.append("Total errors: ").append(errorsTotal).append("
"); - /* - if (errorsTotal > 0) { - sb.append("Errors per module:"); - for (IngestModuleAbstract module : errors.keySet()) { - final int errorsModule = errors.get(module); - sb.append("\t").append(module.getName()).append(": ").append(errorsModule).append("
"); - } - } - * */ - sb.append(""); return sb.toString(); } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleAbstract.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleAbstract.java index d30e57f785..f8ff21bb82 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleAbstract.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleAbstract.java @@ -145,35 +145,28 @@ public abstract class IngestModuleAbstract { */ public void saveAdvancedConfiguration() {} - /** - * Returns a panel that displays the simple (run-time) configuration - * for the given configuration context (such as pipeline instance). - * This is presented to the user before ingest starts and only basic - * settings should be given here. Use the advanced (general) configuration - * panel for more in-depth interfaces. - * The module (or its configuration controller object) is responsible for preserving / saving its configuration state - * In addition, saveSimpleConfiguration() can be used as the trigger. - * - * @param context the configuration context to use in the panel - * @return JPanel containing basic configuration widgets or null if simple configuration is not available - */ - public javax.swing.JPanel getSimpleConfiguration(String context) { - return null; - } - /** - * Returns a panel that displays the advanced (run-time) configuration - * for the given configuration context (such as pipeline instance). - * Implements advanced module configuration exposed to the user before ingest starts. - * - * The module (or its configuration controller object) - * is responsible for preserving / saving its configuration state - * In addition, saveAdvancedConfiguration() can be used as the trigger. - * - * @param context the configuration context to use in the panel - * @return JPanel containing advanced configuration widgets or null if advanced configuration is not available - */ - public javax.swing.JPanel getAdvancedConfiguration(String context) { - return null; - }; -} + * Returns a panel that displays the simple (run-time) configuration. + * This is presented to the user before ingest starts and only basic + * settings should be given here. use the advanced (general) configuration + * panel for more in-depth interfaces. + * The module is responsible for preserving / saving its configuration state + * In addition, saveSimpleConfiguration() can be used + * + * @return JPanel containing basic configuration widgets or null if simple configuration is not available + */ + public javax.swing.JPanel getSimpleConfiguration() { + return null; + } + + /** + * Implements advanced module configuration exposed to the user before ingest starts + * The module is responsible for preserving / saving its configuration state + * In addition, saveAdvancedConfiguration() can be used + * + * @return JPanel containing basic configuration widgets or null if advanced configuration is not available + */ + public javax.swing.JPanel getAdvancedConfiguration() { + return null; + }; + } \ No newline at end of file diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestModule.java b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestModule.java index dd311ee2ed..ba7e621d7e 100644 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestModule.java +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestModule.java @@ -216,13 +216,13 @@ public class HashDbIngestModule extends IngestModuleAbstractFile { } @Override - public javax.swing.JPanel getSimpleConfiguration(String context) { + public javax.swing.JPanel getSimpleConfiguration() { HashDbXML.getCurrent().reload(); return new HashDbSimplePanel(); } @Override - public javax.swing.JPanel getAdvancedConfiguration(String context) { + public javax.swing.JPanel getAdvancedConfiguration() { //return HashDbManagementPanel.getDefault(); getPanel().load(); return getPanel(); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java index bb9945dfa4..968631e27a 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchFilterNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,9 +28,9 @@ import org.openide.nodes.PropertySupport; import org.openide.nodes.Sheet; import org.openide.util.lookup.Lookups; import org.openide.util.lookup.ProxyLookup; -import org.sleuthkit.autopsy.directorytree.TagAction; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExtractAction; +import org.sleuthkit.autopsy.directorytree.TagAbstractFileAction; import org.sleuthkit.autopsy.directorytree.HashSearchAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; import org.sleuthkit.datamodel.Content; @@ -128,8 +128,6 @@ class KeywordSearchFilterNode extends FilterNode { Content content = this.getOriginal().getLookup().lookup(Content.class); actions.addAll(content.accept(new GetPopupActionsContentVisitor())); - //actions.add(new IndexContentFilesAction(nodeContent, "Index")); - return actions.toArray(new Action[actions.size()]); } @@ -137,33 +135,29 @@ class KeywordSearchFilterNode extends FilterNode { @Override public List visit(File f) { - List actions = new ArrayList(); - actions.add(new NewWindowViewAction("View in New Window", KeywordSearchFilterNode.this)); - actions.add(new ExternalViewerAction("Open in External Viewer", getOriginal())); - actions.add(null); - actions.add(new ExtractAction("Extract File", getOriginal())); - actions.add(new HashSearchAction("Search for files with the same MD5 hash", getOriginal())); - actions.add(null); // creates a menu separator - actions.add(new TagAction(getOriginal())); - return actions; + return getFileActions(); } @Override public List visit(DerivedFile f) { - List actions = new ArrayList(); + return getFileActions(); + } + + private List getFileActions() { + List actions = new ArrayList<>(); actions.add(new NewWindowViewAction("View in New Window", KeywordSearchFilterNode.this)); actions.add(new ExternalViewerAction("Open in External Viewer", getOriginal())); actions.add(null); - actions.add(new ExtractAction("Extract File", getOriginal())); + actions.add(ExtractAction.getInstance()); actions.add(new HashSearchAction("Search for files with the same MD5 hash", getOriginal())); actions.add(null); // creates a menu separator - actions.add(new TagAction(getOriginal())); - return actions; + actions.add(TagAbstractFileAction.getInstance()); + return actions; } @Override protected List defaultVisit(Content c) { - return new ArrayList(); + return new ArrayList<>(); } } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java index e6bf38c848..f447695a34 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java @@ -432,13 +432,13 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile { } @Override - public javax.swing.JPanel getSimpleConfiguration(String context) { + public javax.swing.JPanel getSimpleConfiguration() { KeywordSearchListsXML.getCurrent().reload(); return new KeywordSearchIngestSimplePanel(); } @Override - public javax.swing.JPanel getAdvancedConfiguration(String context) { + public javax.swing.JPanel getAdvancedConfiguration() { //return KeywordSearchConfigurationPanel.getDefault(); getPanel().load(); return getPanel();