Add context menu to merge hosts.

Fixed capitalization on csv menu option.
This commit is contained in:
apriestman 2021-03-12 09:57:56 -05:00
parent ed633ff7e6
commit fa1b00d69b
6 changed files with 190 additions and 13 deletions

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.datamodel;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
@ -40,6 +41,7 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.events.HostsChangedEvent;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.hosts.AssociatePersonsMenuAction;
import org.sleuthkit.autopsy.datamodel.hosts.MergeHostMenuAction;
import org.sleuthkit.autopsy.datamodel.hosts.RemoveParentPersonAction;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.Host;
@ -287,10 +289,13 @@ public class HostNode extends DisplayableItemNode {
"HostNode_actions_removeFromPerson=Remove from person ({0})"})
public Action[] getActions(boolean context) {
Optional<Person> parent = Optional.empty();
List<Action> actionsList = new ArrayList<>();
// if there is a host, then provide actions
if (this.host != null) {
// Add the appropriate Person action
Optional<Person> parent;
try {
parent = Case.getCurrentCaseThrows().getSleuthkitCase().getHostManager().getPerson(this.host);
} catch (NoCurrentCaseException | TskCoreException ex) {
@ -300,17 +305,14 @@ public class HostNode extends DisplayableItemNode {
// if there is a parent, only give option to remove parent person.
if (parent.isPresent()) {
return new Action[]{
new RemoveParentPersonAction(this.host, parent.get()),
null
};
actionsList.add(new RemoveParentPersonAction(this.host, parent.get()));
} else {
return new Action[]{
new AssociatePersonsMenuAction(this.host),
null
};
actionsList.add(new AssociatePersonsMenuAction(this.host));
}
// Add option to merge hosts
actionsList.add(new MergeHostMenuAction(this.host));
}
return new Action[0];
return actionsList.toArray(new Action[actionsList.size()]);
}
}

View File

@ -31,6 +31,11 @@ AddEditHostDialog.okButton.text=OK
AddEditHostDialog.cancelButton.text=Cancel
AddEditHostDialog.inputTextField.text=jTextField1
ManageHostsDialog_title_text=Manage Hosts
# {0} - sourceHostName
# {1} - destHostName
MergeHostAction_onError_description=There was an error merging host {0} into host {1}.
MergeHostAction_onError_title=Error Merging Hosts
MergeHostMenuAction_menuTitle=Merge Into Other Host
OpenHostsAction_displayName=Hosts
# {0} - personName
RemoveParentPersonAction_menuTitle=Remove from Person ({0})

View File

@ -0,0 +1,76 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datamodel.hosts;
import java.awt.event.ActionEvent;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.JOptionPane;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Host;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Menu action to merge a host into another host.
*/
@Messages({
"MergeHostAction_onError_title=Error Merging Hosts",
"# {0} - sourceHostName",
"# {1} - destHostName",
"MergeHostAction_onError_description=There was an error merging host {0} into host {1}.",})
public class MergeHostAction extends AbstractAction {
private static final Logger logger = Logger.getLogger(MergeHostAction.class.getName());
private final Host sourceHost;
private final Host destHost;
/**
* Main constructor.
*
* @param sourceHost The source host.
* @param destHost The destination host.
*/
public MergeHostAction(Host sourceHost, Host destHost) {
super(destHost.getName());
this.sourceHost = sourceHost;
this.destHost = destHost;
}
@Override
public void actionPerformed(ActionEvent e) {
try {
Case.getCurrentCaseThrows().getSleuthkitCase().getHostManager().mergeHosts(sourceHost, destHost);
} catch (NoCurrentCaseException | TskCoreException ex) {
logger.log(Level.WARNING, String.format("Unable to merge host: %s into host: %s", sourceHost.getName(), destHost.getName()), ex);
JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(),
Bundle.MergeHostAction_onError_description(sourceHost, destHost),
Bundle.MergeHostAction_onError_title(),
JOptionPane.WARNING_MESSAGE);
}
}
}

View File

@ -0,0 +1,94 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.datamodel.hosts;
import java.awt.event.ActionEvent;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JSeparator;
import org.openide.util.NbBundle.Messages;
import org.openide.util.actions.Presenter;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Host;
import org.sleuthkit.datamodel.TskCoreException;
/**
*
* JMenu item to show a menu allowing the selected host to be merged into another host.
*/
@Messages({
"MergeHostMenuAction_menuTitle=Merge Into Other Host",})
public class MergeHostMenuAction extends AbstractAction implements Presenter.Popup {
private static final Logger logger = Logger.getLogger(MergeHostMenuAction.class.getName());
private final Host sourceHost;
/**
* Main constructor.
*
* @param host The original host.
*/
public MergeHostMenuAction(Host host) {
super("");
this.sourceHost = host;
}
@Override
@SuppressWarnings("NoopMethodInAbstractClass")
public void actionPerformed(ActionEvent event) {
}
@Override
public JMenuItem getPopupPresenter() {
JMenu menu = new JMenu(Bundle.MergeHostMenuAction_menuTitle());
// Get a list of all other hosts
List<Host> otherHosts = Collections.emptyList();
try {
otherHosts = Case.getCurrentCaseThrows().getSleuthkitCase().getHostManager().getHosts();
otherHosts.remove(sourceHost);
} catch (NoCurrentCaseException | TskCoreException ex) {
logger.log(Level.WARNING, "Error getting hosts for case.", ex);
}
// If there are no other hosts, disable the menu item. Otherwise add
// the other hosts to the menu.
if (otherHosts.isEmpty()) {
menu.setEnabled(false);
} else {
menu.setEnabled(true);
otherHosts.stream()
.filter(p -> p != null && p.getName() != null)
.sorted((a, b) -> a.getName().compareToIgnoreCase(b.getName()))
.map(p -> new JMenuItem(new MergeHostAction(sourceHost, p)))
.forEach(menu::add);
}
return menu;
}
}

View File

@ -14,7 +14,7 @@ ExportCSV.saveNodesToCSV.empty=No data to export
# {0} - Output file
ExportCSV.saveNodesToCSV.fileExists=File {0} already exists
ExportCSV.saveNodesToCSV.noCurrentCase=No open case available
ExportCSV.title.text=Export selected rows to CSV
ExportCSV.title.text=Export Selected Rows to CSV
ExternalViewerAction.actionPerformed.failure.exe.message=The file is an executable and will not be opened.
ExternalViewerAction.actionPerformed.failure.IO.message=There is no associated editor for files of this type or the associated application failed to launch.
ExternalViewerAction.actionPerformed.failure.missingFile.message=The file no longer exists.

View File

@ -85,7 +85,7 @@ public final class ExportCSVAction extends AbstractAction {
/**
* Private constructor for the action.
*/
@NbBundle.Messages({"ExportCSV.title.text=Export selected rows to CSV"})
@NbBundle.Messages({"ExportCSV.title.text=Export Selected Rows to CSV"})
private ExportCSVAction() {
super(Bundle.ExportCSV_title_text());
}