/* * Autopsy Forensic Browser * * Copyright 2013 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sleuthkit.autopsy.modules.hashdatabase; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Collection; import java.util.List; import java.util.logging.Level; import javax.swing.AbstractAction; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import org.openide.util.NbBundle; import org.openide.util.Utilities; import org.openide.util.actions.Presenter; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; import static org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.HashUtility; import org.sleuthkit.datamodel.TskCoreException; /** * Instances of this Action allow users to content to a hash database. */ final class AddContentToHashDbAction extends AbstractAction implements Presenter.Popup { private static AddContentToHashDbAction instance; private final static String SINGLE_SELECTION_NAME = NbBundle.getMessage(AddContentToHashDbAction.class, "AddContentToHashDbAction.singleSelectionName"); private final static String MULTIPLE_SELECTION_NAME = NbBundle.getMessage(AddContentToHashDbAction.class, "AddContentToHashDbAction.multipleSelectionName"); /** * AddContentToHashDbAction is a singleton to support multi-selection of * nodes, since org.openide.nodes.NodeOp.findActions(Node[] nodes) will only * pick up an Action from a node if every node in the nodes array returns a * reference to the same action object from Node.getActions(boolean). */ public static synchronized AddContentToHashDbAction getInstance() { if (null == instance) { instance = new AddContentToHashDbAction(); } return instance; } private AddContentToHashDbAction() { } @Override public JMenuItem getPopupPresenter() { return new AddContentToHashDbMenu(); } @Override public void actionPerformed(ActionEvent event) { } // Instances of this class are used to implement the a pop up menu for this // action. private final class AddContentToHashDbMenu extends JMenu { AddContentToHashDbMenu() { super(SINGLE_SELECTION_NAME); // Disable the menu if file ingest is in progress. if (IngestManager.getInstance().isIngestRunning()) { setEnabled(false); return; } // Get any AbstractFile objects from the lookup of the currently focused top component. final Collection<? extends AbstractFile> selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class); if (selectedFiles.isEmpty()) { setEnabled(false); return; } else if (selectedFiles.size() > 1) { setText(MULTIPLE_SELECTION_NAME); } // Disable the menu if hashes have not been calculated. for (AbstractFile file : selectedFiles) { if (null == file.getMd5Hash()) { setEnabled(false); return; } } // Get the current set of updateable hash databases and add each // one to the menu as a separate menu item. Selecting a hash database // adds the selected files to the selected database. final List<HashDb> hashDatabases = HashDbManager.getInstance().getUpdateableHashSets(); if (!hashDatabases.isEmpty()) { for (final HashDb database : hashDatabases) { JMenuItem databaseItem = add(database.getHashSetName()); databaseItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { addFilesToHashSet(selectedFiles, database); } }); } } else { JMenuItem empty = new JMenuItem( NbBundle.getMessage(this.getClass(), "AddContentToHashDbAction.ContentMenu.noHashDbsConfigd")); empty.setEnabled(false); add(empty); } // Add a "New Hash Set..." menu item. Selecting this item invokes a // a hash database creation dialog and adds the selected files to the // the new database. addSeparator(); JMenuItem newHashSetItem = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddContentToHashDbAction.ContentMenu.createDbItem")); newHashSetItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { HashDb hashDb = new HashDbCreateDatabaseDialog().getHashDatabase(); if (null != hashDb) { addFilesToHashSet(selectedFiles, hashDb); } } }); add(newHashSetItem); } private void addFilesToHashSet(final Collection<? extends AbstractFile> files, HashDb hashSet) { for (AbstractFile file : files) { String md5Hash = file.getMd5Hash(); if (null != md5Hash) { // don't let them add the hash for an empty file to the DB if (HashUtility.isNoDataMd5(md5Hash)) { //NON-NLS Logger.getLogger(AddContentToHashDbAction.class.getName()).log(Level.INFO, "Not adding " + file.getName() + " to database (empty content)"); //NON-NLS JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "AddContentToHashDbAction.addFilesToHashSet.unableToAddFileEmptyMsg", file.getName()), NbBundle.getMessage(this.getClass(), "AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr1.text"), JOptionPane.ERROR_MESSAGE); continue; } try { hashSet.addHashes(file); } catch (TskCoreException ex) { Logger.getLogger(AddContentToHashDbAction.class.getName()).log(Level.SEVERE, "Error adding to hash database", ex); //NON-NLS JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "AddContentToHashDbAction.addFilesToHashSet.unableToAddFileMsg", file.getName()), NbBundle.getMessage(this.getClass(), "AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr2.text"), JOptionPane.ERROR_MESSAGE); } } else { JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "AddContentToHashDbAction.addFilesToHashSet.unableToAddFileSzMsg", files.size() > 1 ? NbBundle .getMessage(this.getClass(), "AddContentToHashDbAction.addFilesToHashSet.files") : NbBundle .getMessage(this.getClass(), "AddContentToHashDbAction.addFilesToHashSet.file")), NbBundle.getMessage(this.getClass(), "AddContentToHashDbAction.addFilesToHashSet.addToHashDbErr3.text"), JOptionPane.ERROR_MESSAGE); break; } } } } }