timeZoneComboBox;
private javax.swing.JLabel timeZoneLabel;
// End of variables declaration//GEN-END:variables
@@ -357,26 +383,26 @@ final class LocalDiskPanel extends JPanel {
}
String path = disk.getName();
-
+
// Remove any character that isn't alphanumeric, a space, parent, or underscore.
// If the name ends up empty or starting with a space, prepend "localDisk"
path = path.replaceAll("[^0-9A-Za-z _()]", ""); // NON-NLS
- if(path.isEmpty() || path.startsWith(" ")){
+ if (path.isEmpty() || path.startsWith(" ")) {
path = "localDisk" + path;
}
-
+
path += " " + System.currentTimeMillis();
path += ".vhd";
pathTextField.setText(Paths.get(getDefaultImageWriterFolder(), path).toString());
}
- private boolean imageWriterPathIsValid() {
- if((! copyImageCheckbox.isSelected()) || ! (diskTable.getSelectedRow() >= 0 && diskTable.getSelectedRow() < disks.size())){
+ private boolean imageWriterPathIsValid() {
+ if ((!copyImageCheckbox.isSelected()) || !(diskTable.getSelectedRow() >= 0 && diskTable.getSelectedRow() < disks.size())) {
imageWriterErrorLabel.setVisible(false);
imageWriterErrorLabel.setText("");
return true;
}
-
+
if (pathTextField.getText().isEmpty()) {
imageWriterErrorLabel.setVisible(true);
imageWriterErrorLabel.setText(NbBundle.getMessage(this.getClass(), "LocalDiskPanel.imageWriterEmptyPathError.text"));
@@ -611,12 +637,14 @@ final class LocalDiskPanel extends JPanel {
errorLabel.setToolTipText(NbBundle.getMessage(this.getClass(),
"LocalDiskPanel.errLabel.drivesNotDetected.toolTipText"));
}
+ errorLabel.setVisible(true);
diskTable.setEnabled(false);
} else if (physicalDrives.isEmpty()) {
errorLabel.setText(
NbBundle.getMessage(this.getClass(), "LocalDiskPanel.errLabel.someDisksNotDetected.text"));
errorLabel.setToolTipText(NbBundle.getMessage(this.getClass(),
"LocalDiskPanel.errLabel.someDisksNotDetected.toolTipText"));
+ errorLabel.setVisible(true);
}
}
@@ -625,7 +653,7 @@ final class LocalDiskPanel extends JPanel {
try {
super.get(); //block and get all exceptions thrown while doInBackground()
} catch (CancellationException ex) {
- logger.log(Level.INFO, "Loading local disks was canceled, which should not be possible."); //NON-NLS
+ logger.log(Level.INFO, "Loading local disks was canceled."); //NON-NLS
} catch (InterruptedException ex) {
logger.log(Level.INFO, "Loading local disks was interrupted."); //NON-NLS
} catch (Exception ex) {
@@ -644,14 +672,15 @@ final class LocalDiskPanel extends JPanel {
diskTable.clearSelection();
}
pathTextField.setText("");
- errorLabel.setText("");
- errorLabel.setVisible(false);
fireUpdateEvent();
ready = true;
} else {
- logger.log(Level.INFO, "Loading local disks was canceled, which should not be possible."); //NON-NLS
+ //this should not be possible but happens
+ //possible threading error when this method is called while running
+ logger.log(Level.INFO, "Loading local disks was canceled"); //NON-NLS
}
}
+ diskTable.revalidate();
}
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties
index 1aa7a3b24e..525c46c071 100644
--- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties
@@ -24,7 +24,7 @@ DataContentViewerString.pageLabel2.text=Page
# Product Information panel
LBL_Description=\n Product Version: {0} ({9})
Sleuth Kit Version: {7}
Netbeans RCP Build: {8}
Java: {1}; {2}
System: {3}; {4}; {5}
Userdir: {6}
Format_OperatingSystem_Value={0} version {1} running on {2}
-LBL_Copyright=Autopsy™ is a digital forensics platform based on The Sleuth Kit™ and other tools.
Copyright © 2003-2016.
+LBL_Copyright=Autopsy™ is a digital forensics platform based on The Sleuth Kit™ and other tools.
Copyright © 2003-2017.
URL_ON_IMG=http://www.sleuthkit.org/
URL_ON_HELP=http://sleuthkit.org/autopsy/docs/user-docs/4.3/
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/checkbox24.png b/Core/src/org/sleuthkit/autopsy/corecomponents/checkbox24.png
new file mode 100644
index 0000000000..4d9dd4562c
Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/corecomponents/checkbox24.png differ
diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java
index dc6f5ab2ab..6c245954d9 100644
--- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java
+++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java
@@ -70,7 +70,8 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
private static final Integer[] SHOW_UNIQUE_PATH = new Integer[]{
BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(),
- BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),};
+ BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
+ BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID(),};
// TODO (RC): This is an unattractive alternative to subclassing BlackboardArtifactNode,
// cut from the same cloth as the equally unattractive SHOW_UNIQUE_PATH array
@@ -207,7 +208,9 @@ public class BlackboardArtifactNode extends DisplayableItemNode {
// If this is a node for a keyword hit on an artifact, we set the
// display name to be the artifact type name followed by " Artifact"
// e.g. "Messages Artifact".
- if (artifact != null && artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) {
+ if (artifact != null &&
+ (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() ||
+ artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID())) {
try {
for (BlackboardAttribute attribute : artifact.getAttributes()) {
if (attribute.getAttributeType().getTypeID() == ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID()) {
diff --git a/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/IngestProfileSelectionPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/IngestProfileSelectionPanel.java
index 2d19de0bea..39146417c7 100644
--- a/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/IngestProfileSelectionPanel.java
+++ b/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/IngestProfileSelectionPanel.java
@@ -20,18 +20,20 @@ package org.sleuthkit.autopsy.ingest.runIngestModuleWizard;
import java.awt.Color;
import java.awt.Component;
+import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
+import java.awt.event.ActionListener;
import java.util.Collections;
import java.util.List;
+import javax.swing.Box;
import static javax.swing.Box.createVerticalGlue;
+import javax.swing.ButtonModel;
import javax.swing.JPanel;
-import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
+import javax.swing.JToggleButton;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.corecomponents.AdvancedConfigurationDialog;
import org.sleuthkit.autopsy.ingest.IngestOptionsPanel;
@@ -42,7 +44,7 @@ import org.sleuthkit.autopsy.ingest.IngestProfiles.IngestProfile;
* Visual panel for the choosing of ingest profiles by the user when running
* ingest.
*/
-final class IngestProfileSelectionPanel extends JPanel implements ItemListener {
+final class IngestProfileSelectionPanel extends JPanel {
@Messages({"IngestProfileSelectionPanel.customSettings.name=Custom Settings",
"IngestProfileSelectionPanel.customSettings.description=configure individual module settings in next step of wizard"})
@@ -55,6 +57,10 @@ final class IngestProfileSelectionPanel extends JPanel implements ItemListener {
private List profiles = Collections.emptyList();
boolean isLastPanel = false;
+ //Listener for profile button selection
+ ActionListener buttonGroupActionListener = (ActionEvent e) -> {
+ updateSelectedProfile();
+ };
/**
* Creates new IngestProfileSelectionPanel
*
@@ -65,8 +71,9 @@ final class IngestProfileSelectionPanel extends JPanel implements ItemListener {
initComponents();
wizardPanel = panel;
selectedProfile = lastSelectedProfile;
+ isLastPanel = !selectedProfile.equals(wizardPanel.getDefaultContext());
- populateListOfCheckboxes();
+ populateProfilesList();
}
/**
@@ -79,11 +86,28 @@ final class IngestProfileSelectionPanel extends JPanel implements ItemListener {
}
/**
- * Adds a radio button for custom settings as well as one for each profile
+ * Handles the change to selected profile
+ * if custom settings button is selected, it enables the next button, otherwise
+ * it enables the Finish button.
+ */
+ private void updateSelectedProfile() {
+
+ ButtonModel selectedButton = profileListButtonGroup.getSelection();
+ selectedProfile = selectedButton.getActionCommand();
+
+ boolean wasLastPanel = isLastPanel;
+ isLastPanel = !selectedProfile.equals(wizardPanel.getDefaultContext());
+ wizardPanel.fireChangeEvent();
+ this.firePropertyChange("LAST_ENABLED", wasLastPanel, isLastPanel); //NON-NLS
+ }
+
+ /**
+ * Adds a button for custom settings as well as one for each profile
* that has been created to the panel containing them.
*/
- private void populateListOfCheckboxes() {
+ private void populateProfilesList() {
profiles = getProfiles();
+
GridBagLayout gridBagLayout = new GridBagLayout();
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
@@ -92,13 +116,15 @@ final class IngestProfileSelectionPanel extends JPanel implements ItemListener {
constraints.weighty = .0;
constraints.anchor = GridBagConstraints.FIRST_LINE_START;
- addRadioButton(CUSTOM_SETTINGS_DISPLAY_NAME, wizardPanel.getDefaultContext(), CUSTOM_SETTINGS_DESCRIPTION, gridBagLayout, constraints);
- for (IngestProfile profile : profiles) {
+ addButton(CUSTOM_SETTINGS_DISPLAY_NAME, wizardPanel.getDefaultContext(), CUSTOM_SETTINGS_DESCRIPTION, gridBagLayout, constraints);
+
+ profiles.forEach((profile) -> {
constraints.weightx = 0;
constraints.gridy++;
constraints.gridx = 0;
- addRadioButton(profile.toString(), profile.toString(), profile.getDescription(), gridBagLayout, constraints);
- }
+
+ addButton(profile.toString(), profile.toString(), profile.getDescription(), gridBagLayout, constraints);
+ });
//Add vertical glue at the bottom of the scroll panel so spacing
//between elements is less dependent on the number of elements
constraints.gridy++;
@@ -119,29 +145,64 @@ final class IngestProfileSelectionPanel extends JPanel implements ItemListener {
* programmatically
* @param profileDesc - the description of the profile
*/
- private void addRadioButton(String profileDisplayName, String profileContextName, String profileDesc, GridBagLayout layout, GridBagConstraints constraints) {
- String displayText = profileDisplayName + " - " + profileDesc;
- JRadioButton myRadio = new JRadioButton();
+ private void addButton(String profileDisplayName, String profileContextName, String profileDesc, GridBagLayout layout, GridBagConstraints constraints) {
+
+ //Add a spacer
+ Dimension spacerBlockDimension = new Dimension(6, 4); // Space between left edge and button, Space between rows
+ Box.Filler spacer = new Box.Filler(spacerBlockDimension, spacerBlockDimension, spacerBlockDimension);
+ constraints.weightx = 1;
+ layout.setConstraints(spacer, constraints);
+ profileListPanel.add(spacer);
+ constraints.gridx++;
+ constraints.gridy++;
+
+
+ JToggleButton profileButton = new JToggleButton();
+ profileButton.setMaximumSize(new java.awt.Dimension(48, 48));
+ profileButton.setMinimumSize(new java.awt.Dimension(48, 48));
+ profileButton.setPreferredSize(new java.awt.Dimension(48, 48));
+
+ profileButton.setName(profileContextName);
+ profileButton.setActionCommand(profileContextName);
+
+ profileButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/timeline/images/magnifier-zoom-in-green.png")));
+ profileButton.setSelectedIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/checkbox24.png")));
+ profileButton.setFocusable(false);
+ profileButton.setFocusPainted(false);
+ profileButton.addActionListener(buttonGroupActionListener);
+
+ if (profileContextName.equals(selectedProfile)) {
+ profileButton.setSelected(true);
+ }
+
+ profileListButtonGroup.add(profileButton);
+ profileListPanel.add(profileButton);
+ layout.setConstraints(profileButton, constraints);
+ constraints.gridx++;
+ constraints.weightx = 1;
+
//Using a JTextArea as though it is a label in order to get multi-line support
+ String displayText = profileDisplayName;
+ if (!profileDesc.isEmpty()) {
+ displayText += " - " + profileDesc;
+ }
JTextArea myLabel = new JTextArea(displayText);
Color gray = new Color(240, 240, 240); //matches background of panel
myLabel.setBackground(gray);
myLabel.setEditable(false);
myLabel.setWrapStyleWord(true);
myLabel.setLineWrap(true);
- myRadio.setName(profileContextName);
- myRadio.setToolTipText(profileDesc);
- myRadio.addItemListener(this);
- if (profileContextName.equals(selectedProfile)) {
- myRadio.setSelected(true);
- }
- profileListButtonGroup.add(myRadio);
- profileListPanel.add(myRadio);
- layout.setConstraints(myRadio, constraints);
+
+ //Add space between the button and text
+ Box.Filler buttonTextSpacer = new Box.Filler(spacerBlockDimension, spacerBlockDimension, spacerBlockDimension);
+ layout.setConstraints(buttonTextSpacer, constraints);
+ profileListPanel.add(buttonTextSpacer);
constraints.gridx++;
- constraints.weightx = 1;
+
+ //Add the text area serving as a label to the right of the button
profileListPanel.add(myLabel);
layout.setConstraints(myLabel, constraints);
+
}
/**
@@ -164,30 +225,6 @@ final class IngestProfileSelectionPanel extends JPanel implements ItemListener {
profileListPanel.removeAll();
}
- /**
- * Listens for changes and checks the currently selected radio button if
- * custom settings button is enabled it enables the next button, otherwise
- * it enables the Finish button.
- *
- * @param e
- */
- @Override
- public void itemStateChanged(ItemEvent e) {
- for (Component rButton : profileListPanel.getComponents()) {
- if (rButton instanceof JRadioButton){
- JRadioButton jrb = (JRadioButton) rButton;
- if (jrb.isSelected()) {
- selectedProfile = jrb.getName();
- break;
- }
- }
- }
- boolean wasLastPanel = isLastPanel;
- isLastPanel = !selectedProfile.equals(wizardPanel.getDefaultContext());
- wizardPanel.fireChangeEvent();
- this.firePropertyChange("LAST_ENABLED", wasLastPanel, isLastPanel); //NON-NLS
- }
-
/**
* Get all the currently existing ingest profiles.
*/
@@ -272,7 +309,7 @@ final class IngestProfileSelectionPanel extends JPanel implements ItemListener {
fetchProfileList();
profileListPanel.revalidate();
profileListPanel.repaint();
- populateListOfCheckboxes();
+ populateProfilesList();
dialog.close();
}
);
diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java
index 8a9a2b8469..78a8481f17 100755
--- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java
@@ -32,6 +32,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
+import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
@@ -55,6 +56,7 @@ final class FilesIdentifierIngestModule implements FileIngestModule {
private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter();
private static final Map> interestingFileSetsByJob = new ConcurrentHashMap<>();
private final FilesIdentifierIngestJobSettings settings;
+ private final IngestServices services = IngestServices.getInstance();
private IngestJobContext context;
private Blackboard blackboard;
@@ -141,7 +143,18 @@ final class FilesIdentifierIngestModule implements FileIngestModule {
MessageNotifyUtil.Notify.error(Bundle.FilesIdentifierIngestModule_indexError_message(), artifact.getDisplayName());
}
- IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, Collections.singletonList(artifact)));
+ services.fireModuleDataEvent(new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, Collections.singletonList(artifact)));
+
+ // make an ingest inbox message
+ StringBuilder detailsSb = new StringBuilder();
+ detailsSb.append("File: " + file.getParentPath() + file.getName() + "
\n");
+ detailsSb.append("Rule Set: " + filesSet.getName());
+
+ services.postMessage(IngestMessage.createDataMessage(InterestingItemsIngestModuleFactory.getModuleName(),
+ "Interesting File Match: " + filesSet.getName() + "(" + file.getName() +")",
+ detailsSb.toString(),
+ file.getName(),
+ artifact));
} catch (TskCoreException ex) {
FilesIdentifierIngestModule.logger.log(Level.SEVERE, "Error posting to the blackboard", ex); //NOI18N NON-NLS