diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/UpdateRecentCases.java b/Core/src/org/sleuthkit/autopsy/casemodule/UpdateRecentCases.java index 147337965b..b57f20abdf 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/UpdateRecentCases.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/UpdateRecentCases.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2015 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -60,7 +60,7 @@ class UpdateRecentCases extends JMenuItem implements DynamicMenuContent { menuItem.setActionCommand(caseName[i].toUpperCase()); menuItem.addActionListener(new RecentItems(caseName[i], casePath[i])); comps[i] = menuItem; - hasRecentCase = hasRecentCase || true; + hasRecentCase = true; } } diff --git a/Core/src/org/sleuthkit/autopsy/core/layer.xml b/Core/src/org/sleuthkit/autopsy/core/layer.xml index 2f36280e7a..8ad4410fb4 100644 --- a/Core/src/org/sleuthkit/autopsy/core/layer.xml +++ b/Core/src/org/sleuthkit/autopsy/core/layer.xml @@ -203,6 +203,13 @@ + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties index a30199c86c..6ee8e785f8 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties @@ -1,4 +1,5 @@ OpenIDE-Module-Name=Ingest +Menu/Tools/RunIngestModules=Run Ingest Modules CTL_IngestMessageTopComponent=Messages HINT_IngestMessageTopComponent=Messages windows IngestMessageDetailsPanel.backButton.text= @@ -99,3 +100,4 @@ IngestJobTableModel.colName.rootQueued=Root Queued IngestJobTableModel.colName.dsQueued=DS Queued ModuleTableModel.colName.module=Module ModuleTableModel.colName.duration=Duration +RunIngestSubMenu.menuItem.empty=-Empty- diff --git a/Core/src/org/sleuthkit/autopsy/ingest/RunIngestAction.java b/Core/src/org/sleuthkit/autopsy/ingest/RunIngestAction.java new file mode 100755 index 0000000000..0bcd23b8b9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/ingest/RunIngestAction.java @@ -0,0 +1,93 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2015 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.ingest; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JMenuItem; +import org.openide.awt.ActionID; +import org.openide.awt.ActionRegistration; +import org.openide.util.HelpCtx; +import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; +import org.openide.util.actions.CallableSystemAction; +import org.openide.util.actions.Presenter; + +@ActionID( + category = "Tools", + id = "org.sleuthkit.autopsy.ingest.RunIngestAction" +) +@ActionRegistration( + displayName = "#CTL_RunIngestAction" +) +@Messages("CTL_RunIngestAction=Run Ingest") +public final class RunIngestAction extends CallableSystemAction implements Presenter.Menu, ActionListener { + + static public RunIngestAction getInstance() { + return new RunIngestAction(); + } + + /** + * Call getMenuPresenters to create images sublist + */ + @Override + public void performAction() { + getMenuPresenter(); + } + + /** + * Gets the name of this action. This may be presented as an item in a menu. + * + * @return actionName + */ + @Override + public String getName() { + return NbBundle.getMessage(RunIngestAction.class, "RunIngestModulesMenu.getName.text"); + } + + /** + * Gets the HelpCtx associated with implementing object + * + * @return HelpCtx or HelpCtx.DEFAULT_HELP + */ + @Override + public HelpCtx getHelpCtx() { + return HelpCtx.DEFAULT_HELP; + } + + /** + * Create a sublist of images updated by RunIngestSubMenu + * Each has an action to perform Ingest Modules on it. + * + * @return the images sublist created. + */ + @Override + public JMenuItem getMenuPresenter() { + JMenuItem sublist = new RunIngestSubMenu(); + sublist.setVisible(true); + return sublist; + } + + /** + * This method does nothing, use performAction instead. + */ + @Override + public void actionPerformed(ActionEvent e) { + } +} diff --git a/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesAction.java b/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesAction.java new file mode 100755 index 0000000000..50a2319529 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesAction.java @@ -0,0 +1,52 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2015 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.ingest; + +import java.awt.event.ActionEvent; +import java.util.Collections; +import javax.swing.AbstractAction; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.Image; + +/** + * This class is used to add the action to the run ingest modules menu item. + * When the image is pressed, it should open the wizard for ingest modules. + */ +final class RunIngestModulesAction extends AbstractAction { + + Image image; + + /** + * the constructor + */ + public RunIngestModulesAction(Image image) { + this.image = image; + } + + /** + * Runs the ingest modules wizard on the image. + * + * @param e the action event + */ + @Override + public void actionPerformed(ActionEvent e) { + final RunIngestModulesDialog ingestDialog = new RunIngestModulesDialog(Collections.singletonList(image)); + ingestDialog.display(); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java b/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java index 4b81506603..da491fd22a 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/RunIngestModulesDialog.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2014 Basis Technology Corp. + * Copyright 2013-2015 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/ingest/RunIngestSubMenu.java b/Core/src/org/sleuthkit/autopsy/ingest/RunIngestSubMenu.java new file mode 100755 index 0000000000..f4db5d47e8 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/ingest/RunIngestSubMenu.java @@ -0,0 +1,99 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2015 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.ingest; + +import java.util.ArrayList; +import java.util.List; +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import org.openide.awt.DynamicMenuContent; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.datamodel.Image; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * This class is used to populate the list of open images to run ingest on them + */ +final class RunIngestSubMenu extends JMenuItem implements DynamicMenuContent { + + /** + * Creates main menu/popup menu items. It's called each time a popup menu + * is constructed and just once for the main menu. + * Main menu updates happen through the synchMenuPresenters() method. + * + * @return + */ + @Override + public JComponent[] getMenuPresenters() { + List images = new ArrayList<>(); + + try { + SleuthkitCase sk = Case.getCurrentCase().getSleuthkitCase(); + images = sk.getImages(); + } catch (IllegalStateException ex) { + // No open Cases, create a disabled empty menu + return getEmpty(); + } catch (TskCoreException e) { + System.out.println("Exception getting images: " + e.getMessage()); + } + JComponent[] comps = new JComponent[images.size()]; + + // Add Images to the component list + for (int i = 0; i < images.size(); i++) { + String action = images.get(i).getName(); + JMenuItem menuItem = new JMenuItem(action); + menuItem.setActionCommand(action.toUpperCase()); + menuItem.addActionListener(new RunIngestModulesAction(images.get(i))); + comps[i] = menuItem; + } + // If no images are open, create a disabled empty menu + if (images.isEmpty()) { + return getEmpty(); + } + return comps; + } + + // returns a disabled empty menu + private JComponent[] getEmpty() { + JComponent[] comps = new JComponent[1]; + JMenuItem emptyMenu = new JMenuItem(NbBundle.getMessage(RunIngestSubMenu.class, "RunIngestSubMenu.menuItem.empty")); + comps[0] = emptyMenu; + comps[0].setEnabled(false); + return comps; + } + + /** + * Updates main menu presenters. This method is called only by the main menu + * processing. + * + * @param jcs the previously used menu items returned by previous call to + * getMenuPresenters() or synchMenuPresenters() + * + * @return menu a new set of items to show in menu. Can be either an updated + * old set of instances or a completely new one. + */ + @Override + public JComponent[] synchMenuPresenters(JComponent[] jcs) { + return getMenuPresenters(); + } + + +} diff --git a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties index c7f862b1fc..5e74024afe 100644 --- a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties @@ -3,6 +3,7 @@ CTL_ReportWizardAction=Run Report ArtifactSelectionDialog.titleLabel.text=Select which artifacts you would like to report on: ArtifactSelectionDialog.okButton.text=OK ReportVisualPanel1.reportModulesLabel.text=Report Modules: +ReportVisualPanel1.invalidModuleWarning=Encountered an invalid Report Module ({0}) DefaultReportConfigurationPanel.infoLabel.text=This report will be configured on the next screen. ReportVisualPanel2.dataLabel.text=Select which data to report on: ReportVisualPanel2.deselectAllButton.text=Deselect All diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index ccb22c3f55..f53d374f49 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -151,7 +151,7 @@ class ReportGenerator { if (entry.getValue()) { TableReportModule module = entry.getKey(); String reportFilePath = module.getRelativeFilePath(); - if (reportFilePath != null) { + if (!reportFilePath.isEmpty()) { tableProgress.put(module, panel.addReport(module.getName(), reportPath + reportFilePath)); } else { tableProgress.put(module, panel.addReport(module.getName(), null)); @@ -165,7 +165,7 @@ class ReportGenerator { if (entry.getValue()) { GeneralReportModule module = entry.getKey(); String reportFilePath = module.getRelativeFilePath(); - if (reportFilePath != null) { + if (!reportFilePath.isEmpty()) { generalProgress.put(module, panel.addReport(module.getName(), reportPath + reportFilePath)); } else { generalProgress.put(module, panel.addReport(module.getName(), null)); @@ -179,7 +179,7 @@ class ReportGenerator { if (entry.getValue()) { FileReportModule module = entry.getKey(); String reportFilePath = module.getRelativeFilePath(); - if (reportFilePath != null) { + if (!reportFilePath.isEmpty()) { fileProgress.put(module, panel.addReport(module.getName(), reportPath + reportFilePath)); } else { fileProgress.put(module, panel.addReport(module.getName(), null)); diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel1.java b/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel1.java index acd49f029e..9b6acfd092 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel1.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel1.java @@ -27,6 +27,7 @@ import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.logging.Level; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JRadioButton; @@ -34,11 +35,12 @@ import javax.swing.ListCellRenderer; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.python.JythonModuleLoader; -import org.sleuthkit.autopsy.report.ReportHTML; final class ReportVisualPanel1 extends JPanel implements ListSelectionListener { @@ -64,23 +66,39 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener { // Initialize the list of ReportModules private void initModules() { for (TableReportModule module : Lookup.getDefault().lookupAll(TableReportModule.class)) { - tableModules.add(module); - modules.add(module); + if (moduleIsValid(module)) { + tableModules.add(module); + modules.add(module); + } else { + popupWarning(module); + } } for (GeneralReportModule module : Lookup.getDefault().lookupAll(GeneralReportModule.class)) { - generalModules.add(module); - modules.add(module); + if (moduleIsValid(module)) { + generalModules.add(module); + modules.add(module); + } else { + popupWarning(module); + } } for (GeneralReportModule module : JythonModuleLoader.getGeneralReportModules()) { - generalModules.add(module); - modules.add(module); + if (moduleIsValid(module)) { + generalModules.add(module); + modules.add(module); + } else { + popupWarning(module); + } } for (FileReportModule module : Lookup.getDefault().lookupAll(FileReportModule.class)) { - fileModules.add(module); - modules.add(module); + if (moduleIsValid(module)) { + fileModules.add(module); + modules.add(module); + } else { + popupWarning(module); + } } Collections.sort(modules, new Comparator() { @@ -117,6 +135,20 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener { modulesJList.setSelectedIndex(selectedIndex); } + // Make sure that the report module has a valid non-null name. + private boolean moduleIsValid(ReportModule module) { + return module.getName() != null && !module.getName().isEmpty() + && module.getRelativeFilePath() != null; + } + + private void popupWarning(ReportModule module) { + String moduleClassName = module.getClass().getSimpleName(); + logger.log(Level.WARNING, "Invalid ReportModule: {0}", moduleClassName); // NON_NLS + DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message( + NbBundle.getMessage(ReportVisualPanel1.class, "ReportVisualPanel1.invalidModuleWarning", moduleClassName), + NotifyDescriptor.ERROR_MESSAGE)); + } + @Override public String getName() { return NbBundle.getMessage(this.getClass(), "ReportVisualPanel1.getName.text");