From 36b7a24ea10a824018fa5d98485400adfd6ab1a5 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 7 Nov 2017 13:52:13 -0500 Subject: [PATCH 01/90] 3201 initial revisions to Tag Options Panel to allow editing --- .../casemodule/services/Bundle.properties | 20 +- ...eDefiniton.java => TagNameDefinition.java} | 30 +- ...wTagNameDialog.form => TagNameDialog.form} | 66 +++- ...wTagNameDialog.java => TagNameDialog.java} | 145 ++++--- .../casemodule/services/TagOptionsPanel.form | 218 +++++++++-- .../casemodule/services/TagOptionsPanel.java | 234 ++++++++--- .../casemodule/services/TagsManager.java | 16 +- .../optionspanel/Bundle.properties | 3 - .../optionspanel/GlobalSettingsPanel.form | 108 +----- .../optionspanel/GlobalSettingsPanel.java | 76 ---- .../optionspanel/ManageTagsDialog.form | 147 ------- .../optionspanel/ManageTagsDialog.java | 364 ------------------ 12 files changed, 552 insertions(+), 875 deletions(-) rename Core/src/org/sleuthkit/autopsy/casemodule/services/{TagNameDefiniton.java => TagNameDefinition.java} (83%) rename Core/src/org/sleuthkit/autopsy/casemodule/services/{NewTagNameDialog.form => TagNameDialog.form} (57%) rename Core/src/org/sleuthkit/autopsy/casemodule/services/{NewTagNameDialog.java => TagNameDialog.java} (58%) delete mode 100755 Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.form delete mode 100755 Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties index 0dd66e8c59..6242c6793d 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties @@ -7,10 +7,16 @@ NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.title=Invalid character in NewTagNameDialog.JOptionPane.tagNameEmpty.message=The tag name cannot be empty NewTagNameDialog.JOptionPane.tagNameEmpty.title=Empty tag name TagOptionsPanel.tagTypesListLabel.text=Tag Names: -TagOptionsPanel.panelDescriptionLabel.text=Autopsy keeps a list of the tag names you have created in the past. Add more or delete them here. -NewTagNameDialog.okButton.text=OK -NewTagNameDialog.cancelButton.text=Cancel -NewTagNameDialog.tagNameTextField.text= -NewTagNameDialog.newTagNameLabel.text=New Tag Name: -TagOptionsPanel.deleteTagNameButton.text=Delete Tag Name -TagOptionsPanel.newTagNameButton.text=New Tag Name +TagOptionsPanel.deleteTagNameButton.text=Delete Tag +TagOptionsPanel.newTagNameButton.text=New Tag +TagOptionsPanel.editTagNameButton.text=Edit Tag +TagNameDialog.descriptionLabel.text=Description: +TagNameDialog.okButton.text=OK +TagNameDialog.cancelButton.text=Cancel +TagNameDialog.tagNameTextField.text= +TagNameDialog.newTagNameLabel.text=New Tag Name: +TagNameDialog.notableCheckbox.text=Tag indicates item is notable. +TagOptionsPanel.isNotableLabel.text=Tag indicates item is notable: +TagOptionsPanel.notableYesOrNoLabel.text= +TagOptionsPanel.descriptionLabel.text=Tag Description: +TagOptionsPanel.jTextArea1.text=Autopsy keeps a list of the tag names you have created in the past. Add more or delete them here. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java similarity index 83% rename from Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java rename to Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java index c22b380f96..84ae34c4f7 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java @@ -33,12 +33,12 @@ import org.sleuthkit.autopsy.datamodel.tags.Category; * A tag name definition consisting of a display name, description and color. */ @Immutable -final class TagNameDefiniton implements Comparable { +final class TagNameDefinition implements Comparable { private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS private static final List STANDARD_NOTABLE_TAG_DISPLAY_NAMES = Arrays.asList(TagsManager.getNotableItemText(), Category.ONE.getDisplayName(), Category.TWO.getDisplayName(), Category.THREE.getDisplayName()); // NON-NLS - private static final List STANDARD_TAG_DISPLAY_NAMES = Arrays.asList(TagsManager.getBookmarkText(), TagsManager.getFollowUpText(), + static final List STANDARD_TAG_DISPLAY_NAMES = Arrays.asList(TagsManager.getBookmarkText(), TagsManager.getFollowUpText(), TagsManager.getNotableItemText(), Category.ONE.getDisplayName(), Category.TWO.getDisplayName(), Category.THREE.getDisplayName(), Category.FOUR.getDisplayName(), Category.FIVE.getDisplayName()); @@ -57,7 +57,7 @@ final class TagNameDefiniton implements Comparable { * @param color The color for the tag name. * @param knownStatus The status denoted by the tag. */ - TagNameDefiniton(String displayName, String description, TagName.HTML_COLOR color, String knownStatus) { + TagNameDefinition(String displayName, String description, TagName.HTML_COLOR color, String knownStatus) { this.displayName = displayName; this.description = description; this.color = color; @@ -114,7 +114,7 @@ final class TagNameDefiniton implements Comparable { * the specified tag name definition. */ @Override - public int compareTo(TagNameDefiniton other) { + public int compareTo(TagNameDefinition other) { return this.getDisplayName().toLowerCase().compareTo(other.getDisplayName().toLowerCase()); } @@ -140,10 +140,10 @@ final class TagNameDefiniton implements Comparable { */ @Override public boolean equals(Object obj) { - if (!(obj instanceof TagNameDefiniton)) { + if (!(obj instanceof TagNameDefinition)) { return false; } - TagNameDefiniton thatTagName = (TagNameDefiniton) obj; + TagNameDefinition thatTagName = (TagNameDefinition) obj; return this.getDisplayName().equals(thatTagName.getDisplayName()); } @@ -171,8 +171,8 @@ final class TagNameDefiniton implements Comparable { * * @return A set of tag name definition objects. */ - static synchronized Set getTagNameDefinitions() { - Set tagNames = new HashSet<>(); + static synchronized Set getTagNameDefinitions() { + Set tagNames = new HashSet<>(); List standardTags = new ArrayList<>(STANDARD_TAG_DISPLAY_NAMES); String setting = ModuleSettings.getConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY); if (null != setting && !setting.isEmpty()) { @@ -189,21 +189,21 @@ final class TagNameDefiniton implements Comparable { if (tagNameAttributes.length == 3) { standardTags.remove(tagNameAttributes[0]); //Use standard tag's saved settings instead of default settings if (badTags.contains(tagNameAttributes[0])) { - tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), NOTABLE)); + tagNames.add(new TagNameDefinition(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), NOTABLE)); } else { - tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), "")); //add the default value for that tag + tagNames.add(new TagNameDefinition(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), "")); //add the default value for that tag } } else if (tagNameAttributes.length == 4) { standardTags.remove(tagNameAttributes[0]); //Use standard tag's saved settings instead of default settings - tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), tagNameAttributes[3])); + tagNames.add(new TagNameDefinition(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), tagNameAttributes[3])); } } } for (String standardTagName : standardTags) { if (STANDARD_NOTABLE_TAG_DISPLAY_NAMES.contains(standardTagName)) { - tagNames.add(new TagNameDefiniton(standardTagName, "", TagName.HTML_COLOR.NONE, NOTABLE)); + tagNames.add(new TagNameDefinition(standardTagName, "", TagName.HTML_COLOR.NONE, NOTABLE)); } else { - tagNames.add(new TagNameDefiniton(standardTagName, "", TagName.HTML_COLOR.NONE, "")); //add the default value for that tag + tagNames.add(new TagNameDefinition(standardTagName, "", TagName.HTML_COLOR.NONE, "")); //add the default value for that tag } } return tagNames; @@ -214,9 +214,9 @@ final class TagNameDefiniton implements Comparable { * * @param tagNames A set of tag name definition objects. */ - static synchronized void setTagNameDefinitions(Set tagNames) { + static synchronized void setTagNameDefinitions(Set tagNames) { StringBuilder setting = new StringBuilder(); - for (TagNameDefiniton tagName : tagNames) { + for (TagNameDefinition tagName : tagNames) { if (setting.length() != 0) { setting.append(";"); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.form b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.form similarity index 57% rename from Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.form rename to Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.form index b6400b7c31..e8162e6b3b 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.form @@ -23,10 +23,10 @@ - + - + @@ -34,6 +34,14 @@ + + + + + + + + @@ -41,20 +49,22 @@ - + - - - - + + + + + + + - @@ -63,21 +73,21 @@ - + - + - + @@ -87,12 +97,44 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java similarity index 58% rename from Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.java rename to Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java index ff21ac283b..e79004af6e 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java @@ -1,24 +1,25 @@ /* -* Autopsy Forensic Browser -* -* Copyright 2011-2016 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. + * Autopsy Forensic Browser + * + * Copyright 2011-2016 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.services; import java.awt.BorderLayout; +import java.awt.Color; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.event.WindowAdapter; @@ -28,11 +29,14 @@ import javax.swing.JOptionPane; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.openide.util.NbBundle; +import org.sleuthkit.datamodel.TskData; -final class NewTagNameDialog extends javax.swing.JDialog { +final class TagNameDialog extends javax.swing.JDialog { private static final long serialVersionUID = 1L; private String userTagDisplayName; + private String userTagDescription; + private boolean userTagIsNotable; private BUTTON_PRESSED result; enum BUTTON_PRESSED { @@ -42,13 +46,24 @@ final class NewTagNameDialog extends javax.swing.JDialog { /** * Creates a new NewUserTagNameDialog dialog. */ - NewTagNameDialog() { - super(new JFrame(NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.title.text")), - NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.title.text"), true); + TagNameDialog() { + super(new JFrame(NbBundle.getMessage(TagNameDialog.class, "NewTagNameDialog.title.text")), + NbBundle.getMessage(TagNameDialog.class, "NewTagNameDialog.title.text"), true); initComponents(); this.display(); } + TagNameDialog(TagNameDefinition tagNameToEdit) { + super(new JFrame("Edit 1"), + "Edit 2", true); + initComponents(); + tagNameTextField.setText(tagNameToEdit.getDisplayName()); + descriptionTextArea.setText(tagNameToEdit.getDescription()); + notableCheckbox.setSelected(tagNameToEdit.isNotable()); + tagNameTextField.setEnabled(false); + this.display(); + } + /** * Sets display settings for the dialog and adds appropriate listeners. */ @@ -56,7 +71,7 @@ final class NewTagNameDialog extends javax.swing.JDialog { setLayout(new BorderLayout()); /* - * Center the dialog + * Center the dialog */ Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); int width = this.getSize().width; @@ -81,14 +96,17 @@ final class NewTagNameDialog extends javax.swing.JDialog { public void changedUpdate(DocumentEvent e) { fire(); } + @Override public void removeUpdate(DocumentEvent e) { fire(); } + @Override public void insertUpdate(DocumentEvent e) { fire(); } + private void fire() { enableOkButton(); } @@ -105,6 +123,7 @@ final class NewTagNameDialog extends javax.swing.JDialog { /** * Called when a button is pressed or when the dialog is closed. + * * @param okPressed whether the OK button was pressed. */ private void doButtonAction(boolean okPressed) { @@ -112,38 +131,50 @@ final class NewTagNameDialog extends javax.swing.JDialog { String newTagDisplayName = tagNameTextField.getText().trim(); if (newTagDisplayName.isEmpty()) { JOptionPane.showMessageDialog(null, - NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameEmpty.message"), - NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameEmpty.title"), + NbBundle.getMessage(TagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameEmpty.message"), + NbBundle.getMessage(TagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameEmpty.title"), JOptionPane.ERROR_MESSAGE); return; } - if (TagsManager.containsIllegalCharacters(newTagDisplayName)) { + + //if a tag name contains illegal characters and is not the name of one of the standard tags + if (TagsManager.containsIllegalCharacters(newTagDisplayName) && !TagNameDefinition.STANDARD_TAG_DISPLAY_NAMES.contains(newTagDisplayName)) { JOptionPane.showMessageDialog(null, - NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.message"), - NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.title"), + NbBundle.getMessage(TagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.message"), + NbBundle.getMessage(TagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.title"), JOptionPane.ERROR_MESSAGE); return; } + userTagDescription = descriptionTextArea.getText(); userTagDisplayName = newTagDisplayName; + userTagIsNotable = notableCheckbox.isSelected(); result = BUTTON_PRESSED.OK; } else { result = BUTTON_PRESSED.CANCEL; } - setVisible(false); + setVisible(false); } /** * Returns the tag name entered by the user. - * - * @return a new user tag name + * + * @return a new user tag name */ String getTagName() { return userTagDisplayName; } + String getTagDesciption() { + return userTagDescription; + } + + boolean isTagNotable() { + return userTagIsNotable; + } + /** * Returns information about which button was pressed. - * + * * @return BUTTON_PRESSED (OK, CANCEL) */ BUTTON_PRESSED getResult() { @@ -151,9 +182,9 @@ final class NewTagNameDialog extends javax.swing.JDialog { } /** - * Enable the OK button if the tag name text field is not empty. - * Sets the enter button as default, so user can press enter to activate - * an okButton press and add the tag name. + * Enable the OK button if the tag name text field is not empty. Sets the + * enter button as default, so user can press enter to activate an okButton + * press and add the tag name. */ private void enableOkButton() { okButton.setEnabled(!tagNameTextField.getText().isEmpty()); @@ -173,27 +204,40 @@ final class NewTagNameDialog extends javax.swing.JDialog { tagNameTextField = new javax.swing.JTextField(); cancelButton = new javax.swing.JButton(); okButton = new javax.swing.JButton(); + descriptionScrollPane = new javax.swing.JScrollPane(); + descriptionTextArea = new javax.swing.JTextArea(); + descriptionLabel = new javax.swing.JLabel(); + notableCheckbox = new javax.swing.JCheckBox(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - org.openide.awt.Mnemonics.setLocalizedText(newTagNameLabel, org.openide.util.NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.newTagNameLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(newTagNameLabel, org.openide.util.NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.newTagNameLabel.text")); // NOI18N - tagNameTextField.setText(org.openide.util.NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.tagNameTextField.text")); // NOI18N + tagNameTextField.setText(org.openide.util.NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.tagNameTextField.text")); // NOI18N - org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.cancelButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.cancelButton.text")); // NOI18N cancelButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { cancelButtonActionPerformed(evt); } }); - org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.okButton.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.okButton.text")); // NOI18N okButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { okButtonActionPerformed(evt); } }); + descriptionTextArea.setColumns(20); + descriptionTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N + descriptionTextArea.setRows(5); + descriptionScrollPane.setViewportView(descriptionTextArea); + + org.openide.awt.Mnemonics.setLocalizedText(descriptionLabel, org.openide.util.NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.descriptionLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(notableCheckbox, org.openide.util.NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.notableCheckbox.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( @@ -201,13 +245,19 @@ final class NewTagNameDialog extends javax.swing.JDialog { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(tagNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 220, Short.MAX_VALUE) + .addComponent(tagNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 284, Short.MAX_VALUE) .addGroup(layout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(okButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(cancelButton)) - .addComponent(newTagNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(newTagNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(descriptionScrollPane, javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(notableCheckbox) + .addComponent(descriptionLabel)) + .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); layout.setVerticalGroup( @@ -217,13 +267,16 @@ final class NewTagNameDialog extends javax.swing.JDialog { .addComponent(newTagNameLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(tagNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(50, Short.MAX_VALUE)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(descriptionLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(descriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 57, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(notableCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 42, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(cancelButton) - .addComponent(okButton)) - .addContainerGap()) + .addComponent(okButton))) ); pack(); @@ -240,7 +293,11 @@ final class NewTagNameDialog extends javax.swing.JDialog { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton cancelButton; + private javax.swing.JLabel descriptionLabel; + private javax.swing.JScrollPane descriptionScrollPane; + private javax.swing.JTextArea descriptionTextArea; private javax.swing.JLabel newTagNameLabel; + private javax.swing.JCheckBox notableCheckbox; private javax.swing.JButton okButton; private javax.swing.JTextField tagNameTextField; // End of variables declaration//GEN-END:variables diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form index c58201621a..c2e5c06cab 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form @@ -16,7 +16,7 @@ - + @@ -29,7 +29,7 @@ - + @@ -37,43 +37,39 @@ - - - - - - + + + - - - + - + - + - - + + - - - + + + + @@ -89,34 +85,46 @@ - + - - + - - - - + + + + + + + + + + + + + + - + - - + + + + - - - + + + - - + + + - + @@ -144,7 +152,7 @@ - + @@ -157,6 +165,15 @@ + + + + + + + + + @@ -170,11 +187,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -187,15 +260,86 @@ - + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java index 8fc6a5ff4d..da774f7161 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java @@ -36,15 +36,15 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { private static final long serialVersionUID = 1L; private static final String DEFAULT_DESCRIPTION = ""; private static final TagName.HTML_COLOR DEFAULT_COLOR = TagName.HTML_COLOR.NONE; - private final DefaultListModel tagTypesListModel; - private Set tagTypes; + private final DefaultListModel tagTypesListModel; + private Set tagTypes; /** * Creates new form TagsManagerOptionsPanel */ TagOptionsPanel() { tagTypesListModel = new DefaultListModel<>(); - tagTypes = new TreeSet<>(TagNameDefiniton.getTagNameDefinitions()); + tagTypes = new TreeSet<>(TagNameDefinition.getTagNameDefinitions()); initComponents(); customizeComponents(); } @@ -52,7 +52,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { private void customizeComponents() { tagNamesList.setModel(tagTypesListModel); tagNamesList.addListSelectionListener((ListSelectionEvent event) -> { - enableButtons(); + updatePanel(); }); } @@ -66,7 +66,6 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { private void initComponents() { jPanel1 = new javax.swing.JPanel(); - panelDescriptionLabel = new javax.swing.JLabel(); jScrollPane2 = new javax.swing.JScrollPane(); jSplitPane1 = new javax.swing.JSplitPane(); modifyTagTypesListPanel = new javax.swing.JPanel(); @@ -75,14 +74,23 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { tagNamesList = new javax.swing.JList<>(); newTagNameButton = new javax.swing.JButton(); deleteTagNameButton = new javax.swing.JButton(); + editTagNameButton = new javax.swing.JButton(); + jScrollPane3 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); tagTypesAdditionalPanel = new javax.swing.JPanel(); + descriptionLabel = new javax.swing.JLabel(); + descriptionScrollPane = new javax.swing.JScrollPane(); + descriptionTextArea = new javax.swing.JTextArea(); + isNotableLabel = new javax.swing.JLabel(); + notableYesOrNoLabel = new javax.swing.JLabel(); - jPanel1.setPreferredSize(new java.awt.Dimension(750, 500)); + jPanel1.setPreferredSize(new java.awt.Dimension(750, 490)); - org.openide.awt.Mnemonics.setLocalizedText(panelDescriptionLabel, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.panelDescriptionLabel.text")); // NOI18N + jScrollPane2.setPreferredSize(new java.awt.Dimension(750, 490)); - jSplitPane1.setDividerLocation(400); + jSplitPane1.setDividerLocation(365); jSplitPane1.setDividerSize(1); + jSplitPane1.setPreferredSize(new java.awt.Dimension(748, 488)); org.openide.awt.Mnemonics.setLocalizedText(tagTypesListLabel, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.tagTypesListLabel.text")); // NOI18N @@ -91,6 +99,9 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { newTagNameButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add-tag.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(newTagNameButton, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.newTagNameButton.text")); // NOI18N + newTagNameButton.setMaximumSize(new java.awt.Dimension(111, 25)); + newTagNameButton.setMinimumSize(new java.awt.Dimension(111, 25)); + newTagNameButton.setPreferredSize(new java.awt.Dimension(111, 25)); newTagNameButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { newTagNameButtonActionPerformed(evt); @@ -99,12 +110,36 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { deleteTagNameButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/delete-tag.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(deleteTagNameButton, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.deleteTagNameButton.text")); // NOI18N + deleteTagNameButton.setMaximumSize(new java.awt.Dimension(111, 25)); + deleteTagNameButton.setMinimumSize(new java.awt.Dimension(111, 25)); + deleteTagNameButton.setPreferredSize(new java.awt.Dimension(111, 25)); deleteTagNameButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { deleteTagNameButtonActionPerformed(evt); } }); + org.openide.awt.Mnemonics.setLocalizedText(editTagNameButton, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.editTagNameButton.text")); // NOI18N + editTagNameButton.setMaximumSize(new java.awt.Dimension(111, 25)); + editTagNameButton.setMinimumSize(new java.awt.Dimension(111, 25)); + editTagNameButton.setPreferredSize(new java.awt.Dimension(111, 25)); + editTagNameButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + editTagNameButtonActionPerformed(evt); + } + }); + + jTextArea1.setEditable(false); + jTextArea1.setBackground(new java.awt.Color(240, 240, 240)); + jTextArea1.setColumns(20); + jTextArea1.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N + jTextArea1.setLineWrap(true); + jTextArea1.setRows(3); + jTextArea1.setText(org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.jTextArea1.text")); // NOI18N + jTextArea1.setWrapStyleWord(true); + jTextArea1.setFocusable(false); + jScrollPane3.setViewportView(jTextArea1); + javax.swing.GroupLayout modifyTagTypesListPanelLayout = new javax.swing.GroupLayout(modifyTagTypesListPanel); modifyTagTypesListPanel.setLayout(modifyTagTypesListPanelLayout); modifyTagTypesListPanelLayout.setHorizontalGroup( @@ -112,40 +147,88 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { .addGroup(modifyTagTypesListPanelLayout.createSequentialGroup() .addContainerGap() .addGroup(modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(tagTypesListLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(modifyTagTypesListPanelLayout.createSequentialGroup() - .addComponent(newTagNameButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(deleteTagNameButton) - .addGap(0, 113, Short.MAX_VALUE))) - .addContainerGap()) - ); - modifyTagTypesListPanelLayout.setVerticalGroup( - modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(modifyTagTypesListPanelLayout.createSequentialGroup() - .addContainerGap() - .addComponent(tagTypesListLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 381, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(newTagNameButton) - .addComponent(deleteTagNameButton)) + .addGroup(modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, modifyTagTypesListPanelLayout.createSequentialGroup() + .addComponent(newTagNameButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(editTagNameButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(deleteTagNameButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 345, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); + modifyTagTypesListPanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {deleteTagNameButton, editTagNameButton, newTagNameButton}); + + modifyTagTypesListPanelLayout.setVerticalGroup( + modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(modifyTagTypesListPanelLayout.createSequentialGroup() + .addGap(10, 10, 10) + .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(tagTypesListLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 355, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(newTagNameButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(editTagNameButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(deleteTagNameButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + + modifyTagTypesListPanelLayout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {deleteTagNameButton, editTagNameButton, newTagNameButton}); + jSplitPane1.setLeftComponent(modifyTagTypesListPanel); + org.openide.awt.Mnemonics.setLocalizedText(descriptionLabel, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.descriptionLabel.text")); // NOI18N + + descriptionTextArea.setEditable(false); + descriptionTextArea.setBackground(new java.awt.Color(240, 240, 240)); + descriptionTextArea.setColumns(20); + descriptionTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N + descriptionTextArea.setLineWrap(true); + descriptionTextArea.setRows(5); + descriptionTextArea.setWrapStyleWord(true); + descriptionTextArea.setFocusable(false); + descriptionScrollPane.setViewportView(descriptionTextArea); + + org.openide.awt.Mnemonics.setLocalizedText(isNotableLabel, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.isNotableLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(notableYesOrNoLabel, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.notableYesOrNoLabel.text")); // NOI18N + javax.swing.GroupLayout tagTypesAdditionalPanelLayout = new javax.swing.GroupLayout(tagTypesAdditionalPanel); tagTypesAdditionalPanel.setLayout(tagTypesAdditionalPanelLayout); tagTypesAdditionalPanelLayout.setHorizontalGroup( tagTypesAdditionalPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 354, Short.MAX_VALUE) + .addGroup(tagTypesAdditionalPanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(tagTypesAdditionalPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(descriptionScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 361, Short.MAX_VALUE) + .addComponent(descriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(tagTypesAdditionalPanelLayout.createSequentialGroup() + .addComponent(isNotableLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(notableYesOrNoLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap()) ); tagTypesAdditionalPanelLayout.setVerticalGroup( tagTypesAdditionalPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 454, Short.MAX_VALUE) + .addGroup(tagTypesAdditionalPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(descriptionLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(descriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(tagTypesAdditionalPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(isNotableLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(notableYesOrNoLabel)) + .addContainerGap(351, Short.MAX_VALUE)) ); jSplitPane1.setRightComponent(tagTypesAdditionalPanel); @@ -157,27 +240,23 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(panelDescriptionLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jScrollPane2)) - .addContainerGap()) + .addGap(0, 0, 0) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(0, 0, 0)) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addComponent(panelDescriptionLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 458, Short.MAX_VALUE) - .addContainerGap()) + .addGap(0, 0, 0) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(0, 0, 0)) ); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 778, Short.MAX_VALUE) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -186,11 +265,11 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { }// //GEN-END:initComponents private void newTagNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTagNameButtonActionPerformed - NewTagNameDialog dialog = new NewTagNameDialog(); - NewTagNameDialog.BUTTON_PRESSED result = dialog.getResult(); - if (result == NewTagNameDialog.BUTTON_PRESSED.OK) { - String newTagDisplayName = dialog.getTagName(); - TagNameDefiniton newTagType = new TagNameDefiniton(newTagDisplayName, DEFAULT_DESCRIPTION, DEFAULT_COLOR, ""); + TagNameDialog dialog = new TagNameDialog(); + TagNameDialog.BUTTON_PRESSED result = dialog.getResult(); + if (result == TagNameDialog.BUTTON_PRESSED.OK) { + String status = dialog.isTagNotable() ? "(Notable)" : ""; + TagNameDefinition newTagType = new TagNameDefinition(dialog.getTagName(), dialog.getTagDesciption(), DEFAULT_COLOR, status); /* * If tag name already exists, don't add the tag name. */ @@ -198,7 +277,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { tagTypes.add(newTagType); updateTagNamesListModel(); tagNamesList.setSelectedValue(newTagType, true); - enableButtons(); + updatePanel(); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); } else { JOptionPane.showMessageDialog(null, @@ -210,23 +289,51 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { }//GEN-LAST:event_newTagNameButtonActionPerformed private void deleteTagNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteTagNameButtonActionPerformed - TagNameDefiniton tagName = tagNamesList.getSelectedValue(); + TagNameDefinition tagName = tagNamesList.getSelectedValue(); tagTypes.remove(tagName); updateTagNamesListModel(); - enableButtons(); + updatePanel(); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + }//GEN-LAST:event_deleteTagNameButtonActionPerformed + private void editTagNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editTagNameButtonActionPerformed + TagNameDefinition originalTagName = tagNamesList.getSelectedValue(); + TagNameDialog dialog = new TagNameDialog(originalTagName); + TagNameDialog.BUTTON_PRESSED result = dialog.getResult(); + if (result == TagNameDialog.BUTTON_PRESSED.OK) { + String status = dialog.isTagNotable() ? "(Notable)" : ""; + TagNameDefinition newTagType = new TagNameDefinition(dialog.getTagName(), dialog.getTagDesciption(), DEFAULT_COLOR, status); + /* + * If tag name already exists, don't add the tag name. + */ + + tagTypes.remove(originalTagName); + tagTypes.add(newTagType); + updateTagNamesListModel(); + tagNamesList.setSelectedValue(newTagType, true); + updatePanel(); + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + } + }//GEN-LAST:event_editTagNameButtonActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton deleteTagNameButton; + private javax.swing.JLabel descriptionLabel; + private javax.swing.JScrollPane descriptionScrollPane; + private javax.swing.JTextArea descriptionTextArea; + private javax.swing.JButton editTagNameButton; + private javax.swing.JLabel isNotableLabel; private javax.swing.JPanel jPanel1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JScrollPane jScrollPane3; private javax.swing.JSplitPane jSplitPane1; + private javax.swing.JTextArea jTextArea1; private javax.swing.JPanel modifyTagTypesListPanel; private javax.swing.JButton newTagNameButton; - private javax.swing.JLabel panelDescriptionLabel; - private javax.swing.JList tagNamesList; + private javax.swing.JLabel notableYesOrNoLabel; + private javax.swing.JList tagNamesList; private javax.swing.JPanel tagTypesAdditionalPanel; private javax.swing.JLabel tagTypesListLabel; // End of variables declaration//GEN-END:variables @@ -236,7 +343,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { */ private void updateTagNamesListModel() { tagTypesListModel.clear(); - for (TagNameDefiniton tagName : tagTypes) { + for (TagNameDefinition tagName : tagTypes) { tagTypesListModel.addElement(tagName); } } @@ -246,9 +353,9 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { */ @Override public void load() { - tagTypes = new TreeSet<>(TagNameDefiniton.getTagNameDefinitions()); + tagTypes = new TreeSet<>(TagNameDefinition.getTagNameDefinitions()); updateTagNamesListModel(); - enableButtons(); + updatePanel(); } /** @@ -256,19 +363,36 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { */ @Override public void store() { - TagNameDefiniton.setTagNameDefinitions(tagTypes); + TagNameDefinition.setTagNameDefinitions(tagTypes); } /** * Enables the button components based on the state of the tag types list * component. */ - private void enableButtons() { + private void updatePanel() { /* * Only enable the delete button when there is a tag type selected in * the tag types JList. */ - deleteTagNameButton.setEnabled(tagNamesList.getSelectedIndex() != -1); + boolean isSelected = tagNamesList.getSelectedIndex() != -1; + editTagNameButton.setEnabled(isSelected); + boolean enableDelete = isSelected && !TagNameDefinition.STANDARD_TAG_DISPLAY_NAMES.contains(tagNamesList.getSelectedValue().getDisplayName()); + deleteTagNameButton.setEnabled(enableDelete); + if (isSelected){ + + descriptionTextArea.setText(tagNamesList.getSelectedValue().getDescription()); + if (tagNamesList.getSelectedValue().isNotable()){ + notableYesOrNoLabel.setText("Yes"); + } + else { + notableYesOrNoLabel.setText("No"); + } + } + else { + descriptionTextArea.setText(""); + notableYesOrNoLabel.setText(""); + } } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index b9f63983fa..5ee847cfa9 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -115,7 +115,7 @@ public class TagsManager implements Closeable { */ public static Set getTagDisplayNames() throws TskCoreException { Set tagDisplayNames = new HashSet<>(); - Set customNames = TagNameDefiniton.getTagNameDefinitions(); + Set customNames = TagNameDefinition.getTagNameDefinitions(); customNames.forEach((tagType) -> { tagDisplayNames.add(tagType.getDisplayName()); }); @@ -134,7 +134,7 @@ public class TagsManager implements Closeable { public static List getNotableTagDisplayNames() { List tagDisplayNames = new ArrayList<>(); - for (TagNameDefiniton tagDef : TagNameDefiniton.getTagNameDefinitions()) { + for (TagNameDefinition tagDef : TagNameDefinition.getTagNameDefinitions()) { if (tagDef.isNotable()) { tagDisplayNames.add(tagDef.getDisplayName()); } @@ -203,8 +203,8 @@ public class TagsManager implements Closeable { * map. */ Map tagNames = new HashMap<>(); - Set customTypes = TagNameDefiniton.getTagNameDefinitions(); - for (TagNameDefiniton tagType : customTypes) { + Set customTypes = TagNameDefinition.getTagNameDefinitions(); + for (TagNameDefinition tagType : customTypes) { tagNames.put(tagType.getDisplayName(), null); } for (TagName tagName : caseDb.getAllTagNames()) { @@ -268,7 +268,7 @@ public class TagsManager implements Closeable { public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color) throws TagNameAlreadyExistsException, TskCoreException { String knownStatus = ""; if (getNotableTagDisplayNames().contains(displayName)) { - knownStatus = TagNameDefiniton.NOTABLE; + knownStatus = TagNameDefinition.NOTABLE; } return addTagName(displayName, description, color, knownStatus); } @@ -293,9 +293,9 @@ public class TagsManager implements Closeable { public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color, String knownStatus) throws TagNameAlreadyExistsException, TskCoreException { try { TagName tagName = caseDb.addTagName(displayName, description, color); - Set customTypes = TagNameDefiniton.getTagNameDefinitions(); - customTypes.add(new TagNameDefiniton(displayName, description, color, knownStatus)); - TagNameDefiniton.setTagNameDefinitions(customTypes); + Set customTypes = TagNameDefinition.getTagNameDefinitions(); + customTypes.add(new TagNameDefinition(displayName, description, color, knownStatus)); + TagNameDefinition.setTagNameDefinitions(customTypes); return tagName; } catch (TskCoreException ex) { List existingTagNames = caseDb.getAllTagNames(); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties index 7ab2c9b2e4..597e896a2a 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/Bundle.properties @@ -33,9 +33,6 @@ ImportHashDatabaseDialog.bnNewOrganization.text=Add New Organization ImportHashDatabaseDialog.tfDatabaseName.tooltip=Name for this database ImportHashDatabaseDialog.tfDatabaseVersion.tooltip.text=Database Version Number GlobalSettingsPanel.bnImportDatabase.actionCommand= -GlobalSettingsPanel.bnManageTags.actionCommand= -GlobalSettingsPanel.bnManageTags.toolTipText= -GlobalSettingsPanel.bnManageTags.text=Manage Tags GlobalSettingsPanel.tbOops.text= GlobalSettingsPanel.lbDatabaseSettings.text=Database Settings GlobalSettingsPanel.bnImportDatabase.label=Import Hash Database diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form index 49d525511b..b4a50fc91c 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.form @@ -28,7 +28,6 @@ - @@ -48,8 +47,6 @@ - - @@ -193,109 +190,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -415,7 +309,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java index 58eb9fbe40..57c02fc614 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java @@ -57,12 +57,8 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i @Messages({"GlobalSettingsPanel.title=Central Repository Settings", "GlobalSettingsPanel.cbUseCentralRepo.text=Use a central repository", - "GlobalSettingsPanel.pnTagManagement.border.title=Tags", "GlobalSettingsPanel.pnCorrelationProperties.border.title=Correlation Properties", "GlobalSettingsPanel.lbCentralRepository.text=A central repository allows you to correlate files and results between cases.", - "GlobalSettingsPanel.manageTagsTextArea.text=Configure which tag names are associated with notable items. " - + "When these tags are used, the file or result will be recorded in the central repository. " - + "If that file or result is seen again in future cases, it will be flagged.", "GlobalSettingsPanel.correlationPropertiesTextArea.text=Choose which file and result properties to store in the central repository for later correlation.", "GlobalSettingsPanel.organizationPanel.border.title=Organizations", "GlobalSettingsPanel.manageOrganizationButton.text=Manage Organizations", @@ -100,10 +96,6 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i lbDbLocationValue = new javax.swing.JLabel(); cbUseCentralRepo = new javax.swing.JCheckBox(); bnImportDatabase = new javax.swing.JButton(); - pnTagManagement = new javax.swing.JPanel(); - bnManageTags = new javax.swing.JButton(); - manageTagsScrollPane = new javax.swing.JScrollPane(); - manageTagsTextArea = new javax.swing.JTextArea(); tbOops = new javax.swing.JTextField(); pnCorrelationProperties = new javax.swing.JPanel(); bnManageTypes = new javax.swing.JButton(); @@ -189,56 +181,6 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i } }); - pnTagManagement.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.pnTagManagement.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 12))); // NOI18N - pnTagManagement.setPreferredSize(new java.awt.Dimension(674, 97)); - - org.openide.awt.Mnemonics.setLocalizedText(bnManageTags, org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnManageTags.text")); // NOI18N - bnManageTags.setToolTipText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnManageTags.toolTipText")); // NOI18N - bnManageTags.setActionCommand(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.bnManageTags.actionCommand")); // NOI18N - bnManageTags.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bnManageTagsActionPerformed(evt); - } - }); - - manageTagsScrollPane.setBorder(null); - - manageTagsTextArea.setEditable(false); - manageTagsTextArea.setBackground(new java.awt.Color(240, 240, 240)); - manageTagsTextArea.setColumns(20); - manageTagsTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N - manageTagsTextArea.setLineWrap(true); - manageTagsTextArea.setRows(2); - manageTagsTextArea.setText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.manageTagsTextArea.text")); // NOI18N - manageTagsTextArea.setToolTipText(""); - manageTagsTextArea.setWrapStyleWord(true); - manageTagsTextArea.setBorder(null); - manageTagsScrollPane.setViewportView(manageTagsTextArea); - - javax.swing.GroupLayout pnTagManagementLayout = new javax.swing.GroupLayout(pnTagManagement); - pnTagManagement.setLayout(pnTagManagementLayout); - pnTagManagementLayout.setHorizontalGroup( - pnTagManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnTagManagementLayout.createSequentialGroup() - .addContainerGap() - .addGroup(pnTagManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnTagManagementLayout.createSequentialGroup() - .addComponent(bnManageTags) - .addGap(0, 555, Short.MAX_VALUE)) - .addGroup(pnTagManagementLayout.createSequentialGroup() - .addComponent(manageTagsScrollPane) - .addContainerGap()))) - ); - pnTagManagementLayout.setVerticalGroup( - pnTagManagementLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(pnTagManagementLayout.createSequentialGroup() - .addGap(7, 7, 7) - .addComponent(manageTagsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 31, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(bnManageTags, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(8, 8, 8)) - ); - tbOops.setEditable(false); tbOops.setFont(tbOops.getFont().deriveFont(tbOops.getFont().getStyle() | java.awt.Font.BOLD, 12)); tbOops.setText(org.openide.util.NbBundle.getMessage(GlobalSettingsPanel.class, "GlobalSettingsPanel.tbOops.text")); // NOI18N @@ -351,7 +293,6 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i .addComponent(organizationPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(lbCentralRepository, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(pnCorrelationProperties, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(pnTagManagement, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(cbUseCentralRepo, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 186, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(bnImportDatabase, javax.swing.GroupLayout.Alignment.LEADING)) @@ -366,8 +307,6 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(pnDatabaseConfiguration, javax.swing.GroupLayout.PREFERRED_SIZE, 119, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0) - .addComponent(pnTagManagement, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, 0) .addComponent(pnCorrelationProperties, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0) .addComponent(organizationPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) @@ -377,8 +316,6 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i .addComponent(bnImportDatabase) .addContainerGap()) ); - - pnTagManagement.getAccessibleContext().setAccessibleName(""); }// //GEN-END:initComponents private void bnImportDatabaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnImportDatabaseActionPerformed @@ -387,12 +324,6 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i firePropertyChange(OptionsPanelController.PROP_VALID, null, null); }//GEN-LAST:event_bnImportDatabaseActionPerformed - private void bnManageTagsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnManageTagsActionPerformed - store(); - ManageTagsDialog dialog = new ManageTagsDialog(); - firePropertyChange(OptionsPanelController.PROP_VALID, null, null); - }//GEN-LAST:event_bnManageTagsActionPerformed - private void bnManageTypesActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnManageTypesActionPerformed store(); ManageCorrelationPropertiesDialog dialog = new ManageCorrelationPropertiesDialog(); @@ -565,11 +496,8 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i private boolean enableButtonSubComponents(Boolean enable) { boolean ingestRunning = IngestManager.getInstance().isIngestRunning(); pnCorrelationProperties.setEnabled(enable && !ingestRunning); - pnTagManagement.setEnabled(enable && !ingestRunning); bnManageTypes.setEnabled(enable && !ingestRunning); bnImportDatabase.setEnabled(enable && !ingestRunning); - bnManageTags.setEnabled(enable && !ingestRunning); - manageTagsTextArea.setEnabled(enable && !ingestRunning); correlationPropertiesTextArea.setEnabled(enable && !ingestRunning); organizationPanel.setEnabled(enable && !ingestRunning); organizationTextArea.setEnabled(enable && !ingestRunning); @@ -580,7 +508,6 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton bnDbConfigure; private javax.swing.JButton bnImportDatabase; - private javax.swing.JButton bnManageTags; private javax.swing.JButton bnManageTypes; private javax.swing.JCheckBox cbUseCentralRepo; private javax.swing.JScrollPane correlationPropertiesScrollPane; @@ -593,14 +520,11 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i private javax.swing.JLabel lbDbPlatformTypeLabel; private javax.swing.JLabel lbDbPlatformValue; private javax.swing.JButton manageOrganizationButton; - private javax.swing.JScrollPane manageTagsScrollPane; - private javax.swing.JTextArea manageTagsTextArea; private javax.swing.JPanel organizationPanel; private javax.swing.JScrollPane organizationScrollPane; private javax.swing.JTextArea organizationTextArea; private javax.swing.JPanel pnCorrelationProperties; private javax.swing.JPanel pnDatabaseConfiguration; - private javax.swing.JPanel pnTagManagement; private javax.swing.JTextField tbOops; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.form b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.form deleted file mode 100755 index f1ad5a38e4..0000000000 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.form +++ /dev/null @@ -1,147 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java deleted file mode 100755 index ff179c3032..0000000000 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Central Repository - * - * Copyright 2015-2017 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.centralrepository.optionspanel; - -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.Toolkit; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.logging.Level; -import javax.swing.JFrame; -import javax.swing.table.DefaultTableModel; -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; -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.services.TagsManager; -import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; -import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; -import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute; -import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.BlackboardArtifactTag; -import org.sleuthkit.datamodel.TagName; -import org.sleuthkit.datamodel.ContentTag; -import org.sleuthkit.datamodel.TskData; - -/** - * Instances of this class allow a user to select an existing hash database and - * add it to the set of hash databases used to classify files as unknown, known, - * or notable. - */ -final class ManageTagsDialog extends javax.swing.JDialog { - - private static final Logger LOGGER = Logger.getLogger(ManageTagsDialog.class.getName()); - - /** - * Displays a dialog that allows a user to select an existing hash database - * and add it to the set of hash databases used to classify files as - * unknown, known, or notable. - */ - @Messages({"ManageTagDialog.title=Manage Tags", - "ManageTagDialog.tagInfo.text=Select the tags that cause files and results to be recorded in the central repository. Additional tags can be created in the Tags options panel."}) - ManageTagsDialog() { - super((JFrame) WindowManager.getDefault().getMainWindow(), - Bundle.ManageTagDialog_title(), - true); // NON-NLS - initComponents(); - customizeComponents(); - setupHelpTextArea(); - display(); - } - - - @Messages({"ManageTagsDialog.init.failedConnection.msg=Cannot connect to central cepository.", - "ManageTagsDialog.init.failedGettingTags.msg=Unable to retrieve list of tags.", - "ManageTagsDialog.tagColumn.header.text=Tags", - "ManageTagsDialog.notableColumn.header.text=Notable"}) - private void setupHelpTextArea() { - helpTextArea.setText(Bundle.ManageTagDialog_tagInfo_text()); - } - - private void customizeComponents() { - lbWarnings.setText(""); - EamDb dbManager; - try { - dbManager = EamDb.getInstance(); - } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Failed to connect to central repository database."); - lbWarnings.setText(Bundle.ManageTagsDialog_init_failedConnection_msg()); - return; - } - List badTags = TagsManager.getNotableTagDisplayNames(); - - List tagNames = new ArrayList<>(); - try { - tagNames.addAll(TagsManager.getTagDisplayNames()); - } catch (TskCoreException ex) { - LOGGER.log(Level.WARNING, "Could not get list of tags in case", ex); - lbWarnings.setText(Bundle.ManageTagsDialog_init_failedGettingTags_msg()); - } - - Collections.sort(tagNames); - - DefaultTableModel model = (DefaultTableModel) tblTagNames.getModel(); - model.setColumnIdentifiers(new String[] {Bundle.ManageTagsDialog_tagColumn_header_text(), Bundle.ManageTagsDialog_notableColumn_header_text()}); - for (String tagName : tagNames) { - boolean enabled = badTags.contains(tagName); - model.addRow(new Object[]{tagName, enabled}); - } - CheckBoxModelListener listener = new CheckBoxModelListener(this); - model.addTableModelListener(listener); - } - - private void display() { - Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); - setLocation((screenDimension.width - getSize().width) / 2, (screenDimension.height - getSize().height) / 2); - setVisible(true); - } - - /** - * 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 - * regenerated by the Form Editor. - */ - @SuppressWarnings({"unchecked", "rawtypes"}) - // //GEN-BEGIN:initComponents - private void initComponents() { - - buttonGroup1 = new javax.swing.ButtonGroup(); - okButton = new javax.swing.JButton(); - cancelButton = new javax.swing.JButton(); - tagScrollArea = new javax.swing.JScrollPane(); - tblTagNames = new javax.swing.JTable(); - lbWarnings = new javax.swing.JLabel(); - helpScrollPane = new javax.swing.JScrollPane(); - helpTextArea = new javax.swing.JTextArea(); - - setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - - org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(ManageTagsDialog.class, "ManageTagsDialog.okButton.text")); // NOI18N - okButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - okButtonActionPerformed(evt); - } - }); - - org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(ManageTagsDialog.class, "ManageTagsDialog.cancelButton.text")); // NOI18N - cancelButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - cancelButtonActionPerformed(evt); - } - }); - - tblTagNames.setModel(new javax.swing.table.DefaultTableModel( - new Object [][] { - - }, - new String [] { - "", "" - } - ) { - Class[] types = new Class [] { - java.lang.Object.class, java.lang.Boolean.class - }; - boolean[] canEdit = new boolean [] { - false, true - }; - - public Class getColumnClass(int columnIndex) { - return types [columnIndex]; - } - - public boolean isCellEditable(int rowIndex, int columnIndex) { - return canEdit [columnIndex]; - } - }); - tagScrollArea.setViewportView(tblTagNames); - - helpScrollPane.setBorder(null); - - helpTextArea.setEditable(false); - helpTextArea.setBackground(new java.awt.Color(240, 240, 240)); - helpTextArea.setColumns(20); - helpTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N - helpTextArea.setLineWrap(true); - helpTextArea.setRows(3); - helpTextArea.setWrapStyleWord(true); - helpTextArea.setBorder(null); - helpTextArea.setFocusable(false); - helpScrollPane.setViewportView(helpTextArea); - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(0, 0, Short.MAX_VALUE) - .addComponent(okButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cancelButton)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(helpScrollPane, javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(tagScrollArea, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE) - .addComponent(lbWarnings, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGap(2, 2, 2))) - .addContainerGap()) - ); - - layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {cancelButton, okButton}); - - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addContainerGap() - .addComponent(helpScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 42, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, 0) - .addComponent(tagScrollArea, javax.swing.GroupLayout.DEFAULT_SIZE, 341, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(lbWarnings, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(okButton) - .addComponent(cancelButton)) - .addContainerGap()) - ); - - pack(); - }// //GEN-END:initComponents - - private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed - dispose(); - }//GEN-LAST:event_cancelButtonActionPerformed - - - private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed - if (setBadTags()) { - dispose(); - } - }//GEN-LAST:event_okButtonActionPerformed - - private boolean setBadTags() { - List badTags = new ArrayList<>(); - - DefaultTableModel model = (DefaultTableModel) tblTagNames.getModel(); - for (int i = 0; i < model.getRowCount(); ++i) { - String tagName = (String) model.getValueAt(i, 0); - boolean enabled = (boolean) model.getValueAt(i, 1); - - if (enabled) { - badTags.add(tagName); - } - } - try { - EamDb dbManager = EamDb.getInstance(); - dbManager.saveSettings(); - } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Failed to connect to central repository database."); // NON-NLS - lbWarnings.setText(Bundle.ManageTagsDialog_init_failedConnection_msg()); - return false; - } - return true; - } - - /** - * If the user sets a tag to "Notable", give them the option to update - * any existing tagged items (in the current case only) in the central repo. - */ - public class CheckBoxModelListener implements TableModelListener { - @Messages({"ManageTagsDialog.updateCurrentCase.msg=Mark as notable any files/results in the current case that have this tag?", - "ManageTagsDialog.updateCurrentCase.title=Update current case?", - "ManageTagsDialog.updateCurrentCase.error=Error updating existing central repository entries"}) - - javax.swing.JDialog dialog; - public CheckBoxModelListener(javax.swing.JDialog dialog){ - this.dialog = dialog; - } - - @Override - public void tableChanged(TableModelEvent e) { - int row = e.getFirstRow(); - int column = e.getColumn(); - if (column == 1) { - DefaultTableModel model = (DefaultTableModel) e.getSource(); - String tagName = (String) model.getValueAt(row, 0); - Boolean checked = (Boolean) model.getValueAt(row, column); - if (checked) { - - // Don't do anything if there's no case open - if(Case.isCaseOpen()){ - int dialogButton = JOptionPane.YES_NO_OPTION; - int dialogResult = JOptionPane.showConfirmDialog ( - null, - Bundle.ManageTagsDialog_updateCurrentCase_msg(), - Bundle.ManageTagsDialog_updateCurrentCase_title(), - dialogButton); - if(dialogResult == JOptionPane.YES_OPTION){ - try{ - dialog.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - setArtifactsKnownBadByTag(tagName, Case.getCurrentCase()); - } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Failed to apply notable status to artifacts in current case", ex); - JOptionPane.showMessageDialog(null, Bundle.ManageTagsDialog_updateCurrentCase_error()); - } finally { - dialog.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - } - } - } - } - } - } - } - - /** - * Set knownBad status for all files/artifacts in the given case that - * are tagged with the given tag name. - * Files/artifacts that are not already in the database will be added. - * @param tagName The name of the tag to search for - * @param curCase The case to search in - */ - public void setArtifactsKnownBadByTag(String tagNameString, Case curCase) throws EamDbException{ - try{ - TagName tagName = curCase.getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(tagNameString); - - // First find any matching artifacts - List artifactTags = curCase.getSleuthkitCase().getBlackboardArtifactTagsByTagName(tagName); - - for(BlackboardArtifactTag bbTag:artifactTags){ - List convertedArtifacts = EamArtifactUtil.getCorrelationAttributeFromBlackboardArtifact(bbTag.getArtifact(), true, true); - for (CorrelationAttribute eamArtifact : convertedArtifacts) { - EamDb.getInstance().setArtifactInstanceKnownStatus(eamArtifact,TskData.FileKnown.BAD); - } - } - - // Now search for files - List fileTags = curCase.getSleuthkitCase().getContentTagsByTagName(tagName); - for(ContentTag contentTag:fileTags){ - final CorrelationAttribute eamArtifact = EamArtifactUtil.getEamArtifactFromContent(contentTag.getContent(), - TskData.FileKnown.BAD, ""); - if(eamArtifact != null){ - EamDb.getInstance().setArtifactInstanceKnownStatus(eamArtifact, TskData.FileKnown.BAD); - } - } - } catch (TskCoreException ex){ - throw new EamDbException("Error updating artifacts", ex); - } - - } - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.ButtonGroup buttonGroup1; - private javax.swing.JButton cancelButton; - private javax.swing.JScrollPane helpScrollPane; - private javax.swing.JTextArea helpTextArea; - private javax.swing.JLabel lbWarnings; - private javax.swing.JButton okButton; - private javax.swing.JScrollPane tagScrollArea; - private javax.swing.JTable tblTagNames; - // End of variables declaration//GEN-END:variables -} From ebf34dab14ad4517b10af4b370b819bb7ee65ac9 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 7 Nov 2017 14:15:49 -0500 Subject: [PATCH 02/90] Allow user to import Encase hashsets into central repo --- .../ImportCentralRepoDbProgressDialog.java | 179 +++++++++++++++++- 1 file changed, 177 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 597cb8c39d..969e84b0b8 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -26,6 +26,7 @@ import java.io.File; import java.io.FileReader; import java.util.HashSet; import java.util.Set; +import java.util.List; import java.util.logging.Level; import javax.swing.JFrame; import javax.swing.SwingWorker; @@ -76,14 +77,24 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P bnOk.setEnabled(false); } + @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.unknownFormat.message=Hash set to import is an unknown format"}) void importFile(String hashSetName, String version, int orgId, boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, boolean readOnly, String importFileName){ setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); File importFile = new File(importFileName); - worker = new ImportIDXWorker(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages, - knownFilesType, readOnly, importFile); + if(importFileName.endsWith(".idx")){ // < need case insensitive + worker = new ImportIDXWorker(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages, + knownFilesType, readOnly, importFile); + } else if(importFileName.endsWith(".hash")){ // < need case insensitive + worker = new ImportEncaseWorker(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages, + knownFilesType, readOnly, importFile); + } else { + // We've gotten here with a format that can't be processed + JOptionPane.showMessageDialog(null, Bundle.ImportCentralRepoDbProgressDialog_unknownFormat_message()); + return; + } worker.addPropertyChangeListener(this); worker.execute(); @@ -131,6 +142,170 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P HashDbManager.HashDatabase getDatabase(); } + class ImportEncaseWorker extends SwingWorker implements CentralRepoImportWorker{ + private final int HASH_IMPORT_THRESHOLD = 10000; + private final String hashSetName; + private final String version; + private final int orgId; + private final boolean searchDuringIngest; + private final boolean sendIngestMessages; + private final HashDbManager.HashDb.KnownFilesType knownFilesType; + private final boolean readOnly; + private final File importFile; + private final long totalLines; + private int crIndex = -1; + private HashDbManager.CentralRepoHashDb newHashDb = null; + private final AtomicLong numLines = new AtomicLong(); + + ImportEncaseWorker(String hashSetName, String version, int orgId, + boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, + boolean readOnly, File importFile){ + + this.hashSetName = hashSetName; + this.version = version; + this.orgId = orgId; + this.searchDuringIngest = searchDuringIngest; + this.sendIngestMessages = sendIngestMessages; + this.knownFilesType = knownFilesType; + this.readOnly = readOnly; + this.importFile = importFile; + this.numLines.set(0); + + this.totalLines = getEstimatedTotalHashes(); + } + + /** + * Encase files have a 0x480 byte header, then each hash takes 18 bytes + * @return Approximate number of hashes in the file + */ + final long getEstimatedTotalHashes(){ + long fileSize = importFile.length(); + if(fileSize < 0x492){ + return 1; // There's room for at most one hash + } + return ((fileSize - 0x492) / 18); + } + + @Override + public HashDbManager.HashDatabase getDatabase(){ + return newHashDb; + } + + @Override + public long getLinesProcessed(){ + return numLines.get(); + } + + @Override + public int getProgressPercentage(){ + return this.getProgress(); + } + + @Override + protected Void doInBackground() throws Exception { + + EncaseHashSetParser encaseParser = new EncaseHashSetParser(this.importFile.getAbsolutePath()); + + TskData.FileKnown knownStatus; + if (knownFilesType.equals(HashDbManager.HashDb.KnownFilesType.KNOWN)) { + knownStatus = TskData.FileKnown.KNOWN; + } else { + knownStatus = TskData.FileKnown.BAD; + } + + // Create an empty hashset in the central repository + crIndex = EamDb.getInstance().newReferenceSet(orgId, hashSetName, version, knownStatus, readOnly); + + EamDb dbManager = EamDb.getInstance(); + CorrelationAttribute.Type contentType = dbManager.getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); // get "FILES" type + + Set globalInstances = new HashSet<>(); + + while (! encaseParser.doneReading()) { + if(isCancelled()){ + return null; + } + + String newHash = encaseParser.getNextHash(); + + if(newHash != null){ + EamGlobalFileInstance eamGlobalFileInstance = new EamGlobalFileInstance( + crIndex, + newHash, + knownStatus, + ""); + + globalInstances.add(eamGlobalFileInstance); + numLines.incrementAndGet(); + + if(numLines.get() % HASH_IMPORT_THRESHOLD == 0){ + dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType); + globalInstances.clear(); + + int progress = (int)(numLines.get() * 100 / totalLines); + if(progress < 100){ + this.setProgress(progress); + } else { + this.setProgress(99); + } + } + } + } + + dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType); + this.setProgress(100); + return null; + } + + private void deleteIncompleteSet(int crIndex){ + if(crIndex >= 0){ + + // This can be slow on large reference sets + Executors.newSingleThreadExecutor().execute(new Runnable() { + @Override + public void run() { + try{ + EamDb.getInstance().deleteReferenceSet(crIndex); + } catch (EamDbException ex2){ + Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error deleting incomplete hash set from central repository", ex2); + } + } + }); + } + } + + @Override + protected void done() { + + if(isCancelled()){ + // If the user hit cancel, delete this incomplete hash set from the central repo + deleteIncompleteSet(crIndex); + return; + } + + try { + get(); + try{ + newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetName, version, + crIndex, + searchDuringIngest, sendIngestMessages, knownFilesType, readOnly); + } catch (TskCoreException ex){ + JOptionPane.showMessageDialog(null, Bundle.ImportCentralRepoDbProgressDialog_addDbError_message()); + Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error adding imported hash set", ex); + } + } catch (Exception ex) { + // Delete this incomplete hash set from the central repo + if(crIndex >= 0){ + try{ + EamDb.getInstance().deleteReferenceSet(crIndex); + } catch (EamDbException ex2){ + Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error deleting incomplete hash set from central repository", ex); + } + } + } + } + } + class ImportIDXWorker extends SwingWorker implements CentralRepoImportWorker{ private final int HASH_IMPORT_THRESHOLD = 10000; From 6494a23deeff2507c2215236fbfa01203788f04e Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 7 Nov 2017 14:19:05 -0500 Subject: [PATCH 03/90] Adding encase parser file --- .../hashdatabase/EncaseHashSetParser.java | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java new file mode 100644 index 0000000000..df9d78b7a3 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java @@ -0,0 +1,167 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011 - 2017 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.modules.hashdatabase; + +import java.io.InputStream; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.lang.StringBuilder; +import java.util.Arrays; +import java.util.List; +import java.util.ArrayList; +import java.util.logging.Level; +import javax.swing.JOptionPane; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.core.RuntimeProperties; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.TskCoreException; + +class EncaseHashSetParser { + final byte[] encaseHeader = {(byte)0x48, (byte)0x41, (byte)0x53, (byte)0x48, (byte)0x0d, (byte)0x0a, (byte)0xff, (byte)0x00, + (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00}; + InputStream inputStream; + final int expectedHashes; + int totalHashesRead = 0; + + /** + * Opens the import file and parses the header. + * @param filename The Encase hashset + * @throws TskCoreException There was an error opening/reading the file or it is not the correct format + */ + @NbBundle.Messages({"EncaseHashSetParser.fileOpenError.text=Error reading import file", + "EncaseHashSetParser.wrongFormat.text=Hashset is not Encase format"}) + EncaseHashSetParser(String filename) throws TskCoreException{ + try{ + inputStream = new BufferedInputStream(new FileInputStream(filename)); + + // Read in and test the 16 byte header + byte[] header = new byte[16]; + readBuffer(header, 16); + if(! Arrays.equals(header, encaseHeader)){ + displayError(NbBundle.getMessage(this.getClass(), + "EncaseHashSetParser.wrongFormat.text")); + close(); + throw new TskCoreException("File " + filename + " does not have an Encase header"); + } + + // Read in the expected number of hashes + byte[] sizeBuffer = new byte[4]; + readBuffer(sizeBuffer, 4); + expectedHashes = ((sizeBuffer[3] & 0xff) << 24) | ((sizeBuffer[2] & 0xff) << 16) + | ((sizeBuffer[1] & 0xff) << 8) | (sizeBuffer[0] & 0xff); + + // Read in a bunch of nulls + byte[] filler = new byte[0x3f4]; + readBuffer(filler, 0x3f4); + + // Read in the hash set name + byte[] nameBuffer = new byte[0x50]; + readBuffer(nameBuffer, 0x50); + + // Read in the hash set type + byte[] typeBuffer = new byte[0x28]; + readBuffer(typeBuffer, 0x28); + + } catch (IOException ex){ + displayError(NbBundle.getMessage(this.getClass(), + "EncaseHashSetParser.fileOpenError.text")); + close(); + throw new TskCoreException("Error reading " + filename, ex); + } catch (TskCoreException ex){ + close(); + throw ex; + } + } + + int getExpectedHashes(){ + return expectedHashes; + } + + synchronized boolean doneReading(){ + if(inputStream == null){ + return true; + } + + return(totalHashesRead >= expectedHashes); + } + + synchronized String getNextHash() throws TskCoreException{ + if(inputStream == null){ + return null; + } + + byte[] hashBytes = new byte[16]; + byte[] divider = new byte[2]; + try{ + + readBuffer(hashBytes, 16); + readBuffer(divider, 2); + + StringBuilder sb = new StringBuilder(); + for (byte b : hashBytes) { + sb.append(String.format("%02x", b)); + } + + totalHashesRead++; + return sb.toString(); + } catch (IOException ex){ + // Log it and return what we've got + Logger.getLogger(EncaseHashSetParser.class.getName()).log(Level.SEVERE, "Ran out of data while reading Encase hash sets", ex); + close(); + throw new TskCoreException("Error reading hash", ex); + } + } + + synchronized final void close(){ + if(inputStream != null){ + try{ + inputStream.close(); + } catch (IOException ex){ + Logger.getLogger(EncaseHashSetParser.class.getName()).log(Level.SEVERE, "Error closing Encase hash set", ex); + } finally { + inputStream = null; + } + } + } + + @NbBundle.Messages({"EncaseHashSetParser.outOfData.text=Ran out of data while parsing file"}) + private synchronized void readBuffer(byte[] buffer, int length) throws TskCoreException, IOException { + if(inputStream == null){ + throw new TskCoreException("readBuffer called on null inputStream"); + } + if(length != inputStream.read(buffer)){ + displayError(NbBundle.getMessage(this.getClass(), + "EncaseHashSetParser.outOfData.text")); + close(); + throw new TskCoreException("Ran out of data while parsing Encase file"); + } + } + + @NbBundle.Messages({"EncaseHashSetParser.error.title=Error importing Encase hashset"}) + private void displayError(String errorText){ + if(RuntimeProperties.runningWithGUI()){ + JOptionPane.showMessageDialog(null, + errorText, + NbBundle.getMessage(this.getClass(), + "EncaseHashSetParser.error.title"), + JOptionPane.ERROR_MESSAGE); + } + } +} From d49b1667afc9c61fc3aecf8537edf8506e1a0745 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 8 Nov 2017 09:58:03 -0500 Subject: [PATCH 04/90] 3201 disable tag deletion and editing during ingest --- .../casemodule/services/Bundle.properties | 7 +- .../casemodule/services/Bundle_ja.properties | 3 +- .../casemodule/services/TagOptionsPanel.form | 44 ++++++++-- .../casemodule/services/TagOptionsPanel.java | 86 +++++++++++++++---- 4 files changed, 112 insertions(+), 28 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties index 6242c6793d..74938a677a 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties @@ -1,7 +1,7 @@ OptionsCategory_Name_TagNamesOptions=Tags OptionsCategory_TagNames=TagNames Blackboard.unableToIndexArtifact.error.msg=Unable to index blackboard artifact {0} -NewTagNameDialog.title.text=New Tag Name +NewTagNameDialog.title.text=New Tag NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.message=Tag name may not contain any of the following symbols\: \\ \: * ? " < > | , ; NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.title=Invalid character in tag name NewTagNameDialog.JOptionPane.tagNameEmpty.message=The tag name cannot be empty @@ -14,9 +14,10 @@ TagNameDialog.descriptionLabel.text=Description: TagNameDialog.okButton.text=OK TagNameDialog.cancelButton.text=Cancel TagNameDialog.tagNameTextField.text= -TagNameDialog.newTagNameLabel.text=New Tag Name: +TagNameDialog.newTagNameLabel.text=Name: TagNameDialog.notableCheckbox.text=Tag indicates item is notable. TagOptionsPanel.isNotableLabel.text=Tag indicates item is notable: TagOptionsPanel.notableYesOrNoLabel.text= TagOptionsPanel.descriptionLabel.text=Tag Description: -TagOptionsPanel.jTextArea1.text=Autopsy keeps a list of the tag names you have created in the past. Add more or delete them here. +TagOptionsPanel.jTextArea1.text=Create and manage tags, which can be applied to files and results in the case. Notable tags will cause items tagged with them to be flagged as notable when using a central repository. +TagOptionsPanel.ingestRunningWarningLabel.text=Cannot make changes to existing tags when ingest is running! diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties index a27e3ca586..41e871691b 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle_ja.properties @@ -1,2 +1,3 @@ TagsManager.predefTagNames.bookmark.text=\u30d6\u30c3\u30af\u30de\u30fc\u30af -Blackboard.unableToIndexArtifact.error.msg=blackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8{0}\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 \ No newline at end of file +Blackboard.unableToIndexArtifact.error.msg=blackboard\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8{0}\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 +TagOptionsPanel.ingestRunningWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3092\u5b9f\u884c\u4e2d\u306b\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7\u5b9a\u7fa9\u3092\u5909\u66f4\u3067\u304d\u307e\u305b\u3093\uff01 diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form index c2e5c06cab..541bd90cda 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form @@ -203,6 +203,9 @@
+ + + @@ -260,18 +263,24 @@ - - + + - - - - - + + + + + + + + + + + - + @@ -287,7 +296,9 @@ - + + + @@ -339,6 +350,21 @@ + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java index da774f7161..ec2caa8d20 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java @@ -18,6 +18,9 @@ */ package org.sleuthkit.autopsy.casemodule.services; +import java.awt.EventQueue; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.util.Set; import java.util.TreeSet; import javax.swing.DefaultListModel; @@ -26,6 +29,7 @@ import javax.swing.event.ListSelectionEvent; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; +import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.datamodel.TagName; /** @@ -38,6 +42,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { private static final TagName.HTML_COLOR DEFAULT_COLOR = TagName.HTML_COLOR.NONE; private final DefaultListModel tagTypesListModel; private Set tagTypes; + private IngestJobEventPropertyChangeListener ingestJobEventsListener; /** * Creates new form TagsManagerOptionsPanel @@ -54,6 +59,18 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { tagNamesList.addListSelectionListener((ListSelectionEvent event) -> { updatePanel(); }); + addIngestJobEventsListener(); + } + + /** + * Add a property change listener that listens to ingest job events to + * disable the buttons on the panel if ingest is running. This is done to + * prevent changes to user-defined types while the type definitions are in + * use. + */ + private void addIngestJobEventsListener() { + ingestJobEventsListener = new IngestJobEventPropertyChangeListener(); + IngestManager.getInstance().addIngestJobEventListener(ingestJobEventsListener); } /** @@ -83,6 +100,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { descriptionTextArea = new javax.swing.JTextArea(); isNotableLabel = new javax.swing.JLabel(); notableYesOrNoLabel = new javax.swing.JLabel(); + ingestRunningWarningLabel = new javax.swing.JLabel(); jPanel1.setPreferredSize(new java.awt.Dimension(750, 490)); @@ -119,6 +137,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { } }); + editTagNameButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/edit-tag.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(editTagNameButton, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.editTagNameButton.text")); // NOI18N editTagNameButton.setMaximumSize(new java.awt.Dimension(111, 25)); editTagNameButton.setMinimumSize(new java.awt.Dimension(111, 25)); @@ -202,6 +221,10 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { org.openide.awt.Mnemonics.setLocalizedText(notableYesOrNoLabel, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.notableYesOrNoLabel.text")); // NOI18N + ingestRunningWarningLabel.setFont(ingestRunningWarningLabel.getFont().deriveFont(ingestRunningWarningLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); + ingestRunningWarningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/filetypeid/warning16.png"))); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(ingestRunningWarningLabel, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.ingestRunningWarningLabel.text")); // NOI18N + javax.swing.GroupLayout tagTypesAdditionalPanelLayout = new javax.swing.GroupLayout(tagTypesAdditionalPanel); tagTypesAdditionalPanel.setLayout(tagTypesAdditionalPanelLayout); tagTypesAdditionalPanelLayout.setHorizontalGroup( @@ -210,11 +233,15 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { .addContainerGap() .addGroup(tagTypesAdditionalPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(descriptionScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 361, Short.MAX_VALUE) - .addComponent(descriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(tagTypesAdditionalPanelLayout.createSequentialGroup() - .addComponent(isNotableLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(notableYesOrNoLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGroup(tagTypesAdditionalPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(descriptionLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 92, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(tagTypesAdditionalPanelLayout.createSequentialGroup() + .addComponent(isNotableLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(notableYesOrNoLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(ingestRunningWarningLabel)) + .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); tagTypesAdditionalPanelLayout.setVerticalGroup( @@ -228,7 +255,9 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { .addGroup(tagTypesAdditionalPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(isNotableLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(notableYesOrNoLabel)) - .addContainerGap(351, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 304, Short.MAX_VALUE) + .addComponent(ingestRunningWarningLabel) + .addGap(31, 31, 31)) ); jSplitPane1.setRightComponent(tagTypesAdditionalPanel); @@ -323,6 +352,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { private javax.swing.JScrollPane descriptionScrollPane; private javax.swing.JTextArea descriptionTextArea; private javax.swing.JButton editTagNameButton; + private javax.swing.JLabel ingestRunningWarningLabel; private javax.swing.JLabel isNotableLabel; private javax.swing.JPanel jPanel1; private javax.swing.JScrollPane jScrollPane1; @@ -371,28 +401,54 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { * component. */ private void updatePanel() { + boolean ingestIsRunning = IngestManager.getInstance().isIngestRunning(); /* * Only enable the delete button when there is a tag type selected in * the tag types JList. */ + ingestRunningWarningLabel.setVisible(ingestIsRunning); boolean isSelected = tagNamesList.getSelectedIndex() != -1; - editTagNameButton.setEnabled(isSelected); - boolean enableDelete = isSelected && !TagNameDefinition.STANDARD_TAG_DISPLAY_NAMES.contains(tagNamesList.getSelectedValue().getDisplayName()); + boolean enableEdit = !ingestIsRunning && isSelected; + editTagNameButton.setEnabled(enableEdit); + boolean enableDelete = enableEdit && !TagNameDefinition.STANDARD_TAG_DISPLAY_NAMES.contains(tagNamesList.getSelectedValue().getDisplayName()); deleteTagNameButton.setEnabled(enableDelete); - if (isSelected){ - + if (isSelected) { + descriptionTextArea.setText(tagNamesList.getSelectedValue().getDescription()); - if (tagNamesList.getSelectedValue().isNotable()){ + if (tagNamesList.getSelectedValue().isNotable()) { notableYesOrNoLabel.setText("Yes"); + } else { + notableYesOrNoLabel.setText("No"); } - else { - notableYesOrNoLabel.setText("No"); - } - } - else { + } else { descriptionTextArea.setText(""); notableYesOrNoLabel.setText(""); } } + /** + * @inheritDoc + */ + @Override + @SuppressWarnings("FinalizeDeclaration") + protected void finalize() throws Throwable { + IngestManager.getInstance().removeIngestJobEventListener(ingestJobEventsListener); + super.finalize(); + } + + /** + * A property change listener that listens to ingest job events. + */ + private class IngestJobEventPropertyChangeListener implements PropertyChangeListener { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + updatePanel(); + } + }); + } + } } From d9e97d1b94c0ba514621f5e6ec42307ab216c53c Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Wed, 8 Nov 2017 12:08:52 -0500 Subject: [PATCH 05/90] Finished encase hash set importing --- .../HashDbImportDatabaseDialog.java | 4 +-- .../ImportCentralRepoDbProgressDialog.java | 30 ++++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index 66037cccf9..92e662f43e 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -90,11 +90,11 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { fileChooser.setMultiSelectionEnabled(false); } - @NbBundle.Messages({"HashDbImportDatabaseDialog.centralRepoExtFilter.text=Hash Database File (.idx only)"}) + @NbBundle.Messages({"HashDbImportDatabaseDialog.centralRepoExtFilter.text=Hash Database File (.idx or .hash only)"}) private void updateFileChooserFilter() { fileChooser.resetChoosableFileFilters(); if(centralRepoRadioButton.isSelected()){ - String[] EXTENSION = new String[]{"idx"}; //NON-NLS + String[] EXTENSION = new String[]{"hash", "Hash", "idx"}; //NON-NLS FileNameExtensionFilter filter = new FileNameExtensionFilter( NbBundle.getMessage(this.getClass(), "HashDbImportDatabaseDialog.centralRepoExtFilter.text"), EXTENSION); fileChooser.setFileFilter(filter); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 969e84b0b8..8f83a5e3b4 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.modules.hashdatabase; +import java.awt.Color; import java.awt.Cursor; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; @@ -84,10 +85,10 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); File importFile = new File(importFileName); - if(importFileName.endsWith(".idx")){ // < need case insensitive + if(importFileName.toLowerCase().endsWith(".idx")){ worker = new ImportIDXWorker(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages, knownFilesType, readOnly, importFile); - } else if(importFileName.endsWith(".hash")){ // < need case insensitive + } else if(importFileName.toLowerCase().endsWith(".hash")){ worker = new ImportEncaseWorker(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages, knownFilesType, readOnly, importFile); } else { @@ -123,8 +124,14 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P bnCancel.setEnabled(false); bnOk.setEnabled(true); - progressBar.setValue(progressBar.getMaximum()); - lbProgress.setText(getProgressString()); + if(worker.getError().isEmpty()){ + progressBar.setValue(progressBar.getMaximum()); + lbProgress.setText(getProgressString()); + } else { + progressBar.setValue(0); + lbProgress.setForeground(Color.red); + lbProgress.setText(worker.getError()); + } } } @@ -140,6 +147,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P int getProgressPercentage(); long getLinesProcessed(); HashDbManager.HashDatabase getDatabase(); + String getError(); } class ImportEncaseWorker extends SwingWorker implements CentralRepoImportWorker{ @@ -156,6 +164,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P private int crIndex = -1; private HashDbManager.CentralRepoHashDb newHashDb = null; private final AtomicLong numLines = new AtomicLong(); + private String errorString = ""; ImportEncaseWorker(String hashSetName, String version, int orgId, boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, @@ -201,6 +210,11 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P return this.getProgress(); } + @Override + public String getError(){ + return errorString; + } + @Override protected Void doInBackground() throws Exception { @@ -274,6 +288,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } } + @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.importError=Error importing hash set"}) @Override protected void done() { @@ -302,6 +317,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error deleting incomplete hash set from central repository", ex); } } + errorString = Bundle.ImportCentralRepoDbProgressDialog_importError(); } } } @@ -321,6 +337,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P private int crIndex = -1; private HashDbManager.CentralRepoHashDb newHashDb = null; private final AtomicLong numLines = new AtomicLong(); + private String errorString = ""; ImportIDXWorker(String hashSetName, String version, int orgId, boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, @@ -365,6 +382,11 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P return this.getProgress(); } + @Override + public String getError(){ + return errorString; + } + @Override protected Void doInBackground() throws Exception { From feb12e304b2a7e15a6467d0db75f6220fb51e3ed Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 8 Nov 2017 17:18:22 -0500 Subject: [PATCH 06/90] 3201 fix title for Edit Tag dialog --- .../casemodule/services/Bundle.properties | 10 +++++----- .../casemodule/services/TagNameDialog.java | 20 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties index 74938a677a..4cca7e78d6 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties @@ -1,11 +1,11 @@ OptionsCategory_Name_TagNamesOptions=Tags OptionsCategory_TagNames=TagNames Blackboard.unableToIndexArtifact.error.msg=Unable to index blackboard artifact {0} -NewTagNameDialog.title.text=New Tag -NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.message=Tag name may not contain any of the following symbols\: \\ \: * ? " < > | , ; -NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.title=Invalid character in tag name -NewTagNameDialog.JOptionPane.tagNameEmpty.message=The tag name cannot be empty -NewTagNameDialog.JOptionPane.tagNameEmpty.title=Empty tag name +TagNameDialog.title.text=New Tag +TagNameDialog.JOptionPane.tagNameIllegalCharacters.message=Tag name may not contain any of the following symbols\: \\ \: * ? " < > | , ; +TagNameDialog.JOptionPane.tagNameIllegalCharacters.title=Invalid character in tag name +TagNameDialog.JOptionPane.tagNameEmpty.message=The tag name cannot be empty +TagNameDialog.JOptionPane.tagNameEmpty.title=Empty tag name TagOptionsPanel.tagTypesListLabel.text=Tag Names: TagOptionsPanel.deleteTagNameButton.text=Delete Tag TagOptionsPanel.newTagNameButton.text=New Tag diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java index e79004af6e..e310c066e5 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.casemodule.services; import java.awt.BorderLayout; -import java.awt.Color; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.event.WindowAdapter; @@ -29,7 +28,7 @@ import javax.swing.JOptionPane; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.openide.util.NbBundle; -import org.sleuthkit.datamodel.TskData; +import org.openide.util.NbBundle.Messages; final class TagNameDialog extends javax.swing.JDialog { @@ -47,15 +46,16 @@ final class TagNameDialog extends javax.swing.JDialog { * Creates a new NewUserTagNameDialog dialog. */ TagNameDialog() { - super(new JFrame(NbBundle.getMessage(TagNameDialog.class, "NewTagNameDialog.title.text")), - NbBundle.getMessage(TagNameDialog.class, "NewTagNameDialog.title.text"), true); + super(new JFrame(NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.title.text")), + NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.title.text"), true); initComponents(); this.display(); } + @Messages({"TagNameDialog.editTitle.text=Edit Tag"}) TagNameDialog(TagNameDefinition tagNameToEdit) { - super(new JFrame("Edit 1"), - "Edit 2", true); + super(new JFrame(NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.editTitle.text")), + NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.editTitle.text"), true); initComponents(); tagNameTextField.setText(tagNameToEdit.getDisplayName()); descriptionTextArea.setText(tagNameToEdit.getDescription()); @@ -131,8 +131,8 @@ final class TagNameDialog extends javax.swing.JDialog { String newTagDisplayName = tagNameTextField.getText().trim(); if (newTagDisplayName.isEmpty()) { JOptionPane.showMessageDialog(null, - NbBundle.getMessage(TagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameEmpty.message"), - NbBundle.getMessage(TagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameEmpty.title"), + NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameEmpty.message"), + NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameEmpty.title"), JOptionPane.ERROR_MESSAGE); return; } @@ -140,8 +140,8 @@ final class TagNameDialog extends javax.swing.JDialog { //if a tag name contains illegal characters and is not the name of one of the standard tags if (TagsManager.containsIllegalCharacters(newTagDisplayName) && !TagNameDefinition.STANDARD_TAG_DISPLAY_NAMES.contains(newTagDisplayName)) { JOptionPane.showMessageDialog(null, - NbBundle.getMessage(TagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.message"), - NbBundle.getMessage(TagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.title"), + NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameIllegalCharacters.message"), + NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameIllegalCharacters.title"), JOptionPane.ERROR_MESSAGE); return; } From 7a3b009747822fcb525095b764ef688393ac6d0f Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Thu, 9 Nov 2017 07:40:28 -0500 Subject: [PATCH 07/90] Refactoring --- .../ImportCentralRepoDbProgressDialog.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 8f83a5e3b4..ef81083e40 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -139,6 +139,55 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P return worker.getLinesProcessed() + Bundle.ImportCentralRepoDbProgressDialog_linesProcessed(); } + abstract class CentralRepoImportWorker2 extends SwingWorker{ + private final int HASH_IMPORT_THRESHOLD = 10000; + private final String hashSetName; + private final String version; + private final int orgId; + private final boolean searchDuringIngest; + private final boolean sendIngestMessages; + private final HashDbManager.HashDb.KnownFilesType knownFilesType; + private final boolean readOnly; + private final File importFile; + private long totalLines; + private int crIndex = -1; + private HashDbManager.CentralRepoHashDb newHashDb = null; + private final AtomicLong numLines = new AtomicLong(); + private String errorString = ""; + + CentralRepoImportWorker2(String hashSetName, String version, int orgId, + boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, + boolean readOnly, File importFile){ + + this.hashSetName = hashSetName; + this.version = version; + this.orgId = orgId; + this.searchDuringIngest = searchDuringIngest; + this.sendIngestMessages = sendIngestMessages; + this.knownFilesType = knownFilesType; + this.readOnly = readOnly; + this.importFile = importFile; + this.numLines.set(0); + } + + HashDbManager.HashDatabase getDatabase(){ + return newHashDb; + } + + long getLinesProcessed(){ + return numLines.get(); + } + + int getProgressPercentage(){ + return this.getProgress(); + } + + String getError(){ + return errorString; + } + + } + private interface CentralRepoImportWorker{ void execute(); From 4b6a9cb4a024f50621bb012f202500b0696e7cba Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Thu, 9 Nov 2017 08:09:16 -0500 Subject: [PATCH 08/90] Refactored the database import workers --- .../ImportCentralRepoDbProgressDialog.java | 324 +++++------------- 1 file changed, 92 insertions(+), 232 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 0389cd3460..281583a4bf 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -111,7 +111,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P return null; } - @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.linesProcessed= lines processed"}) + @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.linesProcessed= hashes processed"}) @Override public void propertyChange(PropertyChangeEvent evt) { @@ -139,23 +139,23 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P return worker.getLinesProcessed() + Bundle.ImportCentralRepoDbProgressDialog_linesProcessed(); } - abstract class CentralRepoImportWorker2 extends SwingWorker{ - private final int HASH_IMPORT_THRESHOLD = 10000; - private final String hashSetName; - private final String version; - private final int orgId; - private final boolean searchDuringIngest; - private final boolean sendIngestMessages; - private final HashDbManager.HashDb.KnownFilesType knownFilesType; - private final boolean readOnly; - private final File importFile; - private long totalLines; - private int crIndex = -1; - private HashDbManager.CentralRepoHashDb newHashDb = null; - private final AtomicLong numLines = new AtomicLong(); - private String errorString = ""; + abstract class CentralRepoImportWorker extends SwingWorker{ + final int HASH_IMPORT_THRESHOLD = 10000; + final String hashSetName; + final String version; + final int orgId; + final boolean searchDuringIngest; + final boolean sendIngestMessages; + final HashDbManager.HashDb.KnownFilesType knownFilesType; + final boolean readOnly; + final File importFile; + long totalHashes = 1; + int referenceSetID = -1; + HashDbManager.CentralRepoHashDb newHashDb = null; + final AtomicLong numLines = new AtomicLong(); + String errorString = ""; - CentralRepoImportWorker2(String hashSetName, String version, int orgId, + CentralRepoImportWorker(String hashSetName, String version, int orgId, boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, boolean readOnly, File importFile){ @@ -186,88 +186,88 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P return errorString; } - } - - private interface CentralRepoImportWorker{ + /** + * Should be called in the constructor to set the max number of hashes. + * The value can be updated later after parsing the import file. + */ + abstract void setEstimatedTotalHashes(); - void execute(); - boolean cancel(boolean mayInterruptIfRunning); - void addPropertyChangeListener(PropertyChangeListener dialog); - int getProgressPercentage(); - long getLinesProcessed(); - HashDbManager.HashDatabase getDatabase(); - String getError(); + void deleteIncompleteSet(){ + if(referenceSetID >= 0){ + + // This can be slow on large reference sets + Executors.newSingleThreadExecutor().execute(new Runnable() { + @Override + public void run() { + try{ + EamDb.getInstance().deleteReferenceSet(referenceSetID); + } catch (EamDbException ex2){ + Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error deleting incomplete hash set from central repository", ex2); + } + } + }); + } + } + + @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.importHashsetError=Error importing hash set", + "ImportCentralRepoDbProgressDialog.addDbError.message=Error adding new hash set"}) + @Override + protected void done() { + + if(isCancelled()){ + // If the user hit cancel, delete this incomplete hash set from the central repo + deleteIncompleteSet(); + return; + } + + try { + get(); + try{ + newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetName, version, + referenceSetID, + searchDuringIngest, sendIngestMessages, knownFilesType, readOnly); + } catch (TskCoreException ex){ + JOptionPane.showMessageDialog(null, Bundle.ImportCentralRepoDbProgressDialog_addDbError_message()); + Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error adding imported hash set", ex); + } + } catch (Exception ex) { + // Delete this incomplete hash set from the central repo + deleteIncompleteSet(); + errorString = Bundle.ImportCentralRepoDbProgressDialog_importHashsetError(); + } + } + } - class ImportEncaseWorker extends SwingWorker implements CentralRepoImportWorker{ - private final int HASH_IMPORT_THRESHOLD = 10000; - private final String hashSetName; - private final String version; - private final int orgId; - private final boolean searchDuringIngest; - private final boolean sendIngestMessages; - private final HashDbManager.HashDb.KnownFilesType knownFilesType; - private final boolean readOnly; - private final File importFile; - private final long totalLines; - private int crIndex = -1; - private HashDbManager.CentralRepoHashDb newHashDb = null; - private final AtomicLong numLines = new AtomicLong(); - private String errorString = ""; + class ImportEncaseWorker extends CentralRepoImportWorker{ ImportEncaseWorker(String hashSetName, String version, int orgId, - boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, - boolean readOnly, File importFile){ + boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, + boolean readOnly, File importFile){ + super(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages, knownFilesType, readOnly, importFile); - this.hashSetName = hashSetName; - this.version = version; - this.orgId = orgId; - this.searchDuringIngest = searchDuringIngest; - this.sendIngestMessages = sendIngestMessages; - this.knownFilesType = knownFilesType; - this.readOnly = readOnly; - this.importFile = importFile; - this.numLines.set(0); - - this.totalLines = getEstimatedTotalHashes(); + setEstimatedTotalHashes(); } + /** * Encase files have a 0x480 byte header, then each hash takes 18 bytes * @return Approximate number of hashes in the file */ - final long getEstimatedTotalHashes(){ + @Override + final void setEstimatedTotalHashes(){ long fileSize = importFile.length(); if(fileSize < 0x492){ - return 1; // There's room for at most one hash + totalHashes = 1; // There's room for at most one hash } - return ((fileSize - 0x492) / 18); - } - - @Override - public HashDbManager.HashDatabase getDatabase(){ - return newHashDb; - } - - @Override - public long getLinesProcessed(){ - return numLines.get(); - } - - @Override - public int getProgressPercentage(){ - return this.getProgress(); - } - - @Override - public String getError(){ - return errorString; + totalHashes = (fileSize - 0x492) / 18; } @Override protected Void doInBackground() throws Exception { - EncaseHashSetParser encaseParser = new EncaseHashSetParser(this.importFile.getAbsolutePath()); + EncaseHashSetParser encaseParser = new EncaseHashSetParser(importFile.getAbsolutePath()); + totalHashes = encaseParser.getExpectedHashes(); TskData.FileKnown knownStatus; if (knownFilesType.equals(HashDbManager.HashDb.KnownFilesType.KNOWN)) { @@ -277,7 +277,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } // Create an empty hashset in the central repository - crIndex = EamDb.getInstance().newReferenceSet(orgId, hashSetName, version, knownStatus, readOnly); + referenceSetID = EamDb.getInstance().newReferenceSet(orgId, hashSetName, version, knownStatus, readOnly); EamDb dbManager = EamDb.getInstance(); CorrelationAttribute.Type contentType = dbManager.getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); // get "FILES" type @@ -293,7 +293,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P if(newHash != null){ EamGlobalFileInstance eamGlobalFileInstance = new EamGlobalFileInstance( - crIndex, + referenceSetID, newHash, knownStatus, ""); @@ -305,7 +305,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType); globalInstances.clear(); - int progress = (int)(numLines.get() * 100 / totalLines); + int progress = (int)(numLines.get() * 100 / totalHashes); if(progress < 100){ this.setProgress(progress); } else { @@ -319,90 +319,17 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P this.setProgress(100); return null; } - - private void deleteIncompleteSet(int crIndex){ - if(crIndex >= 0){ - - // This can be slow on large reference sets - Executors.newSingleThreadExecutor().execute(new Runnable() { - @Override - public void run() { - try{ - EamDb.getInstance().deleteReferenceSet(crIndex); - } catch (EamDbException ex2){ - Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error deleting incomplete hash set from central repository", ex2); - } - } - }); - } - } - - @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.importError=Error importing hash set"}) - @Override - protected void done() { - - if(isCancelled()){ - // If the user hit cancel, delete this incomplete hash set from the central repo - deleteIncompleteSet(crIndex); - return; - } - - try { - get(); - try{ - newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetName, version, - crIndex, - searchDuringIngest, sendIngestMessages, knownFilesType, readOnly); - } catch (TskCoreException ex){ - JOptionPane.showMessageDialog(null, Bundle.ImportCentralRepoDbProgressDialog_addDbError_message()); - Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error adding imported hash set", ex); - } - } catch (Exception ex) { - // Delete this incomplete hash set from the central repo - if(crIndex >= 0){ - try{ - EamDb.getInstance().deleteReferenceSet(crIndex); - } catch (EamDbException ex2){ - Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error deleting incomplete hash set from central repository", ex); - } - } - errorString = Bundle.ImportCentralRepoDbProgressDialog_importError(); - } - } } - class ImportIDXWorker extends SwingWorker implements CentralRepoImportWorker{ - - private final int HASH_IMPORT_THRESHOLD = 10000; - private final String hashSetName; - private final String version; - private final int orgId; - private final boolean searchDuringIngest; - private final boolean sendIngestMessages; - private final HashDbManager.HashDb.KnownFilesType knownFilesType; - private final boolean readOnly; - private final File importFile; - private final long totalLines; - private int referenceSetID = -1; - private HashDbManager.CentralRepoHashDb newHashDb = null; - private final AtomicLong numLines = new AtomicLong(); - private String errorString = ""; + + class ImportIDXWorker extends CentralRepoImportWorker{ ImportIDXWorker(String hashSetName, String version, int orgId, - boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, - boolean readOnly, File importFile){ + boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, + boolean readOnly, File importFile){ + super(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages, knownFilesType, readOnly, importFile); - this.hashSetName = hashSetName; - this.version = version; - this.orgId = orgId; - this.searchDuringIngest = searchDuringIngest; - this.sendIngestMessages = sendIngestMessages; - this.knownFilesType = knownFilesType; - this.readOnly = readOnly; - this.importFile = importFile; - this.numLines.set(0); - - this.totalLines = getEstimatedTotalHashes(); + setEstimatedTotalHashes(); } /** @@ -411,29 +338,10 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P * progress bar. * @return Approximate number of hashes in the file */ - final long getEstimatedTotalHashes(){ + @Override + final void setEstimatedTotalHashes(){ long fileSize = importFile.length(); - return (fileSize / 0x33 + 1); // IDX file lines are generally 0x33 bytes long, and we don't want this to be zero - } - - @Override - public HashDbManager.HashDatabase getDatabase(){ - return newHashDb; - } - - @Override - public long getLinesProcessed(){ - return numLines.get(); - } - - @Override - public int getProgressPercentage(){ - return this.getProgress(); - } - - @Override - public String getError(){ - return errorString; + totalHashes = fileSize / 0x33 + 1; // IDX file lines are generally 0x33 bytes long, and we don't want this to be zero } @Override @@ -480,7 +388,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType); globalInstances.clear(); - int progress = (int)(numLines.get() * 100 / totalLines); + int progress = (int)(numLines.get() * 100 / totalHashes); if(progress < 100){ this.setProgress(progress); } else { @@ -494,54 +402,6 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P return null; } - - private void deleteIncompleteSet(int idToDelete){ - if(idToDelete >= 0){ - - // This can be slow on large reference sets - Executors.newSingleThreadExecutor().execute(new Runnable() { - @Override - public void run() { - try{ - EamDb.getInstance().deleteReferenceSet(idToDelete); - } catch (EamDbException ex2){ - Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error deleting incomplete hash set from central repository", ex2); - } - } - }); - } - } - - @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.addDbError.message=Error adding new hash set"}) - @Override - protected void done() { - if(isCancelled()){ - // If the user hit cancel, delete this incomplete hash set from the central repo - deleteIncompleteSet(referenceSetID); - return; - } - - try { - get(); - try{ - newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetName, version, - referenceSetID, - searchDuringIngest, sendIngestMessages, knownFilesType, readOnly); - } catch (TskCoreException ex){ - JOptionPane.showMessageDialog(null, Bundle.ImportCentralRepoDbProgressDialog_addDbError_message()); - Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error adding imported hash set", ex); - } - } catch (Exception ex) { - // Delete this incomplete hash set from the central repo - if(referenceSetID >= 0){ - try{ - EamDb.getInstance().deleteReferenceSet(referenceSetID); - } catch (EamDbException ex2){ - Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error deleting incomplete hash set from central repository", ex); - } - } - } - } } /** From 1a63dc413c5d233712b5fc5b645ef4e6c51385aa Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 10 Nov 2017 09:46:47 -0500 Subject: [PATCH 09/90] 3201 attribute storing knownStatus for TagName renamed to knownStatus --- .../casemodule/services/TagNameDefinition.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java index 7dd4b5309a..b24913b4e0 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java @@ -46,7 +46,7 @@ final class TagNameDefinition implements Comparable { private final String displayName; private final String description; private final TagName.HTML_COLOR color; - private final TskData.FileKnown knownStatusDenoted; + private final TskData.FileKnown knownStatus; /** * Constructs a tag name definition consisting of a display name, @@ -55,14 +55,14 @@ final class TagNameDefinition implements Comparable { * @param displayName The display name for the tag name. * @param description The description for the tag name. * @param color The color for the tag name. - * @param knownStatus The status denoted by the tag. + * @param knownStatus The status denoted by the tag name. */ TagNameDefinition(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown status) { this.displayName = displayName; this.description = description; this.color = color; - this.knownStatusDenoted = status; + this.knownStatus = status; } /** @@ -93,13 +93,13 @@ final class TagNameDefinition implements Comparable { } /** - * Whether or not the status that this tag implies is the Notable status + * Whether or not the status that this tag implies Notable status * * @return true if the Notable status is implied by this tag, false * otherwise. */ boolean isNotable() { - return knownStatusDenoted == TskData.FileKnown.BAD; + return knownStatus == TskData.FileKnown.BAD; } /** @@ -162,7 +162,7 @@ final class TagNameDefinition implements Comparable { * that is used by the tags settings file. */ private String toSettingsFormat() { - return displayName + "," + description + "," + color.name() + "," + knownStatusDenoted.toString(); + return displayName + "," + description + "," + color.name() + "," + knownStatus.toString(); } /** From 3ab8a95165becd7676221012ade1af2f7c806830 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Fri, 10 Nov 2017 12:44:48 -0500 Subject: [PATCH 10/90] Enable any central repo has sets the user personally creates by default. --- .../modules/hashdatabase/HashDbManager.java | 45 ++++++++++++++++++- .../hashdatabase/HashLookupSettingsPanel.java | 19 ++++---- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index cd0b1339b7..8d03c4e37a 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -46,6 +46,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalSet; import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupSettings.HashDbInfo; import org.sleuthkit.datamodel.AbstractFile; @@ -70,6 +71,8 @@ public class HashDbManager implements PropertyChangeListener { PropertyChangeSupport changeSupport = new PropertyChangeSupport(HashDbManager.class); private static final Logger logger = Logger.getLogger(HashDbManager.class.getName()); private boolean allDatabasesLoadedCorrectly = false; + private static final String CENTRAL_REPO_HASH_SET_SETTINGS = "CentralRepoHashSets"; + private static final String CENTRAL_REPO_HASH_SET_LOCAL_KEY = "LocallyCreatedHashsets"; /** * Property change event support In events: For both of these enums, the old @@ -697,6 +700,44 @@ public class HashDbManager implements PropertyChangeListener { } } } + + /** + * Save any newly created central repo databases to the properties file. + * @param newHashSets + */ + static void saveNewCentralRepoDatabases(List newHashSets){ + + if(! newHashSets.isEmpty()){ + String newDbs = ""; + for(CentralRepoHashDb db:newHashSets){ + newDbs += makeCentralRepoHashSetString(db); + } + String oldSetting = ModuleSettings.getConfigSetting(CENTRAL_REPO_HASH_SET_SETTINGS, CENTRAL_REPO_HASH_SET_LOCAL_KEY); + String newSetting = ""; + if((oldSetting != null) && (! oldSetting.isEmpty())){ + newSetting = oldSetting; + } + newSetting += newDbs; + ModuleSettings.setConfigSetting(CENTRAL_REPO_HASH_SET_SETTINGS, CENTRAL_REPO_HASH_SET_LOCAL_KEY, newSetting); + } + } + + /** + * Check whether a given central repository hash set was created on this machine. + * @return true if it was created on this machine, false otherwise + */ + static boolean centralRepoWasCreatedLocally(CentralRepoHashDb db){ + String setting = ModuleSettings.getConfigSetting(CENTRAL_REPO_HASH_SET_SETTINGS, CENTRAL_REPO_HASH_SET_LOCAL_KEY); + String dbStr = makeCentralRepoHashSetString(db); + if(setting == null){ + return false; + } + return setting.contains(dbStr); + } + + private static String makeCentralRepoHashSetString(CentralRepoHashDb db){ + return "|" + db.getReferenceSetID() + "." + db.getHashSetName() + "." + db.getVersion() + "|"; + } private boolean hashDbInfoIsNew(HashDbInfo dbInfo){ for(HashDatabase db:this.hashSets){ @@ -1258,8 +1299,8 @@ public class HashDbManager implements PropertyChangeListener { @Override public boolean getDefaultSearchDuringIngest(){ - // Central repo hash sets are off by default - return false; + // Central repo hash sets are off by default, unless created on this machine + return centralRepoWasCreatedLocally(this); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java index 0a299a6e87..4b40c60386 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java @@ -27,7 +27,6 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import javax.swing.JComponent; -import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; @@ -66,7 +65,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan .getMessage(HashLookupSettingsPanel.class, "HashDbConfigPanel.errorGettingIndexStatusText"); private final HashDbManager hashSetManager = HashDbManager.getInstance(); private final HashSetTableModel hashSetTableModel = new HashSetTableModel(); - private final List newReferenceSetIDs = new ArrayList<>(); + private final List newReferenceSets = new ArrayList<>(); public HashLookupSettingsPanel() { initComponents(); @@ -328,7 +327,8 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan try { hashSetManager.save(); - newReferenceSetIDs.clear(); + HashDbManager.getInstance().saveNewCentralRepoDatabases(newReferenceSets); + newReferenceSets.clear(); } catch (HashDbManager.HashDbManagerException ex) { SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(null, Bundle.HashLookupSettingsPanel_saveFail_message(), Bundle.HashLookupSettingsPanel_saveFail_title(), JOptionPane.ERROR_MESSAGE); @@ -355,10 +355,10 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan */ if (IngestManager.getInstance().isIngestRunning() == false) { // Remove any new central repo hash sets from the database - for(int refID:newReferenceSetIDs){ + for(CentralRepoHashDb db:newReferenceSets){ try{ if(EamDb.isEnabled()){ - EamDb.getInstance().deleteReferenceSet(refID); + EamDb.getInstance().deleteReferenceSet(db.getReferenceSetID()); } else { // This is the case where the user imported a database, then switched over to the central // repo panel and disabled it before cancelling. We can't delete the database at this point. @@ -368,6 +368,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan Logger.getLogger(HashLookupSettingsPanel.class.getName()).log(Level.SEVERE, "Error reverting central repository hash sets", ex); //NON-NLS } } + newReferenceSets.clear(); HashDbManager.getInstance().loadLastSavedConfiguration(); } @@ -922,8 +923,8 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan HashDatabase hashDb = new HashDbCreateDatabaseDialog().getHashDatabase(); if (null != hashDb) { if(hashDb instanceof CentralRepoHashDb){ - int newDbIndex = ((CentralRepoHashDb)hashDb).getReferenceSetID(); - newReferenceSetIDs.add(newDbIndex); + CentralRepoHashDb crDb = (CentralRepoHashDb)hashDb; + newReferenceSets.add(crDb); } hashSetTableModel.refreshModel(); @@ -976,8 +977,8 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan HashDatabase hashDb = new HashDbImportDatabaseDialog().getHashDatabase(); if (null != hashDb) { if(hashDb instanceof CentralRepoHashDb){ - int newReferenceSetID = ((CentralRepoHashDb)hashDb).getReferenceSetID(); - newReferenceSetIDs.add(newReferenceSetID); + CentralRepoHashDb crDb = (CentralRepoHashDb)hashDb; + newReferenceSets.add(crDb); } hashSetTableModel.refreshModel(); From bb40f1d8e886f08039abb0be4360fc31681f54a6 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 10 Nov 2017 17:52:02 -0500 Subject: [PATCH 11/90] 3202 Messaging for changing of status which tag implies --- .../sleuthkit/autopsy/casemodule/Case.java | 12 ++- .../services/TagNameDefinition.java | 18 ++-- .../casemodule/services/TagNameDialog.java | 3 +- .../casemodule/services/TagOptionsPanel.java | 11 ++- .../casemodule/services/TagsManager.java | 2 +- .../eventlisteners/CaseEventListener.java | 95 ++++++++++++++++++- 6 files changed, 122 insertions(+), 19 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 983c9420b2..1cadd0b0b2 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -76,6 +76,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ReportAddedEvent; import org.sleuthkit.autopsy.casemodule.services.Services; +import org.sleuthkit.autopsy.casemodule.services.TagNameDefinition; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CategoryNode; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; @@ -362,7 +363,13 @@ public class Case { * case number, the examiner name, examiner phone, examiner email, and * the case notes. */ - CASE_DETAILS; + CASE_DETAILS, + /** + * The status which a Tag indicates has been changed and the new value + * of the TagNameDefinition is included. + */ + TAG_STATUS_CHANGED; + }; /** @@ -1472,6 +1479,9 @@ public class Case { eventPublisher.publish(new ContentTagDeletedEvent(deletedTag)); } + public void notifyTagStatusChanged(TagNameDefinition oldTag, TagNameDefinition newTag) { + eventPublisher.publish(new AutopsyEvent(Events.TAG_STATUS_CHANGED.toString(), oldTag, newTag)); + } /** * Notifies case event subscribers that an artifact tag has been added. * diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java index 7dd4b5309a..f039a40d92 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java @@ -34,7 +34,7 @@ import org.sleuthkit.datamodel.TskData; * A tag name definition consisting of a display name, description and color. */ @Immutable -final class TagNameDefinition implements Comparable { +public final class TagNameDefinition implements Comparable { private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS @@ -58,7 +58,8 @@ final class TagNameDefinition implements Comparable { * @param knownStatus The status denoted by the tag. */ - TagNameDefinition(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown status) { + public TagNameDefinition(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown status) { + this.displayName = displayName; this.description = description; this.color = color; @@ -70,7 +71,7 @@ final class TagNameDefinition implements Comparable { * * @return The display name. */ - String getDisplayName() { + public String getDisplayName() { return displayName; } @@ -92,14 +93,9 @@ final class TagNameDefinition implements Comparable { return color; } - /** - * Whether or not the status that this tag implies is the Notable status - * - * @return true if the Notable status is implied by this tag, false - * otherwise. - */ - boolean isNotable() { - return knownStatusDenoted == TskData.FileKnown.BAD; + + public TskData.FileKnown getKnownStatus() { + return knownStatusDenoted; } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java index e310c066e5..402c3b1a09 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java @@ -29,6 +29,7 @@ import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.datamodel.TskData; final class TagNameDialog extends javax.swing.JDialog { @@ -59,7 +60,7 @@ final class TagNameDialog extends javax.swing.JDialog { initComponents(); tagNameTextField.setText(tagNameToEdit.getDisplayName()); descriptionTextArea.setText(tagNameToEdit.getDescription()); - notableCheckbox.setSelected(tagNameToEdit.isNotable()); + notableCheckbox.setSelected(tagNameToEdit.getKnownStatus()== TskData.FileKnown.BAD); tagNameTextField.setEnabled(false); this.display(); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java index 6505fec9df..082827a94a 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java @@ -28,6 +28,7 @@ import javax.swing.JOptionPane; import javax.swing.event.ListSelectionEvent; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.datamodel.TagName; @@ -46,7 +47,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { private IngestJobEventPropertyChangeListener ingestJobEventsListener; /** - * Creates new form TagsManagerOptionsPanel + * Creates new form TagOptionsPanel */ TagOptionsPanel() { tagTypesListModel = new DefaultListModel<>(); @@ -336,14 +337,16 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { TagNameDefinition newTagType = new TagNameDefinition(dialog.getTagName(), dialog.getTagDesciption(), DEFAULT_COLOR, status); /* * If tag name already exists, don't add the tag name. - */ - + */ tagTypes.remove(originalTagName); tagTypes.add(newTagType); updateTagNamesListModel(); tagNamesList.setSelectedValue(newTagType, true); updatePanel(); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + if (originalTagName.getKnownStatus() != newTagType.getKnownStatus() && Case.isCaseOpen()){ + Case.getCurrentCase().notifyTagStatusChanged(originalTagName,newTagType); + } } }//GEN-LAST:event_editTagNameButtonActionPerformed @@ -416,7 +419,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { if (isSelected) { descriptionTextArea.setText(tagNamesList.getSelectedValue().getDescription()); - if (tagNamesList.getSelectedValue().isNotable()) { + if (tagNamesList.getSelectedValue().getKnownStatus() == TskData.FileKnown.BAD) { notableYesOrNoLabel.setText("Yes"); } else { notableYesOrNoLabel.setText("No"); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index 6dd4d359c3..d2dc7deea4 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -136,7 +136,7 @@ public class TagsManager implements Closeable { public static List getNotableTagDisplayNames() { List tagDisplayNames = new ArrayList<>(); for (TagNameDefinition tagDef : TagNameDefinition.getTagNameDefinitions()) { - if (tagDef.isNotable()) { + if (tagDef.getKnownStatus() == TskData.FileKnown.BAD) { tagDisplayNames.add(tagDef.getDisplayName()); } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index dbe17d6e6d..064f04fd78 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -33,6 +33,7 @@ import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent; +import org.sleuthkit.autopsy.casemodule.services.TagNameDefinition; import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute; @@ -48,6 +49,7 @@ import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentTag; +import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskDataException; @@ -97,6 +99,10 @@ final class CaseEventListener implements PropertyChangeListener { jobProcessingExecutor.submit(new DataSourceAddedTask(dbManager, evt)); } break; + case TAG_STATUS_CHANGED: { + //WJS-TODO actaully do stuff when event is seen. + jobProcessingExecutor.submit(new TagStatusChangeTask(dbManager, evt)); + } case CURRENT_CASE: { jobProcessingExecutor.submit(new CurrentCaseTask(dbManager, evt)); @@ -294,6 +300,93 @@ final class CaseEventListener implements PropertyChangeListener { } + private final class TagStatusChangeTask implements Runnable { + + private final EamDb dbManager; + private final PropertyChangeEvent event; + + private TagStatusChangeTask(EamDb db, PropertyChangeEvent evt) { + dbManager = db; + event = evt; + } + + @Override + public void run() { + if (!EamDb.isEnabled()) { + return; + } + TskData.FileKnown status = ((TagNameDefinition) event.getNewValue()).getKnownStatus(); + /** + * Set knownBad status for all files/artifacts in the given case + * that are tagged with the given tag name. Files/artifacts that are + * not already in the database will be added. + * + * @param tagName The name of the tag to search for + * @param curCase The case to search in + */ + try { + TagName tagName = Case.getCurrentCase().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(((TagNameDefinition) event.getNewValue()).getDisplayName()); + // First find any matching artifacts + List artifactTags = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifactTagsByTagName(tagName); + List notableTags = TagsManager.getNotableTagDisplayNames(); + for (BlackboardArtifactTag bbTag : artifactTags) { + List convertedArtifacts = EamArtifactUtil.getCorrelationAttributeFromBlackboardArtifact(bbTag.getArtifact(), true, true); + for (CorrelationAttribute eamArtifact : convertedArtifacts) { + if (status == TskData.FileKnown.UNKNOWN) { + Content content = bbTag.getContent(); + BlackboardArtifact bbArtifact = bbTag.getArtifact(); + TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); + List tags = tagsManager.getBlackboardArtifactTagsByArtifact(bbArtifact); + if (!(tags.stream() + .map(tag -> tag.getName().getDisplayName()) + .filter(notableTags::contains) + .collect(Collectors.toList()) + .isEmpty())) { // There are more bad tags on the object + break; + } + if ((content instanceof AbstractFile) && (((AbstractFile) content).getKnown() == TskData.FileKnown.KNOWN)) { + break; + } + } + System.out.println( + "TAG " + ((TagNameDefinition) event.getNewValue()).getDisplayName() + " event FROM " + ((TagNameDefinition) event.getOldValue()).getKnownStatus() + " TO " + ((TagNameDefinition) event.getNewValue()).getKnownStatus()); + EamDb.getInstance().setArtifactInstanceKnownStatus(eamArtifact, status); + } + } + + // Now search for files + List fileTags = Case.getCurrentCase().getSleuthkitCase().getContentTagsByTagName(tagName); + for (ContentTag contentTag : fileTags) { + if (status == TskData.FileKnown.UNKNOWN) { + Content content = contentTag.getContent(); + TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); + List tags = tagsManager.getContentTagsByContent(content); + if (!(tags.stream() + .map(tag -> tag.getName().getDisplayName()) + .filter(notableTags::contains) + .collect(Collectors.toList()) + .isEmpty())) { // There are more bad tags on the object + continue; + } + } + System.out.println("MAKING ARTIFACT"); + final CorrelationAttribute eamArtifact = EamArtifactUtil.getEamArtifactFromContent(contentTag.getContent(), + TskData.FileKnown.BAD, ""); + if (eamArtifact != null) { + EamDb.getInstance().setArtifactInstanceKnownStatus(eamArtifact, status); + System.out.println( + "TAG " + ((TagNameDefinition) event.getNewValue()).getDisplayName() + " event FROM " + ((TagNameDefinition) event.getOldValue()).getKnownStatus() + " TO " + ((TagNameDefinition) event.getNewValue()).getKnownStatus()); + } + } + } catch (TskCoreException ex) { + System.out.println("Cannot update "); + } catch (EamDbException ex) { + System.out.println("Cannot get CR"); + } + + } //TAG_STATUS_CHANGED + } + private final class DataSourceAddedTask implements Runnable { private final EamDb dbManager; @@ -350,7 +443,7 @@ final class CaseEventListener implements PropertyChangeListener { if ((null == event.getOldValue()) && (event.getNewValue() instanceof Case)) { Case curCase = (Case) event.getNewValue(); IngestEventsListener.resetCeModuleInstanceCount(); - + CorrelationCase curCeCase = new CorrelationCase( -1, curCase.getName(), // unique case ID From 9b7ada8f64f63d1e2e571ffae6bd92c682a89798 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 14 Nov 2017 17:32:11 -0500 Subject: [PATCH 12/90] 3202 remove confirmation for changing tag status in current case --- .../services/TagNameDefinition.java | 7 +- .../casemodule/services/TagOptionsPanel.java | 68 +++++++++++++++++-- .../services/TagsOptionsPanelController.java | 1 + .../eventlisteners/CaseEventListener.java | 68 +++++++++---------- 4 files changed, 99 insertions(+), 45 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java index f039a40d92..38581aa83f 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java @@ -57,7 +57,6 @@ public final class TagNameDefinition implements Comparable { * @param color The color for the tag name. * @param knownStatus The status denoted by the tag. */ - public TagNameDefinition(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown status) { this.displayName = displayName; @@ -93,7 +92,6 @@ public final class TagNameDefinition implements Comparable { return color; } - public TskData.FileKnown getKnownStatus() { return knownStatusDenoted; } @@ -139,8 +137,9 @@ public final class TagNameDefinition implements Comparable { if (!(obj instanceof TagNameDefinition)) { return false; } - TagNameDefinition thatTagName = (TagNameDefinition) obj; - return this.getDisplayName().equals(thatTagName.getDisplayName()); + boolean sameName = this.getDisplayName().equals(((TagNameDefinition) obj).getDisplayName()); + boolean sameStatus = this.getKnownStatus().equals(((TagNameDefinition) obj).getKnownStatus()); + return sameName && sameStatus; } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java index 082827a94a..02f3b925fb 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.casemodule.services; import java.awt.EventQueue; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.HashSet; import java.util.Set; import java.util.TreeSet; import javax.swing.DefaultListModel; @@ -28,6 +29,7 @@ import javax.swing.JOptionPane; import javax.swing.event.ListSelectionEvent; import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.autopsy.ingest.IngestManager; @@ -40,11 +42,11 @@ import org.sleuthkit.datamodel.TskData; final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { private static final long serialVersionUID = 1L; - private static final String DEFAULT_DESCRIPTION = ""; private static final TagName.HTML_COLOR DEFAULT_COLOR = TagName.HTML_COLOR.NONE; private final DefaultListModel tagTypesListModel; private Set tagTypes; private IngestJobEventPropertyChangeListener ingestJobEventsListener; + private Set updatedStatusTags; /** * Creates new form TagOptionsPanel @@ -52,6 +54,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { TagOptionsPanel() { tagTypesListModel = new DefaultListModel<>(); tagTypes = new TreeSet<>(TagNameDefinition.getTagNameDefinitions()); + updatedStatusTags = new HashSet<>(); initComponents(); customizeComponents(); } @@ -295,12 +298,15 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { ); }// //GEN-END:initComponents + @Messages({"TagOptionsPanel.TagNameDialog.tagNameAlreadyExists.message=Tag name must be unique. A tag with this name already exists.", + "TagOptionsPanel.TagNameDialog.tagNameAlreadyExists.title=Duplicate Tag Name"}) + private void newTagNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTagNameButtonActionPerformed TagNameDialog dialog = new TagNameDialog(); TagNameDialog.BUTTON_PRESSED result = dialog.getResult(); if (result == TagNameDialog.BUTTON_PRESSED.OK) { TskData.FileKnown status = dialog.isTagNotable() ? TskData.FileKnown.BAD : TskData.FileKnown.UNKNOWN; - TagNameDefinition newTagType = new TagNameDefinition(dialog.getTagName(), DEFAULT_DESCRIPTION, DEFAULT_COLOR, status); + TagNameDefinition newTagType = new TagNameDefinition(dialog.getTagName(), dialog.getTagDesciption(), DEFAULT_COLOR, status); /* * If tag name already exists, don't add the tag name. */ @@ -312,8 +318,8 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); } else { JOptionPane.showMessageDialog(null, - NbBundle.getMessage(TagOptionsPanel.class, "TagNamesSettingsPanel.JOptionPane.tagNameAlreadyExists.message"), - NbBundle.getMessage(TagOptionsPanel.class, "TagNamesSettingsPanel.JOptionPane.tagNameAlreadyExists.title"), + NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.TagNameDialog.tagNameAlreadyExists.message"), + NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.TagNameDialog.tagNameAlreadyExists.title"), JOptionPane.INFORMATION_MESSAGE); } } @@ -337,15 +343,15 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { TagNameDefinition newTagType = new TagNameDefinition(dialog.getTagName(), dialog.getTagDesciption(), DEFAULT_COLOR, status); /* * If tag name already exists, don't add the tag name. - */ + */ tagTypes.remove(originalTagName); tagTypes.add(newTagType); updateTagNamesListModel(); tagNamesList.setSelectedValue(newTagType, true); updatePanel(); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - if (originalTagName.getKnownStatus() != newTagType.getKnownStatus() && Case.isCaseOpen()){ - Case.getCurrentCase().notifyTagStatusChanged(originalTagName,newTagType); + if (originalTagName.getKnownStatus() != newTagType.getKnownStatus() && Case.isCaseOpen()) { + updatedStatusTags.add(new TagPair(originalTagName, newTagType)); } } }//GEN-LAST:event_editTagNameButtonActionPerformed @@ -398,6 +404,18 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { @Override public void store() { TagNameDefinition.setTagNameDefinitions(tagTypes); + sendStatusChangedEvents(); + } + + void cancelChanges() { + updatedStatusTags.clear(); + } + + private void sendStatusChangedEvents() { + for (TagPair modifiedTag : updatedStatusTags) { + Case.getCurrentCase().notifyTagStatusChanged(modifiedTag.getOldValue(), modifiedTag.getNewValue()); + } + updatedStatusTags.clear(); } /** @@ -440,6 +458,42 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { super.finalize(); } + private class TagPair implements Comparable { + + private TagNameDefinition oldValue; + private TagNameDefinition newValue; + + private TagPair(TagNameDefinition oldV, TagNameDefinition newV) { + oldValue = oldV; + newValue = newV; + } + + private TagNameDefinition getOldValue() { + return oldValue; + } + + private TagNameDefinition getNewValue() { + return newValue; + } + + /** + * Compares this tag name definition with the specified tag name + * definition for order. + * + * @param other The tag name definition to which to compare this tag + * name definition. + * + * @return Negative integer, zero, or a positive integer to indicate + * that this tag name definition is less than, equal to, or + * greater than the specified tag name definition. + */ + @Override + public int compareTo(TagPair other) { + return this.getNewValue().compareTo(other.getNewValue()); + } + + } + /** * A property change listener that listens to ingest job events. */ diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsOptionsPanelController.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsOptionsPanelController.java index c27835f83a..fcd2131f90 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsOptionsPanelController.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsOptionsPanelController.java @@ -69,6 +69,7 @@ public final class TagsOptionsPanelController extends OptionsPanelController { */ @Override public void cancel() { + getPanel().cancelChanges(); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index 064f04fd78..6ecc0edb4a 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -100,10 +100,9 @@ final class CaseEventListener implements PropertyChangeListener { } break; case TAG_STATUS_CHANGED: { - //WJS-TODO actaully do stuff when event is seen. jobProcessingExecutor.submit(new TagStatusChangeTask(dbManager, evt)); } - + break; case CURRENT_CASE: { jobProcessingExecutor.submit(new CurrentCaseTask(dbManager, evt)); } @@ -318,12 +317,9 @@ final class CaseEventListener implements PropertyChangeListener { TskData.FileKnown status = ((TagNameDefinition) event.getNewValue()).getKnownStatus(); /** * Set knownBad status for all files/artifacts in the given case - * that are tagged with the given tag name. Files/artifacts that are - * not already in the database will be added. - * - * @param tagName The name of the tag to search for - * @param curCase The case to search in + * that are tagged with the given tag name. */ + System.out.println("TAG " + ((TagNameDefinition) event.getNewValue()).getDisplayName() + " event FROM " + ((TagNameDefinition) event.getOldValue()).getKnownStatus().toString() + " TO " + status.toString()); try { TagName tagName = Case.getCurrentCase().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(((TagNameDefinition) event.getNewValue()).getDisplayName()); // First find any matching artifacts @@ -332,50 +328,54 @@ final class CaseEventListener implements PropertyChangeListener { for (BlackboardArtifactTag bbTag : artifactTags) { List convertedArtifacts = EamArtifactUtil.getCorrelationAttributeFromBlackboardArtifact(bbTag.getArtifact(), true, true); for (CorrelationAttribute eamArtifact : convertedArtifacts) { + boolean hasOtherBadTags = false; if (status == TskData.FileKnown.UNKNOWN) { Content content = bbTag.getContent(); - BlackboardArtifact bbArtifact = bbTag.getArtifact(); - TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); - List tags = tagsManager.getBlackboardArtifactTagsByArtifact(bbArtifact); - if (!(tags.stream() - .map(tag -> tag.getName().getDisplayName()) - .filter(notableTags::contains) - .collect(Collectors.toList()) - .isEmpty())) { // There are more bad tags on the object - break; - } if ((content instanceof AbstractFile) && (((AbstractFile) content).getKnown() == TskData.FileKnown.KNOWN)) { break; } + BlackboardArtifact bbArtifact = bbTag.getArtifact(); + TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); + List tags = tagsManager.getBlackboardArtifactTagsByArtifact(bbArtifact); + for (BlackboardArtifactTag t : tags) { + if (t.getName().equals(tagName)) { + continue; + } + if (notableTags.contains(t.getName().getDisplayName())) { + hasOtherBadTags = true; + break; + } + } + } + if (!hasOtherBadTags) { + EamDb.getInstance().setArtifactInstanceKnownStatus(eamArtifact, status); } - System.out.println( - "TAG " + ((TagNameDefinition) event.getNewValue()).getDisplayName() + " event FROM " + ((TagNameDefinition) event.getOldValue()).getKnownStatus() + " TO " + ((TagNameDefinition) event.getNewValue()).getKnownStatus()); - EamDb.getInstance().setArtifactInstanceKnownStatus(eamArtifact, status); } } - // Now search for files List fileTags = Case.getCurrentCase().getSleuthkitCase().getContentTagsByTagName(tagName); for (ContentTag contentTag : fileTags) { + boolean hasOtherBadTags = false; if (status == TskData.FileKnown.UNKNOWN) { Content content = contentTag.getContent(); TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); List tags = tagsManager.getContentTagsByContent(content); - if (!(tags.stream() - .map(tag -> tag.getName().getDisplayName()) - .filter(notableTags::contains) - .collect(Collectors.toList()) - .isEmpty())) { // There are more bad tags on the object - continue; + for (ContentTag t : tags) { + if (t.getName().equals(tagName)) { + continue; + } + if (notableTags.contains(t.getName().getDisplayName())) { + hasOtherBadTags = true; + break; + } } } - System.out.println("MAKING ARTIFACT"); - final CorrelationAttribute eamArtifact = EamArtifactUtil.getEamArtifactFromContent(contentTag.getContent(), - TskData.FileKnown.BAD, ""); - if (eamArtifact != null) { - EamDb.getInstance().setArtifactInstanceKnownStatus(eamArtifact, status); - System.out.println( - "TAG " + ((TagNameDefinition) event.getNewValue()).getDisplayName() + " event FROM " + ((TagNameDefinition) event.getOldValue()).getKnownStatus() + " TO " + ((TagNameDefinition) event.getNewValue()).getKnownStatus()); + if (!hasOtherBadTags) { + final CorrelationAttribute eamArtifact = EamArtifactUtil.getEamArtifactFromContent(contentTag.getContent(), + status, ""); + if (eamArtifact != null) { + EamDb.getInstance().setArtifactInstanceKnownStatus(eamArtifact, status); + } } } } catch (TskCoreException ex) { From 55efc419ab9050d154df9fc587d5b27c0918dc6a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 14 Nov 2017 18:16:44 -0500 Subject: [PATCH 13/90] 3202 rename gui elements in TagOptionsPanel, change @messages --- .../casemodule/services/Bundle.properties | 8 +-- .../casemodule/services/TagOptionsPanel.form | 16 +++--- .../casemodule/services/TagOptionsPanel.java | 54 +++++++++++-------- 3 files changed, 41 insertions(+), 37 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties index 4cca7e78d6..95fd09a57b 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties @@ -9,15 +9,9 @@ TagNameDialog.JOptionPane.tagNameEmpty.title=Empty tag name TagOptionsPanel.tagTypesListLabel.text=Tag Names: TagOptionsPanel.deleteTagNameButton.text=Delete Tag TagOptionsPanel.newTagNameButton.text=New Tag -TagOptionsPanel.editTagNameButton.text=Edit Tag TagNameDialog.descriptionLabel.text=Description: TagNameDialog.okButton.text=OK TagNameDialog.cancelButton.text=Cancel TagNameDialog.tagNameTextField.text= TagNameDialog.newTagNameLabel.text=Name: -TagNameDialog.notableCheckbox.text=Tag indicates item is notable. -TagOptionsPanel.isNotableLabel.text=Tag indicates item is notable: -TagOptionsPanel.notableYesOrNoLabel.text= -TagOptionsPanel.descriptionLabel.text=Tag Description: -TagOptionsPanel.jTextArea1.text=Create and manage tags, which can be applied to files and results in the case. Notable tags will cause items tagged with them to be flagged as notable when using a central repository. -TagOptionsPanel.ingestRunningWarningLabel.text=Cannot make changes to existing tags when ingest is running! +TagNameDialog.notableCheckbox.text=Tag indicates item is notable. \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form index 541bd90cda..2d763857be 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form @@ -91,7 +91,7 @@ - + @@ -100,7 +100,7 @@ - + @@ -113,11 +113,11 @@ - + - + @@ -137,7 +137,7 @@ - + @@ -223,14 +223,14 @@ - + - + @@ -243,7 +243,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java index 02f3b925fb..c0be5bd9f4 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java @@ -59,6 +59,16 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { customizeComponents(); } + @Messages({"TagOptionsPanel.panelDescriptionTextArea.text=Create and manage tags. " + + "Tags can be applied to files and results in the case. Notable tags will cause " + + "items tagged with them to be flagged as notable when using a central repository. " + + "Changing the status of a tag will only effect items in the current case.", + "TagOptionsPanel.ingestRunningWarningLabel.text=Cannot make changes to existing tags when ingest is running!", + "TagOptionsPanel.descriptionLabel.text=Tag Description:", + "TagOptionsPanel.notableYesOrNoLabel.text=", + "TagOptionsPanel.isNotableLabel.text=Tag indicates item is notable: ", + "TagOptionsPanel.editTagNameButton.text=Edit Tag"}) + private void customizeComponents() { tagNamesList.setModel(tagTypesListModel); tagNamesList.addListSelectionListener((ListSelectionEvent event) -> { @@ -92,13 +102,13 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { jSplitPane1 = new javax.swing.JSplitPane(); modifyTagTypesListPanel = new javax.swing.JPanel(); tagTypesListLabel = new javax.swing.JLabel(); - jScrollPane1 = new javax.swing.JScrollPane(); + TagNameScrollPane = new javax.swing.JScrollPane(); tagNamesList = new javax.swing.JList<>(); newTagNameButton = new javax.swing.JButton(); deleteTagNameButton = new javax.swing.JButton(); editTagNameButton = new javax.swing.JButton(); - jScrollPane3 = new javax.swing.JScrollPane(); - jTextArea1 = new javax.swing.JTextArea(); + panelDescriptionScrollPane = new javax.swing.JScrollPane(); + panelDescriptionTextArea = new javax.swing.JTextArea(); tagTypesAdditionalPanel = new javax.swing.JPanel(); descriptionLabel = new javax.swing.JLabel(); descriptionScrollPane = new javax.swing.JScrollPane(); @@ -118,7 +128,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { org.openide.awt.Mnemonics.setLocalizedText(tagTypesListLabel, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.tagTypesListLabel.text")); // NOI18N tagNamesList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); - jScrollPane1.setViewportView(tagNamesList); + TagNameScrollPane.setViewportView(tagNamesList); newTagNameButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add-tag.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(newTagNameButton, org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.newTagNameButton.text")); // NOI18N @@ -153,16 +163,16 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { } }); - jTextArea1.setEditable(false); - jTextArea1.setBackground(new java.awt.Color(240, 240, 240)); - jTextArea1.setColumns(20); - jTextArea1.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N - jTextArea1.setLineWrap(true); - jTextArea1.setRows(3); - jTextArea1.setText(org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.jTextArea1.text")); // NOI18N - jTextArea1.setWrapStyleWord(true); - jTextArea1.setFocusable(false); - jScrollPane3.setViewportView(jTextArea1); + panelDescriptionTextArea.setEditable(false); + panelDescriptionTextArea.setBackground(new java.awt.Color(240, 240, 240)); + panelDescriptionTextArea.setColumns(20); + panelDescriptionTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N + panelDescriptionTextArea.setLineWrap(true); + panelDescriptionTextArea.setRows(3); + panelDescriptionTextArea.setText(org.openide.util.NbBundle.getMessage(TagOptionsPanel.class, "TagOptionsPanel.panelDescriptionTextArea.text")); // NOI18N + panelDescriptionTextArea.setWrapStyleWord(true); + panelDescriptionTextArea.setFocusable(false); + panelDescriptionScrollPane.setViewportView(panelDescriptionTextArea); javax.swing.GroupLayout modifyTagTypesListPanelLayout = new javax.swing.GroupLayout(modifyTagTypesListPanel); modifyTagTypesListPanel.setLayout(modifyTagTypesListPanelLayout); @@ -175,14 +185,14 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { .addGroup(modifyTagTypesListPanelLayout.createSequentialGroup() .addGroup(modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(TagNameScrollPane, javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.LEADING, modifyTagTypesListPanelLayout.createSequentialGroup() .addComponent(newTagNameButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(editTagNameButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(deleteTagNameButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 345, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(panelDescriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 345, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); @@ -193,11 +203,11 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(modifyTagTypesListPanelLayout.createSequentialGroup() .addGap(10, 10, 10) - .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(panelDescriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(tagTypesListLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 355, Short.MAX_VALUE) + .addComponent(TagNameScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 343, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(newTagNameButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) @@ -299,7 +309,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { }// //GEN-END:initComponents @Messages({"TagOptionsPanel.TagNameDialog.tagNameAlreadyExists.message=Tag name must be unique. A tag with this name already exists.", - "TagOptionsPanel.TagNameDialog.tagNameAlreadyExists.title=Duplicate Tag Name"}) + "TagOptionsPanel.TagNameDialog.tagNameAlreadyExists.title=Duplicate Tag Name"}) private void newTagNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTagNameButtonActionPerformed TagNameDialog dialog = new TagNameDialog(); @@ -357,6 +367,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { }//GEN-LAST:event_editTagNameButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane TagNameScrollPane; private javax.swing.JButton deleteTagNameButton; private javax.swing.JLabel descriptionLabel; private javax.swing.JScrollPane descriptionScrollPane; @@ -365,14 +376,13 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { private javax.swing.JLabel ingestRunningWarningLabel; private javax.swing.JLabel isNotableLabel; private javax.swing.JPanel jPanel1; - private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; - private javax.swing.JScrollPane jScrollPane3; private javax.swing.JSplitPane jSplitPane1; - private javax.swing.JTextArea jTextArea1; private javax.swing.JPanel modifyTagTypesListPanel; private javax.swing.JButton newTagNameButton; private javax.swing.JLabel notableYesOrNoLabel; + private javax.swing.JScrollPane panelDescriptionScrollPane; + private javax.swing.JTextArea panelDescriptionTextArea; private javax.swing.JList tagNamesList; private javax.swing.JPanel tagTypesAdditionalPanel; private javax.swing.JLabel tagTypesListLabel; From 9b511c3c0558664d1942edf61469fdd1dbfb2b8b Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 14 Nov 2017 18:18:16 -0500 Subject: [PATCH 14/90] 3202 make TagsPanelDescription large enough for text --- .../autopsy/casemodule/services/TagOptionsPanel.form | 8 ++++---- .../autopsy/casemodule/services/TagOptionsPanel.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form index 2d763857be..8654d04598 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form @@ -113,11 +113,11 @@ - - + + - - + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java index c0be5bd9f4..299a06219e 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java @@ -203,11 +203,11 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(modifyTagTypesListPanelLayout.createSequentialGroup() .addGap(10, 10, 10) - .addComponent(panelDescriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(panelDescriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(tagTypesListLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(TagNameScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 343, Short.MAX_VALUE) + .addComponent(TagNameScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 338, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(modifyTagTypesListPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(newTagNameButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) From 7f205b3ae4c37bab1980bc8ef22ab3e83cf1af8b Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 15 Nov 2017 12:34:05 -0500 Subject: [PATCH 15/90] 3201 move fix for blank description on new tag into 3201 from 3202 --- .../sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java index 6505fec9df..fd3663ea7a 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java @@ -299,7 +299,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { TagNameDialog.BUTTON_PRESSED result = dialog.getResult(); if (result == TagNameDialog.BUTTON_PRESSED.OK) { TskData.FileKnown status = dialog.isTagNotable() ? TskData.FileKnown.BAD : TskData.FileKnown.UNKNOWN; - TagNameDefinition newTagType = new TagNameDefinition(dialog.getTagName(), DEFAULT_DESCRIPTION, DEFAULT_COLOR, status); + TagNameDefinition newTagType = new TagNameDefinition(dialog.getTagName(), dialog.getTagDesciption(), DEFAULT_COLOR, status); /* * If tag name already exists, don't add the tag name. */ From 19c7cfb7048a6d0cc5cf49965cb709e512383b60 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Wed, 15 Nov 2017 13:10:57 -0500 Subject: [PATCH 16/90] 3207: Add a collection of attributes to aritifact instead of add one attribute at a time. --- .../eventlisteners/IngestEventsListener.java | 9 +++---- .../modules/filetypeid/FileTypeDetector.java | 7 ++++-- .../hashdatabase/HashDbIngestModule.java | 13 +++++----- .../autopsy/modules/iOS/CallLogAnalyzer.java | 16 ++++++++----- .../autopsy/modules/iOS/ContactAnalyzer.java | 11 +++++---- .../modules/iOS/TextMessageAnalyzer.java | 23 ++++++++++-------- .../FilesIdentifierIngestModule.java | 7 ++++-- .../modules/stix/StixArtifactData.java | 10 +++++--- ...nterestingArtifactCreatorIngestModule.java | 24 ++++++++++++------- .../recentactivity/ExtractRegistry.java | 14 ++++++----- 10 files changed, 82 insertions(+), 52 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java index 02d64904a4..0877bc1685 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java @@ -130,17 +130,18 @@ public class IngestEventsListener { try { AbstractFile af = bbArtifact.getSleuthkitCase().getAbstractFileById(bbArtifact.getObjectID()); - + Collection attributes = new ArrayList<>(); String MODULE_NAME = Bundle.IngestEventsListener_ingestmodule_name(); BlackboardArtifact tifArtifact = af.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT); BlackboardAttribute att = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, Bundle.IngestEventsListener_prevTaggedSet_text()); BlackboardAttribute att2 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME, Bundle.IngestEventsListener_prevCaseComment_text() + caseDisplayNames.stream().distinct().collect(Collectors.joining(",", "", ""))); - tifArtifact.addAttribute(att); - tifArtifact.addAttribute(att2); - tifArtifact.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, bbArtifact.getArtifactID())); + attributes.add(att); + attributes.add(att2); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, bbArtifact.getArtifactID())); + tifArtifact.addAttributes(attributes); try { // index the artifact for keyword search Blackboard blackboard = Case.getCurrentCase().getServices().getBlackboard(); diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index eb1ab33591..4bfbb8b734 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.modules.filetypeid; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.SortedSet; @@ -360,8 +361,9 @@ public class FileTypeDetector { if (fileType.createInterestingFileHit()) { BlackboardArtifact artifact; artifact = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); + Collection attributes = new ArrayList<>(); BlackboardAttribute setNameAttribute = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, FileTypeIdModuleFactory.getModuleName(), fileType.getInterestingFilesSetName()); - artifact.addAttribute(setNameAttribute); + attributes.add(setNameAttribute); /* * Use the MIME type as the category attribute, i.e., the @@ -369,8 +371,9 @@ public class FileTypeDetector { * files set. */ BlackboardAttribute ruleNameAttribute = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, FileTypeIdModuleFactory.getModuleName(), fileType.getMimeType()); - artifact.addAttribute(ruleNameAttribute); + attributes.add(ruleNameAttribute); + artifact.addAttributes(attributes); /* * Index the artifact for keyword search. */ diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index 3dd7416872..1ef51bdaeb 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.modules.hashdatabase; import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -296,14 +297,14 @@ public class HashDbIngestModule implements FileIngestModule { String MODULE_NAME = NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.moduleName"); BlackboardArtifact badFile = abstractFile.newArtifact(ARTIFACT_TYPE.TSK_HASHSET_HIT); + Collection attributes = new ArrayList<>(); //TODO Revisit usage of deprecated constructor as per TSK-583 //BlackboardAttribute att2 = new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), MODULE_NAME, "Known Bad", hashSetName); - BlackboardAttribute att2 = new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, hashSetName); - badFile.addAttribute(att2); - BlackboardAttribute att3 = new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_HASH_MD5, MODULE_NAME, md5Hash); - badFile.addAttribute(att3); - BlackboardAttribute att4 = new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME, comment); - badFile.addAttribute(att4); + attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, hashSetName)); + attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_HASH_MD5, MODULE_NAME, md5Hash)); + attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME, comment)); + + badFile.addAttributes(attributes); try { // index the artifact for keyword search diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java index bb2657c8ef..cfc7272315 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java @@ -23,6 +23,8 @@ import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.logging.Level; import org.openide.util.NbBundle.Messages; @@ -116,16 +118,18 @@ class CallLogAnalyzer { type = resultSet.getString("type"); //NON-NLS bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG); //create a call log and then add attributes from result set. + Collection attributes = new ArrayList<>(); if (type.equalsIgnoreCase("outgoing")) { //NON-NLS - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, moduleName, number)); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, moduleName, number)); } else { /// Covers INCOMING and MISSED - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, moduleName, number)); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, moduleName, number)); } - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START, moduleName, date)); // RC: Should be long! - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END, moduleName, duration + date)); // RC: Should be long! - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, type)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, moduleName, name)); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START, moduleName, date)); // RC: Should be long! + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END, moduleName, duration + date)); // RC: Should be long! + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, type)); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, moduleName, name)); + bba.addAttributes(attributes); try { // index the artifact for keyword search blackboard.indexArtifact(bba); diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java index ecfce79ae4..efa4494f26 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java @@ -28,6 +28,8 @@ import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.logging.Level; import org.openide.util.NbBundle.Messages; @@ -128,6 +130,7 @@ class ContactAnalyzer { BlackboardArtifact bba; bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); + Collection attributes = new ArrayList<>(); String name; String oldName = ""; String mimetype; // either phone or email @@ -137,16 +140,16 @@ class ContactAnalyzer { data1 = resultSet.getString("data1"); //NON-NLS mimetype = resultSet.getString("mimetype"); //NON-NLS if (name.equals(oldName) == false) { - bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, moduleName, name)); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, moduleName, name)); } if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { //NON-NLS - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, moduleName, data1)); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, moduleName, data1)); } else { - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, moduleName, data1)); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, moduleName, data1)); } oldName = name; + bba.addAttributes(attributes); try { // index the artifact for keyword search blackboard.indexArtifact(bba); diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java index 7a7e2f0cfa..d1a81663fe 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java @@ -23,6 +23,8 @@ import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.logging.Level; import org.openide.util.NbBundle; @@ -116,21 +118,22 @@ class TextMessageAnalyzer { body = resultSet.getString("body"); //NON-NLS bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create Message artifact and then add attributes from result set. - + Collection attributes = new ArrayList<>(); // @@@ NEed to put into more specific TO or FROM if (type.equals("1")) { - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, NbBundle.getMessage(this.getClass(), "TextMessageAnalyzer.bbAttribute.incoming"))); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, moduleName, address)); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, NbBundle.getMessage(this.getClass(), "TextMessageAnalyzer.bbAttribute.incoming"))); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, moduleName, address)); } else { - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, NbBundle.getMessage(this.getClass(), "TextMessageAnalyzer.bbAttribute.outgoing"))); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, moduleName, address)); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, NbBundle.getMessage(this.getClass(), "TextMessageAnalyzer.bbAttribute.outgoing"))); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, moduleName, address)); } - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, date)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, type)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT, moduleName, subject)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, moduleName, body)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, NbBundle.getMessage(this.getClass(), "TextMessageAnalyzer.bbAttribute.smsMessage"))); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, date)); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, type)); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT, moduleName, subject)); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, moduleName, body)); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, NbBundle.getMessage(this.getClass(), "TextMessageAnalyzer.bbAttribute.smsMessage"))); + bba.addAttributes(attributes); try { // index the artifact for keyword search blackboard.indexArtifact(bba); diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java index 78a8481f17..88ee3ae1b7 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesIdentifierIngestModule.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.modules.interestingitems; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; @@ -121,6 +122,7 @@ final class FilesIdentifierIngestModule implements FileIngestModule { // blackboard. String moduleName = InterestingItemsIngestModuleFactory.getModuleName(); BlackboardArtifact artifact = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); + Collection attributes = new ArrayList<>(); // Add a set name attribute to the artifact. This adds a // fair amount of redundant data to the attributes table @@ -128,13 +130,14 @@ final class FilesIdentifierIngestModule implements FileIngestModule { // otherwise would requires reworking the interesting files // set hit artifact. BlackboardAttribute setNameAttribute = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, moduleName, filesSet.getName()); - artifact.addAttribute(setNameAttribute); + attributes.add(setNameAttribute); // Add a category attribute to the artifact to record the // interesting files set membership rule that was satisfied. BlackboardAttribute ruleNameAttribute = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, moduleName, ruleSatisfied); - artifact.addAttribute(ruleNameAttribute); + attributes.add(ruleNameAttribute); + artifact.addAttributes(attributes); try { // index the artifact for keyword search blackboard.indexArtifact(artifact); diff --git a/Core/src/org/sleuthkit/autopsy/modules/stix/StixArtifactData.java b/Core/src/org/sleuthkit/autopsy/modules/stix/StixArtifactData.java index 8a8466d89f..afc84d87aa 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/stix/StixArtifactData.java +++ b/Core/src/org/sleuthkit/autopsy/modules/stix/StixArtifactData.java @@ -18,6 +18,8 @@ */ package org.sleuthkit.autopsy.modules.stix; +import java.util.ArrayList; +import java.util.Collection; import java.util.logging.Level; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; @@ -70,10 +72,12 @@ class StixArtifactData { } BlackboardArtifact bba = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, "Stix", setName)); //NON-NLS - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE, "Stix", observableId)); //NON-NLS - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, "Stix", objType)); //NON-NLS + Collection attributes = new ArrayList<>(); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, "Stix", setName)); //NON-NLS + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE, "Stix", observableId)); //NON-NLS + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, "Stix", objType)); //NON-NLS + bba.addAttributes(attributes); try { // index the artifact for keyword search blackboard.indexArtifact(bba); diff --git a/Core/src/org/sleuthkit/autopsy/test/InterestingArtifactCreatorIngestModule.java b/Core/src/org/sleuthkit/autopsy/test/InterestingArtifactCreatorIngestModule.java index 5e9a876ab6..a57623f02e 100755 --- a/Core/src/org/sleuthkit/autopsy/test/InterestingArtifactCreatorIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/test/InterestingArtifactCreatorIngestModule.java @@ -18,6 +18,8 @@ */ package org.sleuthkit.autopsy.test; +import java.util.ArrayList; +import java.util.Collection; import java.util.logging.Level; import org.openide.util.Exceptions; @@ -77,6 +79,7 @@ final class InterestingArtifactCreatorIngestModule extends FileIngestModuleAdapt Blackboard blackboard = Case.getCurrentCase().getServices().getBlackboard(); BlackboardArtifact.Type artifactTypeBase = blackboard.getOrAddArtifactType(ARTIFACT_TYPE_NAMES[randomArtIndex], ARTIFACT_DISPLAY_NAMES[randomArtIndex]); BlackboardArtifact artifactBase = file.newArtifact(artifactTypeBase.getTypeID()); + Collection baseAttributes = new ArrayList<>(); String commentTxt; BlackboardAttribute baseAttr; switch (artifactBase.getArtifactTypeID()) { @@ -84,7 +87,7 @@ final class InterestingArtifactCreatorIngestModule extends FileIngestModuleAdapt commentTxt = "www.placeholderWebsiteDOTCOM"; baseAttr = new BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL, "Fake Web BookMark", "www.thisWebsiteIsStillFake.com"); - artifactBase.addAttribute(baseAttr); + baseAttributes.add(baseAttr); break; case 9: commentTxt = "fakeKeyword"; @@ -94,29 +97,32 @@ final class InterestingArtifactCreatorIngestModule extends FileIngestModuleAdapt BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, "Fake Keyword Search", "Fake"); BlackboardAttribute keyword = new BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, "Fake Keyword Search", "FakeKeyword"); - artifactBase.addAttribute(baseAttr); - artifactBase.addAttribute(set); - artifactBase.addAttribute(keyword); + baseAttributes.add(baseAttr); + baseAttributes.add(set); + baseAttributes.add(keyword); break; case 25: commentTxt = "fake phone number from"; baseAttr = new BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, "Fake Call Log Whatever", "555-555-5555"); - artifactBase.addAttribute(baseAttr); + baseAttributes.add(baseAttr); break; default: commentTxt = "DEPENDENT ON ARTIFACT TYPE"; break; } + artifactBase.addAttributes(baseAttributes); BlackboardArtifact artifact = file.newArtifact(artifactType.getTypeID()); + Collection attributes = new ArrayList<>(); BlackboardAttribute att = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, "ArtifactsAndTxt"); BlackboardAttribute att2 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME, commentTxt); BlackboardAttribute att3 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, MODULE_NAME, ""); - artifact.addAttribute(att); - artifact.addAttribute(att2); - artifact.addAttribute(att3); - artifact.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, artifactBase.getArtifactID())); + attributes.add(att); + attributes.add(att2); + attributes.add(att3); + attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, artifactBase.getArtifactID())); + artifact.addAttributes(attributes); } catch (TskCoreException ex) { logger.log(Level.SEVERE, String.format("Failed to process file (obj_id = %d)", file.getId()), ex); return ProcessResult.ERROR; diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index d22ce2ca76..b0af801089 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -649,14 +649,15 @@ class ExtractRegistry extends Extract { String homeDir = value; String sid = artnode.getAttribute("sid"); //NON-NLS String username = artnode.getAttribute("username"); //NON-NLS - BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); - bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, parentModuleName, username)); - bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID, + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID, parentModuleName, sid)); - bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, homeDir)); + + bbart.addAttributes(bbattributes); // index the artifact for keyword search this.indexArtifact(bbart); } catch (TskCoreException ex) { @@ -669,10 +670,11 @@ class ExtractRegistry extends Extract { String localPath = artnode.getAttribute("localPath"); //NON-NLS String remoteName = value; BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE); - bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH, + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH, parentModuleName, localPath)); - bbart.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH, + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH, parentModuleName, remoteName)); + bbart.addAttributes(bbattributes); // index the artifact for keyword search this.indexArtifact(bbart); } catch (TskCoreException ex) { From 01fda811d5b003bea32354110df447629239ad32 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Thu, 16 Nov 2017 13:56:09 -0500 Subject: [PATCH 17/90] 3207: Update python code to use collection of attributes instead of adding addtribute one at a time --- .../android/browserlocation.py | 11 ++++++---- .../android/cachelocation.py | 11 ++++++---- InternalPythonModules/android/calllog.py | 15 +++++++------ InternalPythonModules/android/contact.py | 9 +++++--- .../android/googlemaplocation.py | 21 +++++++++++-------- InternalPythonModules/android/tangomessage.py | 11 ++++++---- InternalPythonModules/android/textmessage.py | 21 +++++++++++-------- InternalPythonModules/android/wwfmessage.py | 12 ++++++----- .../FindContactsDb.py | 16 +++++++------- 9 files changed, 76 insertions(+), 51 deletions(-) diff --git a/InternalPythonModules/android/browserlocation.py b/InternalPythonModules/android/browserlocation.py index ef79a623c2..81ce9d9163 100755 --- a/InternalPythonModules/android/browserlocation.py +++ b/InternalPythonModules/android/browserlocation.py @@ -28,6 +28,7 @@ from java.sql import ResultSet from java.sql import SQLException from java.sql import Statement from java.util.logging import Level +from java.util import ArrayList from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.casemodule.services import Blackboard from org.sleuthkit.autopsy.casemodule.services import FileManager @@ -89,14 +90,16 @@ class BrowserLocationAnalyzer(general.AndroidComponentAnalyzer): latitude = Double.valueOf(resultSet.getString("latitude")) longitude = Double.valueOf(resultSet.getString("longitude")) + attributes = ArrayList<>() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, general.MODULE_NAME, latitude)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, general.MODULE_NAME, longitude)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, timestamp)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, general.MODULE_NAME, "Browser Location History")) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, general.MODULE_NAME, latitude)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, general.MODULE_NAME, longitude)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, timestamp)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, general.MODULE_NAME, "Browser Location History")) # artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),moduleName, accuracy)) # NOTE: originally commented out + artifact.addAttributes(attributes); try: # index the artifact for keyword search blackboard = Case.getCurrentCase().getServices().getBlackboard() diff --git a/InternalPythonModules/android/cachelocation.py b/InternalPythonModules/android/cachelocation.py index c28aa48fc3..680db6d6e6 100755 --- a/InternalPythonModules/android/cachelocation.py +++ b/InternalPythonModules/android/cachelocation.py @@ -25,6 +25,7 @@ from java.lang import ClassNotFoundException from java.math import BigInteger from java.nio import ByteBuffer from java.util.logging import Level +from java.util import ArrayList from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.casemodule.services import Blackboard from org.sleuthkit.autopsy.casemodule.services import FileManager @@ -120,13 +121,15 @@ class CacheLocationAnalyzer(general.AndroidComponentAnalyzer): inputStream.read(tempBytes) timestamp = BigInteger(tempBytes).longValue() / 1000 + attributes = ArrayList<>() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, AndroidAnalyzer.MODULE_NAME, latitude)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, AndroidAnalyzer.MODULE_NAME, longitude)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, AndroidModuleFactorymodule.Name, timestamp)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, AndroidAnalyzer.MODULE_NAME, + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, AndroidAnalyzer.MODULE_NAME, latitude)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, AndroidAnalyzer.MODULE_NAME, longitude)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, AndroidModuleFactorymodule.Name, timestamp)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, AndroidAnalyzer.MODULE_NAME, file.getName() + "Location History")) + artifact.addAttributes(attributes) #Not storing these for now. # artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), AndroidModuleFactorymodule.moduleName, accuracy)) # artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID(), AndroidModuleFactorymodule.moduleName, confidence)) diff --git a/InternalPythonModules/android/calllog.py b/InternalPythonModules/android/calllog.py index 42e3a293a1..c3a65f8f38 100755 --- a/InternalPythonModules/android/calllog.py +++ b/InternalPythonModules/android/calllog.py @@ -28,6 +28,7 @@ from java.sql import ResultSet from java.sql import SQLException from java.sql import Statement from java.util.logging import Level +from java.util import ArrayList from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.casemodule.services import Blackboard from org.sleuthkit.autopsy.casemodule.services import FileManager @@ -119,17 +120,19 @@ class CallLogAnalyzer(general.AndroidComponentAnalyzer): name = resultSet.getString("name") # name of person dialed or called. None if unregistered try: + attributes = ArrayList<>() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG) # create a call log and then add attributes from result set. if direction == CallLogAnalyzer.OUTGOING: - artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, general.MODULE_NAME, number)) + attributes.add(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, general.MODULE_NAME, number)) else: # Covers INCOMING and MISSED - artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, general.MODULE_NAME, number)) + attributes.add(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, general.MODULE_NAME, number)) - artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_START, general.MODULE_NAME, date)) - artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_END, general.MODULE_NAME, duration + date)) - artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, directionString)) - artifact.addAttribute(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, name)) + attributes.add(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_START, general.MODULE_NAME, date)) + attributes.add(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_END, general.MODULE_NAME, duration + date)) + attributes.add(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, directionString)) + attributes.add(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, name)) + artifact.addAttributes(attributes) bbartifacts.append(artifact) try: diff --git a/InternalPythonModules/android/contact.py b/InternalPythonModules/android/contact.py index fe56cc1cbb..75768b8a8e 100755 --- a/InternalPythonModules/android/contact.py +++ b/InternalPythonModules/android/contact.py @@ -27,6 +27,7 @@ from java.sql import ResultSet from java.sql import SQLException from java.sql import Statement from java.util.logging import Level +from java.util import ArrayList from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.casemodule.services import Blackboard from org.sleuthkit.autopsy.casemodule.services import FileManager @@ -118,6 +119,7 @@ class ContactAnalyzer(general.AndroidComponentAnalyzer): + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" + "ORDER BY raw_contacts.display_name ASC;") + attributes = ArrayList<>() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT) oldName = "" while resultSet.next(): @@ -126,14 +128,15 @@ class ContactAnalyzer(general.AndroidComponentAnalyzer): mimetype = resultSet.getString("mimetype") # either phone or email if name != oldName: artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, name)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, name)) if mimetype == "vnd.android.cursor.item/phone_v2": - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, general.MODULE_NAME, data1)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, general.MODULE_NAME, data1)) else: - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, general.MODULE_NAME, data1)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, general.MODULE_NAME, data1)) oldName = name + artifact.addAttributes(attributes) bbartifacts.append(artifact) try: diff --git a/InternalPythonModules/android/googlemaplocation.py b/InternalPythonModules/android/googlemaplocation.py index 066ed2f792..3b4a265937 100755 --- a/InternalPythonModules/android/googlemaplocation.py +++ b/InternalPythonModules/android/googlemaplocation.py @@ -28,6 +28,7 @@ from java.sql import ResultSet from java.sql import SQLException from java.sql import Statement from java.util.logging import Level +from java.util import ArrayList from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.casemodule.services import Blackboard from org.sleuthkit.autopsy.casemodule.services import FileManager @@ -96,17 +97,19 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): source_lat = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("source_lat")) source_lng = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("source_lng")) + attributes = ArrayList<>() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, general.MODULE_NAME, "Destination")) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, time)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END, general.MODULE_NAME, dest_lat)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END, general.MODULE_NAME, dest_lng)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START, general.MODULE_NAME, source_lat)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START, general.MODULE_NAME, source_lng)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, dest_title)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION, general.MODULE_NAME, dest_address)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, general.MODULE_NAME, "Google Maps History")) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, general.MODULE_NAME, "Destination")) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, time)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END, general.MODULE_NAME, dest_lat)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END, general.MODULE_NAME, dest_lng)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START, general.MODULE_NAME, source_lat)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START, general.MODULE_NAME, source_lng)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, dest_title)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION, general.MODULE_NAME, dest_address)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, general.MODULE_NAME, "Google Maps History")) + aritfact.addAttributes(attributes) try: # index the artifact for keyword search blackboard = Case.getCurrentCase().getServices().getBlackboard() diff --git a/InternalPythonModules/android/tangomessage.py b/InternalPythonModules/android/tangomessage.py index 04223f7fe1..5ba6ad0339 100755 --- a/InternalPythonModules/android/tangomessage.py +++ b/InternalPythonModules/android/tangomessage.py @@ -28,6 +28,7 @@ from java.sql import ResultSet from java.sql import SQLException from java.sql import Statement from java.util.logging import Level +from java.util import ArrayList from org.apache.commons.codec.binary import Base64 from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.casemodule.services import Blackboard @@ -94,12 +95,14 @@ class TangoMessageAnalyzer(general.AndroidComponentAnalyzer): direction = "Outgoing" payload = resultSet.getString("payload") + attributes = ArrayList<>() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) #create a call log and then add attributes from result set. - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, create_time)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, direction)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, general.MODULE_NAME, TangoMessageAnalyzer.decodeMessage(conv_id, payload))) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, general.MODULE_NAME, "Tango Message")) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, create_time)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, direction)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, general.MODULE_NAME, TangoMessageAnalyzer.decodeMessage(conv_id, payload))) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, general.MODULE_NAME, "Tango Message")) + artifact.addAttributes(attributes) try: # index the artifact for keyword search blackboard = Case.getCurrentCase().getServices().getBlackboard() diff --git a/InternalPythonModules/android/textmessage.py b/InternalPythonModules/android/textmessage.py index afca23cdf1..221023ce44 100755 --- a/InternalPythonModules/android/textmessage.py +++ b/InternalPythonModules/android/textmessage.py @@ -28,6 +28,7 @@ from java.sql import ResultSet from java.sql import SQLException from java.sql import Statement from java.util.logging import Level +from java.util import ArrayList from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.casemodule.services import Blackboard from org.sleuthkit.autopsy.casemodule.services import FileManager @@ -92,19 +93,21 @@ class TextMessageAnalyzer(general.AndroidComponentAnalyzer): read = resultSet.getInt("read") # may be unread = 0, read = 1 subject = resultSet.getString("subject") # message subject body = resultSet.getString("body") # message body + attributes = ArrayList<>() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); #create Message artifact and then add attributes from result set. if resultSet.getString("type") == "1": - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, "Incoming")) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, general.MODULE_NAME, address)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, "Incoming")) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, general.MODULE_NAME, address)) else: - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, "Outgoing")) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, general.MODULE_NAME, address)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, date)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_READ_STATUS, general.MODULE_NAME, Integer(read))) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT, general.MODULE_NAME, subject)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, general.MODULE_NAME, body)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, general.MODULE_NAME, "SMS Message")) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, "Outgoing")) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, general.MODULE_NAME, address)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, date)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_READ_STATUS, general.MODULE_NAME, Integer(read))) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT, general.MODULE_NAME, subject)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, general.MODULE_NAME, body)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, general.MODULE_NAME, "SMS Message")) + artifact.addAttributes(attributes) bbartifacts.append(artifact) try: # index the artifact for keyword search diff --git a/InternalPythonModules/android/wwfmessage.py b/InternalPythonModules/android/wwfmessage.py index 97f35869ed..1fe80a099d 100755 --- a/InternalPythonModules/android/wwfmessage.py +++ b/InternalPythonModules/android/wwfmessage.py @@ -88,13 +88,15 @@ class WWFMessageAnalyzer(general.AndroidComponentAnalyzer): user_id = resultSet.getString("user_id") # the ID of the user who sent the message. game_id = resultSet.getString("game_id") # ID of the game which the the message was sent. + attributes = ArrayList<>() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) # create a call log and then add attributes from result set. - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, created_at)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, user_id)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MSG_ID, general.MODULE_NAME, game_id)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, general.MODULE_NAME, message)) - artifact.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, general.MODULE_NAME, "Words With Friends Message")) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, created_at)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, user_id)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MSG_ID, general.MODULE_NAME, game_id)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, general.MODULE_NAME, message)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, general.MODULE_NAME, "Words With Friends Message")) + artifact.addAttrisbutes(attributes) try: # index the artifact for keyword search blackboard = Case.getCurrentCase().getServices().getBlackboard() diff --git a/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py b/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py index 7a11ed913d..5900f4f04f 100755 --- a/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py +++ b/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py @@ -40,6 +40,7 @@ from java.lang import Class from java.lang import System from java.sql import DriverManager, SQLException from java.util.logging import Level +from java.util import ArrayList from java.io import File from org.sleuthkit.datamodel import SleuthkitCase from org.sleuthkit.datamodel import AbstractFile @@ -162,17 +163,18 @@ class ContactsDbIngestModule(DataSourceIngestModule): # Make an artifact on the blackboard, TSK_CONTACT and give it attributes for each of the fields art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT) - - art.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME_PERSON.getTypeID(), + attributes = ArrayList<>() + + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME_PERSON.getTypeID(), ContactsDbIngestModuleFactory.moduleName, name)) - art.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL.getTypeID(), + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL.getTypeID(), ContactsDbIngestModuleFactory.moduleName, email)) - art.addAttribute(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), ContactsDbIngestModuleFactory.moduleName, phone)) - - + + art.addAttributes(attributes) try: # index the artifact for keyword search blackboard.indexArtifact(art) @@ -195,4 +197,4 @@ class ContactsDbIngestModule(DataSourceIngestModule): "ContactsDb Analyzer", "Found %d files" % fileCount) IngestServices.getInstance().postMessage(message) - return IngestModule.ProcessResult.OK \ No newline at end of file + return IngestModule.ProcessResult.OK From 4ecfb24165ea073cc94e0cff92d0cfa20d66b78b Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Fri, 17 Nov 2017 09:40:31 -0500 Subject: [PATCH 18/90] 3207: create ArrayList in python --- InternalPythonModules/android/browserlocation.py | 2 +- InternalPythonModules/android/cachelocation.py | 2 +- InternalPythonModules/android/calllog.py | 2 +- InternalPythonModules/android/contact.py | 2 +- InternalPythonModules/android/googlemaplocation.py | 2 +- InternalPythonModules/android/tangomessage.py | 2 +- InternalPythonModules/android/textmessage.py | 2 +- InternalPythonModules/android/wwfmessage.py | 2 +- pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/InternalPythonModules/android/browserlocation.py b/InternalPythonModules/android/browserlocation.py index 81ce9d9163..6db230c2e6 100755 --- a/InternalPythonModules/android/browserlocation.py +++ b/InternalPythonModules/android/browserlocation.py @@ -90,7 +90,7 @@ class BrowserLocationAnalyzer(general.AndroidComponentAnalyzer): latitude = Double.valueOf(resultSet.getString("latitude")) longitude = Double.valueOf(resultSet.getString("longitude")) - attributes = ArrayList<>() + attributes = ArrayList() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT) attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, general.MODULE_NAME, latitude)) attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, general.MODULE_NAME, longitude)) diff --git a/InternalPythonModules/android/cachelocation.py b/InternalPythonModules/android/cachelocation.py index 680db6d6e6..019c03c654 100755 --- a/InternalPythonModules/android/cachelocation.py +++ b/InternalPythonModules/android/cachelocation.py @@ -121,7 +121,7 @@ class CacheLocationAnalyzer(general.AndroidComponentAnalyzer): inputStream.read(tempBytes) timestamp = BigInteger(tempBytes).longValue() / 1000 - attributes = ArrayList<>() + attributes = ArrayList() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT) attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, AndroidAnalyzer.MODULE_NAME, latitude)) attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, AndroidAnalyzer.MODULE_NAME, longitude)) diff --git a/InternalPythonModules/android/calllog.py b/InternalPythonModules/android/calllog.py index c3a65f8f38..6b9cb956d8 100755 --- a/InternalPythonModules/android/calllog.py +++ b/InternalPythonModules/android/calllog.py @@ -120,7 +120,7 @@ class CallLogAnalyzer(general.AndroidComponentAnalyzer): name = resultSet.getString("name") # name of person dialed or called. None if unregistered try: - attributes = ArrayList<>() + attributes = ArrayList() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG) # create a call log and then add attributes from result set. if direction == CallLogAnalyzer.OUTGOING: attributes.add(BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, general.MODULE_NAME, number)) diff --git a/InternalPythonModules/android/contact.py b/InternalPythonModules/android/contact.py index 75768b8a8e..22eb681061 100755 --- a/InternalPythonModules/android/contact.py +++ b/InternalPythonModules/android/contact.py @@ -119,7 +119,7 @@ class ContactAnalyzer(general.AndroidComponentAnalyzer): + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" + "ORDER BY raw_contacts.display_name ASC;") - attributes = ArrayList<>() + attributes = ArrayList() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT) oldName = "" while resultSet.next(): diff --git a/InternalPythonModules/android/googlemaplocation.py b/InternalPythonModules/android/googlemaplocation.py index 3b4a265937..10a1542568 100755 --- a/InternalPythonModules/android/googlemaplocation.py +++ b/InternalPythonModules/android/googlemaplocation.py @@ -97,7 +97,7 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): source_lat = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("source_lat")) source_lng = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("source_lng")) - attributes = ArrayList<>() + attributes = ArrayList() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE) attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, general.MODULE_NAME, "Destination")) attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, time)) diff --git a/InternalPythonModules/android/tangomessage.py b/InternalPythonModules/android/tangomessage.py index 5ba6ad0339..9a792064da 100755 --- a/InternalPythonModules/android/tangomessage.py +++ b/InternalPythonModules/android/tangomessage.py @@ -95,7 +95,7 @@ class TangoMessageAnalyzer(general.AndroidComponentAnalyzer): direction = "Outgoing" payload = resultSet.getString("payload") - attributes = ArrayList<>() + attributes = ArrayList() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) #create a call log and then add attributes from result set. attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, create_time)) attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, direction)) diff --git a/InternalPythonModules/android/textmessage.py b/InternalPythonModules/android/textmessage.py index 221023ce44..55bb563fea 100755 --- a/InternalPythonModules/android/textmessage.py +++ b/InternalPythonModules/android/textmessage.py @@ -93,7 +93,7 @@ class TextMessageAnalyzer(general.AndroidComponentAnalyzer): read = resultSet.getInt("read") # may be unread = 0, read = 1 subject = resultSet.getString("subject") # message subject body = resultSet.getString("body") # message body - attributes = ArrayList<>() + attributes = ArrayList() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); #create Message artifact and then add attributes from result set. if resultSet.getString("type") == "1": attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, general.MODULE_NAME, "Incoming")) diff --git a/InternalPythonModules/android/wwfmessage.py b/InternalPythonModules/android/wwfmessage.py index 1fe80a099d..941e81f329 100755 --- a/InternalPythonModules/android/wwfmessage.py +++ b/InternalPythonModules/android/wwfmessage.py @@ -88,7 +88,7 @@ class WWFMessageAnalyzer(general.AndroidComponentAnalyzer): user_id = resultSet.getString("user_id") # the ID of the user who sent the message. game_id = resultSet.getString("game_id") # ID of the game which the the message was sent. - attributes = ArrayList<>() + attributes = ArrayList() artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE) # create a call log and then add attributes from result set. attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, created_at)) attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, user_id)) diff --git a/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py b/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py index 5900f4f04f..2aa5d9d9a4 100755 --- a/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py +++ b/pythonExamples/Aug2015DataSourceTutorial/FindContactsDb.py @@ -163,7 +163,7 @@ class ContactsDbIngestModule(DataSourceIngestModule): # Make an artifact on the blackboard, TSK_CONTACT and give it attributes for each of the fields art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT) - attributes = ArrayList<>() + attributes = ArrayList() attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME_PERSON.getTypeID(), ContactsDbIngestModuleFactory.moduleName, name)) From 30615f5b7d711161d91e3635ba61e9bbe61cfe82 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\zhaohui" Date: Fri, 17 Nov 2017 11:06:29 -0500 Subject: [PATCH 19/90] 3207: fix typo --- InternalPythonModules/android/googlemaplocation.py | 2 +- InternalPythonModules/android/wwfmessage.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/InternalPythonModules/android/googlemaplocation.py b/InternalPythonModules/android/googlemaplocation.py index 10a1542568..444c0477ee 100755 --- a/InternalPythonModules/android/googlemaplocation.py +++ b/InternalPythonModules/android/googlemaplocation.py @@ -109,7 +109,7 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION, general.MODULE_NAME, dest_address)) attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, general.MODULE_NAME, "Google Maps History")) - aritfact.addAttributes(attributes) + artifact.addAttributes(attributes) try: # index the artifact for keyword search blackboard = Case.getCurrentCase().getServices().getBlackboard() diff --git a/InternalPythonModules/android/wwfmessage.py b/InternalPythonModules/android/wwfmessage.py index 941e81f329..e880cc1759 100755 --- a/InternalPythonModules/android/wwfmessage.py +++ b/InternalPythonModules/android/wwfmessage.py @@ -26,6 +26,7 @@ from java.sql import ResultSet from java.sql import SQLException from java.sql import Statement from java.util.logging import Level +from java.util import ArrayList from org.sleuthkit.autopsy.casemodule import Case from org.sleuthkit.autopsy.casemodule.services import Blackboard from org.sleuthkit.autopsy.casemodule.services import FileManager @@ -96,7 +97,7 @@ class WWFMessageAnalyzer(general.AndroidComponentAnalyzer): attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, general.MODULE_NAME, message)) attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, general.MODULE_NAME, "Words With Friends Message")) - artifact.addAttrisbutes(attributes) + artifact.addAttributes(attributes) try: # index the artifact for keyword search blackboard = Case.getCurrentCase().getServices().getBlackboard() From b871974e7b254ff308aa277cb7a69002d1e0585f Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 17 Nov 2017 12:58:11 -0500 Subject: [PATCH 20/90] Crypto module created for detecting encrypted files. --- Core/nbproject/project.xml | 1 + .../CryptoDetectionFileIngestModule.java | 242 ++++++++++++++++++ .../crypto/CryptoDetectionModuleFactory.java | 73 ++++++ 3 files changed, 316 insertions(+) create mode 100755 Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 987b2ffe78..e5778c0955 100755 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -313,6 +313,7 @@ org.sleuthkit.autopsy.ingest org.sleuthkit.autopsy.keywordsearchservice org.sleuthkit.autopsy.menuactions + org.sleuthkit.autopsy.modules.crypto org.sleuthkit.autopsy.modules.filetypeid org.sleuthkit.autopsy.modules.hashdatabase org.sleuthkit.autopsy.modules.vmextractor diff --git a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java new file mode 100755 index 0000000000..93db6697e7 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java @@ -0,0 +1,242 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2017 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.modules.crypto; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.logging.Level; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.services.Blackboard; +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.IngestModule; +import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; +import org.sleuthkit.autopsy.ingest.IngestServices; +import org.sleuthkit.autopsy.ingest.ModuleDataEvent; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.ReadContentInputStream; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; + +/** + * File ingest module to detect encryption. + */ +final class CryptoDetectionFileIngestModule implements FileIngestModule { + + private static final double ENTROPY_FACTOR = 1.4426950408889634073599246810019; // (1 / log(2)) + + private static final Logger LOGGER = Logger.getLogger(CryptoDetectionFileIngestModule.class.getName()); + private final IngestServices SERVICES = IngestServices.getInstance(); + private long jobId; + private static final IngestModuleReferenceCounter REF_COUNTER = new IngestModuleReferenceCounter(); + private FileTypeDetector fileTypeDetector; + private Blackboard blackboard; + + /** + * Create a CryptoDetectionFileIngestModule object that will detect files + * that are encrypted and create blackboard artifacts as appropriate. + */ + CryptoDetectionFileIngestModule() { + } + + @Override + public void startUp(IngestJobContext context) throws IngestModule.IngestModuleException { + jobId = context.getJobId(); + REF_COUNTER.incrementAndGet(jobId); + try { + fileTypeDetector = new FileTypeDetector(); + } catch (FileTypeDetector.FileTypeDetectorInitException ex) { + throw new IngestModule.IngestModuleException("Failed to create file type detector", ex); + } + } + + @Override + public IngestModule.ProcessResult process(AbstractFile content) { + blackboard = Case.getCurrentCase().getServices().getBlackboard(); + + if (isFileSupported(content)) { + return processFile(content); + } + + return IngestModule.ProcessResult.OK; + } + + /** + * Process the file. If the file has an entropy value greater than seven, + * create a blackboard artifact. + * + * @param The file to be processed. + * + * @return 'OK' if the file was processed successfully, or 'ERROR' if there + * was a problem. + */ + private IngestModule.ProcessResult processFile(AbstractFile f) { + try { + double entropy = calculateEntropy(f); + if (entropy > 7.5) { + BlackboardArtifact artifact = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED); + + try { + /* + * Index the artifact for keyword search. + */ + blackboard.indexArtifact(artifact); + } catch (Blackboard.BlackboardException ex) { + LOGGER.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex); //NON-NLS + MessageNotifyUtil.Notify.error("Failed to index encryption detected artifact for keyword search.", artifact.getDisplayName()); + } + + /* + * Send an event to update the view with the new result. + */ + SERVICES.fireModuleDataEvent(new ModuleDataEvent(CryptoDetectionModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED, Collections.singletonList(artifact))); + } + + return IngestModule.ProcessResult.OK; + } catch (TskCoreException ex) { + LOGGER.log(Level.WARNING, "Failed to create blackboard artifact ({0}).", ex.getLocalizedMessage()); //NON-NLS + return IngestModule.ProcessResult.ERROR; + } catch (IOException ex) { + LOGGER.log(Level.WARNING, String.format("Failed to calculate the entropy for '%s'.", Paths.get(f.getParentPath(), f.getName())), ex); //NON-NLS + return IngestModule.ProcessResult.ERROR; + } + } + + /** + * Calculate the entropy of the file. The result is used to qualify the file + * as an encrypted file. + * + * @param file The file to be calculated against. + * + * @return The entropy of the file. + * + * @throws IOException If there is a failure closing or reading from the + * InputStream. + */ + private double calculateEntropy(AbstractFile file) throws IOException { + InputStream in = null; + BufferedInputStream bin = null; + + try { + in = new ReadContentInputStream(file); + bin = new BufferedInputStream(in); + + /* + * Determine the number of times each byte value appears. + */ + int[] byteOccurences = new int[256]; + int mostRecentByte = 0; + int readByte; + while ((readByte = bin.read()) != -1) { + byteOccurences[readByte]++; + mostRecentByte = readByte; + } + byteOccurences[mostRecentByte]--; + + /* + * Calculate the entropy based on the byte occurence counts. + */ + long dataLength = file.getSize() - 1; + double entropy = 0; + for (int i = 0; i < 256; i++) { + if (byteOccurences[i] > 0) { + double byteProbability = (double) byteOccurences[i] / (double) dataLength; + entropy += (byteProbability * Math.log(byteProbability) * ENTROPY_FACTOR); + } + } + + return -entropy; + + } catch (IOException ex) { + LOGGER.log(Level.WARNING, "IOException occurred while trying to read data from InputStream.", ex); //NON-NLS + throw ex; + } finally { + try { + if (in != null) { + in.close(); + } + if (bin != null) { + bin.close(); + } + } catch (IOException ex) { + LOGGER.log(Level.WARNING, "Failed to close InputStream.", ex); //NON-NLS + throw ex; + } + } + } + + /** + * This method checks if the AbstractFile input is supported. To qualify, it + * must be an actual file that is not known, has a size that's evenly + * divisible by 512 and a minimum size of 5MB, and has a MIME type of + * 'application/octet-stream'. + * + * @param file AbstractFile to be checked. + * + * @return True if the AbstractFile qualifies. + */ + private boolean isFileSupported(AbstractFile file) { + boolean supported = false; + + /* + * Qualify the file type. + */ + if (!file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) && + !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) && + !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR) && + !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR)) { + /* + * Qualify the file against hash databases. + */ + if (!file.getKnown().equals(TskData.FileKnown.KNOWN)) { + /* + * Qualify the size. + */ + long contentSize = file.getSize(); + if (contentSize >= 0x500000 && (contentSize & 511) == 0) { + /* + * Qualify the MIME type. + */ + try { + String mimeType = fileTypeDetector.getFileType(file); + if (mimeType != null && mimeType.equals("application/octet-stream")) { + supported = true; + } + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Failed to detect file type", ex); //NON-NLS + } + } + } + } + + return supported; + } + + @Override + public void shutDown() { + REF_COUNTER.decrementAndGet(jobId); + } +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java new file mode 100755 index 0000000000..de3d518ee2 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java @@ -0,0 +1,73 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2017 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.modules.crypto; + +import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.coreutils.Version; +import org.sleuthkit.autopsy.ingest.FileIngestModule; +import org.sleuthkit.autopsy.ingest.IngestModuleFactory; +import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; + +/** + * A factory that creates file ingest modules that detect encryption. + */ +@ServiceProvider(service = IngestModuleFactory.class) +@Messages({ + "CryptoDetectionFileIngestModule.moduleName.text=Crypto Detection", + "CryptoDetectionFileIngestModule.getDesc.text=Looks for files that are encrypted and have an entropy greater than seven." +}) +public class CryptoDetectionModuleFactory extends IngestModuleFactoryAdapter { + + @Override + public String getModuleDisplayName() { + return getModuleName(); + } + + /** + * Get the name of the module. + * + * @return The module name. + */ + static String getModuleName() { + return NbBundle.getMessage(CryptoDetectionFileIngestModule.class, "CryptoDetectionFileIngestModule.moduleName.text"); + } + + @Override + public String getModuleDescription() { + return NbBundle.getMessage(CryptoDetectionFileIngestModule.class, "CryptoDetectionFileIngestModule.getDesc.text"); + } + + @Override + public String getModuleVersionNumber() { + return Version.getVersion(); + } + + @Override + public boolean isFileIngestModuleFactory() { + return true; + } + + @Override + public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings ingestOptions) { + return new CryptoDetectionFileIngestModule(); + } +} \ No newline at end of file From 39cd68aca65ee573b54ba6c4612889ef6b9c48eb Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 17 Nov 2017 13:38:55 -0500 Subject: [PATCH 21/90] Minor tweaks. --- .../crypto/CryptoDetectionFileIngestModule.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java index 93db6697e7..ea0e806b14 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java @@ -137,6 +137,10 @@ final class CryptoDetectionFileIngestModule implements FileIngestModule { * InputStream. */ private double calculateEntropy(AbstractFile file) throws IOException { + /* + * Logic in this method is based on + * https://github.com/willjasen/entropy/blob/master/entropy.java + */ InputStream in = null; BufferedInputStream bin = null; @@ -200,6 +204,11 @@ final class CryptoDetectionFileIngestModule implements FileIngestModule { */ private boolean isFileSupported(AbstractFile file) { boolean supported = false; + + /* + * Criteria for the checks in this method are partially based on + * http://www.forensicswiki.org/wiki/TrueCrypt#Detection + */ /* * Qualify the file type. @@ -216,7 +225,7 @@ final class CryptoDetectionFileIngestModule implements FileIngestModule { * Qualify the size. */ long contentSize = file.getSize(); - if (contentSize >= 0x500000 && (contentSize & 511) == 0) { + if (contentSize >= 5242880 && (contentSize % 512) == 0) { /* * Qualify the MIME type. */ From 6bb2701776b781dfb26d0e074f1b8078bf9e01c3 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 17 Nov 2017 14:02:08 -0500 Subject: [PATCH 22/90] Minor tweaks. --- .../CryptoDetectionFileIngestModule.java | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java index ea0e806b14..60c1040359 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java @@ -46,7 +46,7 @@ import org.sleuthkit.datamodel.TskData; */ final class CryptoDetectionFileIngestModule implements FileIngestModule { - private static final double ENTROPY_FACTOR = 1.4426950408889634073599246810019; // (1 / log(2)) + private static final double ONE_OVER_LOG2 = 1.4426950408889634073599246810019; // (1 / log(2)) private static final Logger LOGGER = Logger.getLogger(CryptoDetectionFileIngestModule.class.getName()); private final IngestServices SERVICES = IngestServices.getInstance(); @@ -152,13 +152,10 @@ final class CryptoDetectionFileIngestModule implements FileIngestModule { * Determine the number of times each byte value appears. */ int[] byteOccurences = new int[256]; - int mostRecentByte = 0; int readByte; while ((readByte = bin.read()) != -1) { byteOccurences[readByte]++; - mostRecentByte = readByte; } - byteOccurences[mostRecentByte]--; /* * Calculate the entropy based on the byte occurence counts. @@ -168,7 +165,7 @@ final class CryptoDetectionFileIngestModule implements FileIngestModule { for (int i = 0; i < 256; i++) { if (byteOccurences[i] > 0) { double byteProbability = (double) byteOccurences[i] / (double) dataLength; - entropy += (byteProbability * Math.log(byteProbability) * ENTROPY_FACTOR); + entropy += (byteProbability * Math.log(byteProbability) * ONE_OVER_LOG2); } } @@ -203,20 +200,20 @@ final class CryptoDetectionFileIngestModule implements FileIngestModule { * @return True if the AbstractFile qualifies. */ private boolean isFileSupported(AbstractFile file) { - boolean supported = false; - /* * Criteria for the checks in this method are partially based on * http://www.forensicswiki.org/wiki/TrueCrypt#Detection */ + boolean supported = false; + /* * Qualify the file type. */ - if (!file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) && - !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) && - !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR) && - !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR)) { + if (!file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) + && !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) + && !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR) + && !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR)) { /* * Qualify the file against hash databases. */ @@ -248,4 +245,4 @@ final class CryptoDetectionFileIngestModule implements FileIngestModule { public void shutDown() { REF_COUNTER.decrementAndGet(jobId); } -} \ No newline at end of file +} From 7c0cbe098ebbbbf9757f41b0f8c0f8b253286abd Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 17 Nov 2017 14:11:56 -0500 Subject: [PATCH 23/90] Typo fixed. --- .../autopsy/modules/crypto/CryptoDetectionModuleFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java index de3d518ee2..2b6e7c25f8 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java @@ -33,7 +33,7 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; @ServiceProvider(service = IngestModuleFactory.class) @Messages({ "CryptoDetectionFileIngestModule.moduleName.text=Crypto Detection", - "CryptoDetectionFileIngestModule.getDesc.text=Looks for files that are encrypted and have an entropy greater than seven." + "CryptoDetectionFileIngestModule.getDesc.text=Looks for files that are encrypted and have an entropy greater than 7.5." }) public class CryptoDetectionModuleFactory extends IngestModuleFactoryAdapter { From 7a55b65989b1c112d09ea279414eddc52727f669 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 17 Nov 2017 14:23:23 -0500 Subject: [PATCH 24/90] Updated description to be more generic. --- .../autopsy/modules/crypto/CryptoDetectionModuleFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java index 2b6e7c25f8..f40b2a3490 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java @@ -33,7 +33,7 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; @ServiceProvider(service = IngestModuleFactory.class) @Messages({ "CryptoDetectionFileIngestModule.moduleName.text=Crypto Detection", - "CryptoDetectionFileIngestModule.getDesc.text=Looks for files that are encrypted and have an entropy greater than 7.5." + "CryptoDetectionFileIngestModule.getDesc.text=Looks for large files with high entropy." }) public class CryptoDetectionModuleFactory extends IngestModuleFactoryAdapter { From 0b27196ad415bca34d7baac43cb6312e98f919e4 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 17 Nov 2017 15:37:19 -0500 Subject: [PATCH 25/90] 3201 merge changes from 3199 and resolve conflicts --- .../services/TagNameDefinition.java | 34 +++++++++++++++--- .../casemodule/services/TagNameDialog.java | 8 ++--- .../casemodule/services/TagOptionsPanel.java | 2 +- .../casemodule/services/TagsManager.java | 35 +------------------ .../datamodel/DrawableTagsManager.java | 4 +-- 5 files changed, 38 insertions(+), 45 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java index 211bbe82e4..c9458dfbd7 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2016 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,9 +25,14 @@ import java.util.List; import java.util.Objects; import java.util.Set; import javax.annotation.concurrent.Immutable; +import org.openide.util.Exceptions; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; /** @@ -36,11 +41,14 @@ import org.sleuthkit.datamodel.TskData; @Immutable final class TagNameDefinition implements Comparable { + @NbBundle.Messages({"TagNameDefinition.predefTagNames.bookmark.text=Bookmark", + "TagNameDefinition.predefTagNames.followUp.text=Follow Up", + "TagNameDefinition.predefTagNames.notableItem.text=Notable Item"}) private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS - private static final List STANDARD_NOTABLE_TAG_DISPLAY_NAMES = Arrays.asList(TagsManager.getNotableItemText(), Category.ONE.getDisplayName(), Category.TWO.getDisplayName(), Category.THREE.getDisplayName()); // NON-NLS - static final List STANDARD_TAG_DISPLAY_NAMES = Arrays.asList(TagsManager.getBookmarkText(), TagsManager.getFollowUpText(), - TagsManager.getNotableItemText(), Category.ONE.getDisplayName(), + private static final List STANDARD_NOTABLE_TAG_DISPLAY_NAMES = Arrays.asList(Bundle.TagNameDefinition_predefTagNames_notableItem_text(), Category.ONE.getDisplayName(), Category.TWO.getDisplayName(), Category.THREE.getDisplayName()); // NON-NLS + private static final List STANDARD_TAG_DISPLAY_NAMES = Arrays.asList(Bundle.TagNameDefinition_predefTagNames_bookmark_text(), Bundle.TagNameDefinition_predefTagNames_followUp_text(), + Bundle.TagNameDefinition_predefTagNames_notableItem_text(), Category.ONE.getDisplayName(), Category.TWO.getDisplayName(), Category.THREE.getDisplayName(), Category.FOUR.getDisplayName(), Category.FIVE.getDisplayName()); private final String displayName; @@ -65,6 +73,10 @@ final class TagNameDefinition implements Comparable { this.knownStatus = status; } + static List getStandardTagNames() { + return STANDARD_TAG_DISPLAY_NAMES; + } + /** * Gets the display name for the tag name. * @@ -165,6 +177,16 @@ final class TagNameDefinition implements Comparable { return displayName + "," + description + "," + color.name() + "," + knownStatus.toString(); } + private TagName saveToCase(SleuthkitCase caseDb) { + TagName tagName = null; + try { + tagName = caseDb.addTagName(displayName, description, color, knownStatus); + } catch (TskCoreException ex) { + Exceptions.printStackTrace(ex); + } + return tagName; + } + /** * Gets tag name definitions from the tag settings file as well as the * default tag name definitions. @@ -221,6 +243,10 @@ final class TagNameDefinition implements Comparable { setting.append(";"); } setting.append(tagName.toSettingsFormat()); + if (Case.isCaseOpen()) { + SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase(); + tagName.saveToCase(caseDb); + } } ModuleSettings.setConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY, setting.toString()); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java index e310c066e5..c8d1351763 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2016 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -135,10 +135,10 @@ final class TagNameDialog extends javax.swing.JDialog { NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameEmpty.title"), JOptionPane.ERROR_MESSAGE); return; - } - + } //if a tag name contains illegal characters and is not the name of one of the standard tags - if (TagsManager.containsIllegalCharacters(newTagDisplayName) && !TagNameDefinition.STANDARD_TAG_DISPLAY_NAMES.contains(newTagDisplayName)) { + if (TagsManager.containsIllegalCharacters(newTagDisplayName) && !TagNameDefinition.getStandardTagNames().contains(newTagDisplayName)) { + JOptionPane.showMessageDialog(null, NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameIllegalCharacters.message"), NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameIllegalCharacters.title"), diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java index fd3663ea7a..61314e6f1f 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java @@ -411,7 +411,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { boolean isSelected = tagNamesList.getSelectedIndex() != -1; boolean enableEdit = !ingestIsRunning && isSelected; editTagNameButton.setEnabled(enableEdit); - boolean enableDelete = enableEdit && !TagNameDefinition.STANDARD_TAG_DISPLAY_NAMES.contains(tagNamesList.getSelectedValue().getDisplayName()); + boolean enableDelete = enableEdit && !TagNameDefinition.getStandardTagNames().contains(tagNamesList.getSelectedValue().getDisplayName()); deleteTagNameButton.setEnabled(enableDelete); if (isSelected) { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index 49b25b54db..5699034f7b 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -27,7 +27,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; -import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -46,41 +45,9 @@ import org.sleuthkit.datamodel.TskData; public class TagsManager implements Closeable { private static final Logger LOGGER = Logger.getLogger(TagsManager.class.getName()); - @NbBundle.Messages({"TagsManager.predefTagNames.bookmark.text=Bookmark", - "TagsManager.predefTagNames.followUp.text=Follow Up", - "TagsManager.predefTagNames.notableItem.text=Notable Item"}) - private static final String FOLLOW_UP = Bundle.TagsManager_predefTagNames_followUp_text(); - private static final String BOOKMARK = Bundle.TagsManager_predefTagNames_bookmark_text(); - private static final String NOTABLE_ITEM = Bundle.TagsManager_predefTagNames_notableItem_text(); + private final SleuthkitCase caseDb; - /** - * Get the text for the Follow Up tag. - * - * @return FOLLOW_UP - */ - public static String getFollowUpText() { - return FOLLOW_UP; - } - - /** - * Get the text for the Bookmark tag. - * - * @return BOOKMARK - */ - public static String getBookmarkText() { - return BOOKMARK; - } - - /** - * Get the text for the Notable Item tag. - * - * @return NOTABLE_ITEM - */ - static String getNotableItemText() { - return NOTABLE_ITEM; - } - /** * Tests whether or not a given tag display name contains an illegal * character. diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java index 6859a12830..0497068924 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java @@ -138,7 +138,7 @@ public class DrawableTagsManager { public TagName getFollowUpTagName() throws TskCoreException { synchronized (autopsyTagsManagerLock) { if (Objects.isNull(followUpTagName)) { - followUpTagName = getTagName(TagsManager.getFollowUpText()); + followUpTagName = getTagName(NbBundle.getMessage(DrawableTagsManager.class, "DrawableTagsManager.followUp")); } return followUpTagName; } @@ -147,7 +147,7 @@ public class DrawableTagsManager { private Object getBookmarkTagName() throws TskCoreException { synchronized (autopsyTagsManagerLock) { if (Objects.isNull(bookmarkTagName)) { - bookmarkTagName = getTagName(TagsManager.getBookmarkText()); + bookmarkTagName = getTagName(NbBundle.getMessage(DrawableTagsManager.class, "DrawableTagsManager.bookMark")); } return bookmarkTagName; } From eef2e81246dc256ae2a05945d25114f10074078c Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Fri, 17 Nov 2017 16:04:24 -0500 Subject: [PATCH 26/90] Added message inbox integration and modified logging. --- .../CryptoDetectionFileIngestModule.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java index 60c1040359..f3f821d2e1 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java @@ -30,6 +30,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.IngestModule; import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; import org.sleuthkit.autopsy.ingest.IngestServices; @@ -48,8 +49,8 @@ final class CryptoDetectionFileIngestModule implements FileIngestModule { private static final double ONE_OVER_LOG2 = 1.4426950408889634073599246810019; // (1 / log(2)) - private static final Logger LOGGER = Logger.getLogger(CryptoDetectionFileIngestModule.class.getName()); private final IngestServices SERVICES = IngestServices.getInstance(); + private final Logger LOGGER = SERVICES.getLogger(CryptoDetectionModuleFactory.getModuleName()); private long jobId; private static final IngestModuleReferenceCounter REF_COUNTER = new IngestModuleReferenceCounter(); private FileTypeDetector fileTypeDetector; @@ -106,13 +107,26 @@ final class CryptoDetectionFileIngestModule implements FileIngestModule { blackboard.indexArtifact(artifact); } catch (Blackboard.BlackboardException ex) { LOGGER.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex); //NON-NLS - MessageNotifyUtil.Notify.error("Failed to index encryption detected artifact for keyword search.", artifact.getDisplayName()); + MessageNotifyUtil.Notify.show("Failed to index encryption detected artifact for keyword search.", artifact.getDisplayName(), MessageNotifyUtil.MessageType.ERROR); } /* * Send an event to update the view with the new result. */ SERVICES.fireModuleDataEvent(new ModuleDataEvent(CryptoDetectionModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED, Collections.singletonList(artifact))); + + /* + * Make an ingest inbox message. + */ + StringBuilder detailsSb = new StringBuilder(); + detailsSb.append("File: " + f.getParentPath() + f.getName() + "
\n"); + detailsSb.append("Entropy: " + entropy); + + SERVICES.postMessage(IngestMessage.createDataMessage(CryptoDetectionModuleFactory.getModuleName(), + "Encryption Detected Match: " + f.getName(), + detailsSb.toString(), + f.getName(), + artifact)); } return IngestModule.ProcessResult.OK; From 8533ce98fb56bf14ecdb55e4c4ed3017e918f88e Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 17 Nov 2017 17:13:02 -0500 Subject: [PATCH 27/90] 3201 merge changes from 3199 regarding refactor of addTagName method name --- .../autopsy/casemodule/services/TagNameDefinition.java | 2 +- .../sleuthkit/autopsy/casemodule/services/TagNameDialog.java | 3 +-- .../org/sleuthkit/autopsy/casemodule/services/TagsManager.java | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java index c9458dfbd7..2153b35522 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java @@ -180,7 +180,7 @@ final class TagNameDefinition implements Comparable { private TagName saveToCase(SleuthkitCase caseDb) { TagName tagName = null; try { - tagName = caseDb.addTagName(displayName, description, color, knownStatus); + tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatus); } catch (TskCoreException ex) { Exceptions.printStackTrace(ex); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java index c8d1351763..f923717760 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java @@ -135,10 +135,9 @@ final class TagNameDialog extends javax.swing.JDialog { NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameEmpty.title"), JOptionPane.ERROR_MESSAGE); return; - } + } //if a tag name contains illegal characters and is not the name of one of the standard tags if (TagsManager.containsIllegalCharacters(newTagDisplayName) && !TagNameDefinition.getStandardTagNames().contains(newTagDisplayName)) { - JOptionPane.showMessageDialog(null, NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameIllegalCharacters.message"), NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameIllegalCharacters.title"), diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index 5699034f7b..de16d9456f 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -255,7 +255,7 @@ public class TagsManager implements Closeable { */ public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus) throws TagNameAlreadyExistsException, TskCoreException { try { - TagName tagName = caseDb.addTagName(displayName, description, color, knownStatus); + TagName tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatus); Set customTypes = TagNameDefinition.getTagNameDefinitions(); customTypes.add(new TagNameDefinition(displayName, description, color, knownStatus)); TagNameDefinition.setTagNameDefinitions(customTypes); From 4bc8d85acdcc4dc52ed55f2c05b826bae01c2f80 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 17 Nov 2017 19:08:59 -0500 Subject: [PATCH 28/90] 3199 clean up read Tags properties code and rename Category to DhsImageCategory --- .../casemodule/services/TagNameDefiniton.java | 114 +++++++++++++----- .../Category.java => DhsImageCategory.java} | 20 +-- .../actions/CategorizeAction.java | 30 ++--- .../actions/CategorizeGroupAction.java | 14 +-- .../CategorizeSelectedFilesAction.java | 4 +- .../datamodel/CategoryManager.java | 54 ++++----- .../datamodel/DrawableAttribute.java | 8 +- .../imagegallery/datamodel/DrawableDB.java | 10 +- .../imagegallery/datamodel/DrawableFile.java | 14 +-- .../datamodel/DrawableTagsManager.java | 4 +- .../datamodel/grouping/GroupManager.java | 12 +- .../imagegallery/gui/SummaryTablePane.java | 16 +-- .../autopsy/imagegallery/gui/Toolbar.java | 6 +- .../gui/drawableviews/DrawableView.java | 24 ++-- .../gui/drawableviews/GroupPane.java | 26 ++-- .../gui/drawableviews/MetaDataPane.java | 4 +- .../gui/drawableviews/SlideShowView.java | 8 +- 17 files changed, 210 insertions(+), 158 deletions(-) rename Core/src/org/sleuthkit/autopsy/datamodel/{tags/Category.java => DhsImageCategory.java} (85%) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java index 8c7d29baa3..e2fa9f4af4 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java @@ -24,13 +24,14 @@ import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.logging.Level; import javax.annotation.concurrent.Immutable; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.datamodel.TagName; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; @@ -41,17 +42,18 @@ import org.sleuthkit.datamodel.TskData; @Immutable final class TagNameDefiniton implements Comparable { + private static final Logger LOGGER = Logger.getLogger(TagNameDefiniton.class.getName()); @NbBundle.Messages({"TagNameDefiniton.predefTagNames.bookmark.text=Bookmark", "TagNameDefiniton.predefTagNames.followUp.text=Follow Up", "TagNameDefiniton.predefTagNames.notableItem.text=Notable Item"}) private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS - private static final List STANDARD_NOTABLE_TAG_DISPLAY_NAMES = Arrays.asList(Bundle.TagNameDefiniton_predefTagNames_notableItem_text(), Category.ONE.getDisplayName(), Category.TWO.getDisplayName(), Category.THREE.getDisplayName()); // NON-NLS + private static final List STANDARD_NOTABLE_TAG_DISPLAY_NAMES = Arrays.asList(Bundle.TagNameDefiniton_predefTagNames_notableItem_text(), DhsImageCategory.ONE.getDisplayName(), DhsImageCategory.TWO.getDisplayName(), DhsImageCategory.THREE.getDisplayName()); // NON-NLS private static final List STANDARD_TAG_DISPLAY_NAMES = Arrays.asList(Bundle.TagNameDefiniton_predefTagNames_bookmark_text(), Bundle.TagNameDefiniton_predefTagNames_followUp_text(), - Bundle.TagNameDefiniton_predefTagNames_notableItem_text(), Category.ONE.getDisplayName(), - Category.TWO.getDisplayName(), Category.THREE.getDisplayName(), - Category.FOUR.getDisplayName(), Category.FIVE.getDisplayName()); + Bundle.TagNameDefiniton_predefTagNames_notableItem_text(), DhsImageCategory.ONE.getDisplayName(), + DhsImageCategory.TWO.getDisplayName(), DhsImageCategory.THREE.getDisplayName(), + DhsImageCategory.FOUR.getDisplayName(), DhsImageCategory.FIVE.getDisplayName()); private final String displayName; private final String description; private final TagName.HTML_COLOR color; @@ -182,7 +184,7 @@ final class TagNameDefiniton implements Comparable { try { tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatusDenoted); } catch (TskCoreException ex) { - Exceptions.printStackTrace(ex); + LOGGER.log(Level.SEVERE, "Error updating non-file object ", ex); } return tagName; } @@ -195,42 +197,92 @@ final class TagNameDefiniton implements Comparable { */ static synchronized Set getTagNameDefinitions() { Set tagNames = new HashSet<>(); - List standardTags = new ArrayList<>(STANDARD_TAG_DISPLAY_NAMES); //modifiable copy of default tags list for us to keep track of which ones already exist + //modifiable copy of default tags list for us to keep track of which default tags have already been created + Set standardTags = new HashSet<>(STANDARD_TAG_DISPLAY_NAMES); String setting = ModuleSettings.getConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY); if (null != setting && !setting.isEmpty()) { List tagNameTuples = Arrays.asList(setting.split(";")); - List notableTags = new ArrayList<>(); - String badTagsStr = ModuleSettings.getConfigSetting("CentralRepository", "db.badTags"); // NON-NLS - if (badTagsStr == null || badTagsStr.isEmpty()) { //if there were no bad tags in the central repo properties file use the default list - notableTags.addAll(STANDARD_NOTABLE_TAG_DISPLAY_NAMES); - } else { //otherwise use the list that was in the central repository properties file - notableTags.addAll(Arrays.asList(badTagsStr.split(","))); + int numberOfAttributes = 0; + if (tagNameTuples.size() > 0) { + // Determine if Tags.properties file needs to be upgraded + numberOfAttributes = tagNameTuples.get(0).split(",").length; } - for (String tagNameTuple : tagNameTuples) { //for each tag listed in the tags properties file - String[] tagNameAttributes = tagNameTuple.split(","); //get the attributes - if (tagNameAttributes.length == 3) { //if there are only 3 attributes so Tags.properties does not contain any tag definitions with knownStatus - standardTags.remove(tagNameAttributes[0]); //remove tag from default tags we need to create still - if (notableTags.contains(tagNameAttributes[0])) { //if tag should be notable mark create it as such - tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.BAD)); - } else { //otherwise create it as unknown - tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.UNKNOWN)); //add the default value for that tag - } - } else if (tagNameAttributes.length == 4) { //if there are 4 attributes its a current list we can use the values present - standardTags.remove(tagNameAttributes[0]); //remove tag from default tags we need to create still - tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.valueOf(tagNameAttributes[3]))); + if (numberOfAttributes == 3) { + // Upgrade Tags.Properties with the settings in Central Repository Settings if necessary + tagNames.addAll(upgradeTagPropertiesFile(tagNameTuples, standardTags)); + } else if (numberOfAttributes == 4) { + // if the Tags.Properties file is up to date parse it + tagNames.addAll(readCurrentTagPropertiesFile(tagNameTuples, standardTags)); + } + //create standard tags which should always exist which were not already created for whatever reason, such as upgrade + for (String standardTagName : standardTags) { + if (STANDARD_NOTABLE_TAG_DISPLAY_NAMES.contains(standardTagName)) { + tagNames.add(new TagNameDefiniton(standardTagName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.BAD)); + } else { + tagNames.add(new TagNameDefiniton(standardTagName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN)); } } } - for (String standardTagName : standardTags) { //create standard tags which should always exist which were not already created for whatever reason, such as upgrade - if (STANDARD_NOTABLE_TAG_DISPLAY_NAMES.contains(standardTagName)) { - tagNames.add(new TagNameDefiniton(standardTagName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.BAD)); - } else { - tagNames.add(new TagNameDefiniton(standardTagName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN)); + return tagNames; + + } + + /** + * Read the central repository properties file to get any knownStatus + * related tag settings that may exist in it. + * + * @param tagProperties the list of comma seperated tags in the + * Tags.properties file + * @param standardTagsToBeCreated the list of standard tags which have yet + * to be created + * + * @return tagNames a list of TagNameDefinitions + */ + private static Set upgradeTagPropertiesFile(List tagProperties, Set standardTagsToBeCreated) { + Set tagNames = new HashSet<>(); + List legacyNotableTags = new ArrayList<>(); + String badTagsStr = ModuleSettings.getConfigSetting("CentralRepository", "db.badTags"); // NON-NLS + if (badTagsStr == null || badTagsStr.isEmpty()) { //if there were no bad tags in the central repo properties file use the default list + legacyNotableTags.addAll(STANDARD_NOTABLE_TAG_DISPLAY_NAMES); + } else { //otherwise use the list that was in the central repository properties file + legacyNotableTags.addAll(Arrays.asList(badTagsStr.split(","))); + } + for (String tagNameTuple : tagProperties) { + String[] tagNameAttributes = tagNameTuple.split(","); //get the attributes + standardTagsToBeCreated.remove(tagNameAttributes[0]); //remove the tag from the list of standard tags which have not been created + if (legacyNotableTags.contains(tagNameAttributes[0])) { //if tag should be notable mark create it as such + tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], + TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.BAD)); + } else { //otherwise create it as unknown + tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], + TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.UNKNOWN)); //add the default value for that tag } } return tagNames; } + /** + * Read the Tags.properties file to get the TagNameDefinitions that are + * preserved accross cases. + * + * @param tagProperties the list of comma seperated tags in the + * Tags.properties file + * @param standardTagsToBeCreated the list of standard tags which have yet + * to be created + * + * @return tagNames a list of TagNameDefinitions + */ + private static Set readCurrentTagPropertiesFile(List tagProperties, Set standardTagsToBeCreated) { + Set tagNames = new HashSet<>(); + for (String tagNameTuple : tagProperties) { + String[] tagNameAttributes = tagNameTuple.split(","); //get the attributes + standardTagsToBeCreated.remove(tagNameAttributes[0]); //remove the tag from the list of standard tags which have not been created + tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], + TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.valueOf(tagNameAttributes[3]))); + } + return tagNames; + } + /** * Sets the tag name definitions in the tag settings file. * diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/tags/Category.java b/Core/src/org/sleuthkit/autopsy/datamodel/DhsImageCategory.java similarity index 85% rename from Core/src/org/sleuthkit/autopsy/datamodel/tags/Category.java rename to Core/src/org/sleuthkit/autopsy/datamodel/DhsImageCategory.java index 39d624110f..2357c61599 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/tags/Category.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DhsImageCategory.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datamodel.tags; +package org.sleuthkit.autopsy.datamodel; import com.google.common.collect.ImmutableList; import java.util.Map; @@ -38,6 +38,7 @@ import javafx.scene.layout.CornerRadii; import javafx.scene.layout.Region; import javafx.scene.paint.Color; import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.datamodel.Bundle; /** * Enum to represent the six categories in the DHS image categorization scheme. @@ -48,7 +49,7 @@ import org.openide.util.NbBundle; "Category.four=CAT-4: Exemplar/Comparison (Internal Use Only)", "Category.five=CAT-5: Non-pertinent", "Category.zero=CAT-0: Uncategorized"}) -public enum Category { +public enum DhsImageCategory { /* * This order of declaration is required so that Enum's compareTo method @@ -65,22 +66,21 @@ public enum Category { private static final BorderWidths BORDER_WIDTHS_2 = new BorderWidths(2); private static final CornerRadii CORNER_RADII_4 = new CornerRadii(4); - public static ImmutableList getNonZeroCategories() { + public static ImmutableList getNonZeroCategories() { return nonZeroCategories; } - private static final ImmutableList nonZeroCategories = - ImmutableList.of(Category.FIVE, Category.FOUR, Category.THREE, Category.TWO, Category.ONE); + private static final ImmutableList nonZeroCategories = + ImmutableList.of(DhsImageCategory.FIVE, DhsImageCategory.FOUR, DhsImageCategory.THREE, DhsImageCategory.TWO, DhsImageCategory.ONE); /** * map from displayName to enum value */ - private static final Map nameMap = - Stream.of(values()).collect(Collectors.toMap( - Category::getDisplayName, + private static final Map nameMap = + Stream.of(values()).collect(Collectors.toMap(DhsImageCategory::getDisplayName, Function.identity())); - public static Category fromDisplayName(String displayName) { + public static DhsImageCategory fromDisplayName(String displayName) { return nameMap.get(displayName); } @@ -99,7 +99,7 @@ public enum Category { private final int id; private Image snapshot; - private Category(Color color, int id, String name) { + private DhsImageCategory(Color color, int id, String name) { this.color = color; this.displayName = name; this.id = id; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java index e55078018e..3f8b3aecd0 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java @@ -40,7 +40,7 @@ import org.controlsfx.control.action.ActionUtils; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; @@ -60,15 +60,15 @@ public class CategorizeAction extends Action { private final ImageGalleryController controller; private final UndoRedoManager undoManager; - private final Category cat; + private final DhsImageCategory cat; private final Set selectedFileIDs; private final Boolean createUndo; - public CategorizeAction(ImageGalleryController controller, Category cat, Set selectedFileIDs) { + public CategorizeAction(ImageGalleryController controller, DhsImageCategory cat, Set selectedFileIDs) { this(controller, cat, selectedFileIDs, true); } - private CategorizeAction(ImageGalleryController controller, Category cat, Set selectedFileIDs, Boolean createUndo) { + private CategorizeAction(ImageGalleryController controller, DhsImageCategory cat, Set selectedFileIDs, Boolean createUndo) { super(cat.getDisplayName()); this.controller = controller; this.undoManager = controller.getUndoManager(); @@ -103,7 +103,7 @@ public class CategorizeAction extends Action { // Each category get an item in the sub-menu. Selecting one of these menu items adds // a tag with the associated category. - for (final Category cat : Category.values()) { + for (final DhsImageCategory cat : DhsImageCategory.values()) { MenuItem categoryItem = ActionUtils.createMenuItem(new CategorizeAction(controller, cat, selected)); getItems().add(categoryItem); } @@ -118,9 +118,9 @@ public class CategorizeAction extends Action { private final Set fileIDs; private final boolean createUndo; - private final Category cat; + private final DhsImageCategory cat; - CategorizeTask(Set fileIDs, @Nonnull Category cat, boolean createUndo) { + CategorizeTask(Set fileIDs, @Nonnull DhsImageCategory cat, boolean createUndo) { super(); this.fileIDs = fileIDs; java.util.Objects.requireNonNull(cat); @@ -132,14 +132,14 @@ public class CategorizeAction extends Action { public void run() { final DrawableTagsManager tagsManager = controller.getTagsManager(); final CategoryManager categoryManager = controller.getCategoryManager(); - Map oldCats = new HashMap<>(); + Map oldCats = new HashMap<>(); TagName tagName = categoryManager.getTagName(cat); - TagName catZeroTagName = categoryManager.getTagName(Category.ZERO); + TagName catZeroTagName = categoryManager.getTagName(DhsImageCategory.ZERO); for (long fileID : fileIDs) { try { DrawableFile file = controller.getFileFromId(fileID); //drawable db access if (createUndo) { - Category oldCat = file.getCategory(); //drawable db access + DhsImageCategory oldCat = file.getCategory(); //drawable db access TagName oldCatTagName = categoryManager.getTagName(oldCat); if (false == tagName.equals(oldCatTagName)) { oldCats.put(fileID, oldCat); @@ -147,7 +147,7 @@ public class CategorizeAction extends Action { } final List fileTags = tagsManager.getContentTags(file); - if (tagName == categoryManager.getTagName(Category.ZERO)) { + if (tagName == categoryManager.getTagName(DhsImageCategory.ZERO)) { // delete all cat tags for cat-0 fileTags.stream() .filter(tag -> CategoryManager.isCategoryTagName(tag.getName())) @@ -189,11 +189,11 @@ public class CategorizeAction extends Action { @Immutable private final class CategorizationChange implements UndoRedoManager.UndoableCommand { - private final Category newCategory; - private final ImmutableMap oldCategories; + private final DhsImageCategory newCategory; + private final ImmutableMap oldCategories; private final ImageGalleryController controller; - CategorizationChange(ImageGalleryController controller, Category newCategory, Map oldCategories) { + CategorizationChange(ImageGalleryController controller, DhsImageCategory newCategory, Map oldCategories) { this.controller = controller; this.newCategory = newCategory; this.oldCategories = ImmutableMap.copyOf(oldCategories); @@ -216,7 +216,7 @@ public class CategorizeAction extends Action { @Override public void undo() { - for (Map.Entry entry : oldCategories.entrySet()) { + for (Map.Entry entry : oldCategories.entrySet()) { new CategorizeAction(controller, entry.getValue(), Collections.singleton(entry.getKey()), false) .handle(null); } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java index 439bb59512..f568fbd105 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java @@ -38,7 +38,7 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.ImageGalleryPreferences; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import org.sleuthkit.datamodel.TskCoreException; /** @@ -49,7 +49,7 @@ public class CategorizeGroupAction extends CategorizeAction { private final static Logger LOGGER = Logger.getLogger(CategorizeGroupAction.class.getName()); - public CategorizeGroupAction(Category newCat, ImageGalleryController controller) { + public CategorizeGroupAction(DhsImageCategory newCat, ImageGalleryController controller) { super(controller, newCat, null); setEventHandler(actionEvent -> { ObservableList fileIDs = controller.viewState().get().getGroup().getFileIDs(); @@ -58,12 +58,12 @@ public class CategorizeGroupAction extends CategorizeAction { //if they have preveiously disabled the warning, just go ahead and apply categories. addCatToFiles(ImmutableSet.copyOf(fileIDs)); } else { - final Map catCountMap = new HashMap<>(); + final Map catCountMap = new HashMap<>(); for (Long fileID : fileIDs) { try { - Category category = controller.getFileFromId(fileID).getCategory(); - if (false == Category.ZERO.equals(category) && newCat.equals(category) == false) { + DhsImageCategory category = controller.getFileFromId(fileID).getCategory(); + if (false == DhsImageCategory.ZERO.equals(category) && newCat.equals(category) == false) { catCountMap.merge(category, 1L, Long::sum); } } catch (TskCoreException ex) { @@ -86,14 +86,14 @@ public class CategorizeGroupAction extends CategorizeAction { "CategorizeGroupAction.fileCountMessage={0} with {1}", "CategorizeGroupAction.dontShowAgain=Don't show this message again", "CategorizeGroupAction.fileCountHeader=Files in the following categories will have their categories overwritten: "}) - private void showConfirmationDialog(final Map catCountMap, Category newCat, ObservableList fileIDs) { + private void showConfirmationDialog(final Map catCountMap, DhsImageCategory newCat, ObservableList fileIDs) { ButtonType categorizeButtonType = new ButtonType(Bundle.CategorizeGroupAction_OverwriteButton_text(), ButtonBar.ButtonData.APPLY); VBox textFlow = new VBox(); - for (Map.Entry entry : catCountMap.entrySet()) { + for (Map.Entry entry : catCountMap.entrySet()) { if (entry.getKey().equals(newCat) == false) { if (entry.getValue() > 0) { Label label = new Label(Bundle.CategorizeGroupAction_fileCountMessage(entry.getValue(), entry.getKey().getDisplayName()), diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeSelectedFilesAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeSelectedFilesAction.java index be8c3644bb..bb8cd9de96 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeSelectedFilesAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeSelectedFilesAction.java @@ -19,14 +19,14 @@ package org.sleuthkit.autopsy.imagegallery.actions; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; /** * */ public class CategorizeSelectedFilesAction extends CategorizeAction { - public CategorizeSelectedFilesAction(Category cat, ImageGalleryController controller) { + public CategorizeSelectedFilesAction(DhsImageCategory cat, ImageGalleryController controller) { super(controller, cat, null); setEventHandler(actionEvent -> addCatToFiles(controller.getSelectionModel().getSelected()) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java index 33bc9a58d4..66aa6c578d 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java @@ -35,7 +35,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; @@ -80,13 +80,13 @@ public class CategoryManager { * the count related methods go through this cache, which loads initial * values from the database if needed. */ - private final LoadingCache categoryCounts = + private final LoadingCache categoryCounts = CacheBuilder.newBuilder().build(CacheLoader.from(this::getCategoryCountHelper)); /** * cached TagNames corresponding to Categories, looked up from * autopsyTagManager at initial request or if invalidated by case change. */ - private final LoadingCache catTagNameMap = + private final LoadingCache catTagNameMap = CacheBuilder.newBuilder().build(CacheLoader.from( cat -> getController().getTagsManager().getTagName(cat) )); @@ -119,18 +119,18 @@ public class CategoryManager { } /** - * get the number of file with the given {@link Category} + * get the number of file with the given {@link DhsImageCategory} * * @param cat get the number of files with Category = cat * * @return the number of files with the given Category */ - synchronized public long getCategoryCount(Category cat) { - if (cat == Category.ZERO) { + synchronized public long getCategoryCount(DhsImageCategory cat) { + if (cat == DhsImageCategory.ZERO) { // Keeping track of the uncategorized files is a bit tricky while ingest // is going on, so always use the list of file IDs we already have along with the // other category counts instead of trying to track it separately. - long allOtherCatCount = getCategoryCount(Category.ONE) + getCategoryCount(Category.TWO) + getCategoryCount(Category.THREE) + getCategoryCount(Category.FOUR) + getCategoryCount(Category.FIVE); + long allOtherCatCount = getCategoryCount(DhsImageCategory.ONE) + getCategoryCount(DhsImageCategory.TWO) + getCategoryCount(DhsImageCategory.THREE) + getCategoryCount(DhsImageCategory.FOUR) + getCategoryCount(DhsImageCategory.FIVE); return db.getNumberOfImageFilesInList() - allOtherCatCount; } else { return categoryCounts.getUnchecked(cat).sum(); @@ -139,24 +139,24 @@ public class CategoryManager { /** * increment the cached value for the number of files with the given - * {@link Category} + * {@link DhsImageCategory} * * @param cat the Category to increment */ - synchronized public void incrementCategoryCount(Category cat) { - if (cat != Category.ZERO) { + synchronized public void incrementCategoryCount(DhsImageCategory cat) { + if (cat != DhsImageCategory.ZERO) { categoryCounts.getUnchecked(cat).increment(); } } /** * decrement the cached value for the number of files with the given - * {@link Category} + * {@link DhsImageCategory} * * @param cat the Category to decrement */ - synchronized public void decrementCategoryCount(Category cat) { - if (cat != Category.ZERO) { + synchronized public void decrementCategoryCount(DhsImageCategory cat) { + if (cat != DhsImageCategory.ZERO) { categoryCounts.getUnchecked(cat).decrement(); } } @@ -171,7 +171,7 @@ public class CategoryManager { * @return a LongAdder whose value is set to the number of file with the * given Category */ - synchronized private LongAdder getCategoryCountHelper(Category cat) { + synchronized private LongAdder getCategoryCountHelper(DhsImageCategory cat) { LongAdder longAdder = new LongAdder(); longAdder.decrement(); try { @@ -188,7 +188,7 @@ public class CategoryManager { * * @param fileIDs */ - public void fireChange(Collection fileIDs, Category newCategory) { + public void fireChange(Collection fileIDs, DhsImageCategory newCategory) { categoryEventBus.post(new CategoryChangeEvent(fileIDs, newCategory)); } @@ -231,21 +231,21 @@ public class CategoryManager { * * @return the TagName used for this Category */ - synchronized public TagName getTagName(Category cat) { + synchronized public TagName getTagName(DhsImageCategory cat) { return catTagNameMap.getUnchecked(cat); } - public static Category categoryFromTagName(TagName tagName) { - return Category.fromDisplayName(tagName.getDisplayName()); + public static DhsImageCategory categoryFromTagName(TagName tagName) { + return DhsImageCategory.fromDisplayName(tagName.getDisplayName()); } public static boolean isCategoryTagName(TagName tName) { - return Category.isCategoryName(tName.getDisplayName()); + return DhsImageCategory.isCategoryName(tName.getDisplayName()); } public static boolean isNotCategoryTagName(TagName tName) { - return Category.isNotCategoryName(tName.getDisplayName()); + return DhsImageCategory.isNotCategoryName(tName.getDisplayName()); } @@ -270,8 +270,8 @@ public class CategoryManager { } catch (TskCoreException tskException) { LOGGER.log(Level.SEVERE, "Failed to get content tags for content. Unable to maintain category in a consistent state.", tskException); //NON-NLS } - Category newCat = CategoryManager.categoryFromTagName(addedTag.getName()); - if (newCat != Category.ZERO) { + DhsImageCategory newCat = CategoryManager.categoryFromTagName(addedTag.getName()); + if (newCat != DhsImageCategory.ZERO) { incrementCategoryCount(newCat); } @@ -285,8 +285,8 @@ public class CategoryManager { TagName tagName = deletedTagInfo.getName(); if (isCategoryTagName(tagName)) { - Category deletedCat = CategoryManager.categoryFromTagName(tagName); - if (deletedCat != Category.ZERO) { + DhsImageCategory deletedCat = CategoryManager.categoryFromTagName(tagName); + if (deletedCat != DhsImageCategory.ZERO) { decrementCategoryCount(deletedCat); } fireChange(Collections.singleton(deletedTagInfo.getContentID()), null); @@ -301,15 +301,15 @@ public class CategoryManager { public static class CategoryChangeEvent { private final ImmutableSet fileIDs; - private final Category newCategory; + private final DhsImageCategory newCategory; - public CategoryChangeEvent(Collection fileIDs, Category newCategory) { + public CategoryChangeEvent(Collection fileIDs, DhsImageCategory newCategory) { super(); this.fileIDs = ImmutableSet.copyOf(fileIDs); this.newCategory = newCategory; } - public Category getNewCategory() { + public DhsImageCategory getNewCategory() { return newCategory; } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java index 0ac5142f3c..c3b8771b6d 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java @@ -18,7 +18,7 @@ */ package org.sleuthkit.autopsy.imagegallery.datamodel; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -84,14 +84,14 @@ public class DrawableAttribute> { * //TODO: this has lead to awkward hard to maintain code, and little * advantage. move categories into DrawableDB? */ - public final static DrawableAttribute CATEGORY = - new DrawableAttribute(AttributeName.CATEGORY, Bundle.DrawableAttribute_category(), + public final static DrawableAttribute CATEGORY = + new DrawableAttribute(AttributeName.CATEGORY, Bundle.DrawableAttribute_category(), false, "category-icon.png", //NON-NLS f -> Collections.singleton(f.getCategory())) { @Override - public Node getGraphicForValue(Category val) { + public Node getGraphicForValue(DhsImageCategory val) { return val.getGraphic(); } }; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index 5426ac205a..fa008fe3e9 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -18,7 +18,7 @@ */ package org.sleuthkit.autopsy.imagegallery.datamodel; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -231,7 +231,7 @@ public final class DrawableDB { insertHashHitStmt = prepareStatement("INSERT OR IGNORE INTO hash_set_hits (hash_set_id, obj_id) VALUES (?,?)"); //NON-NLS - for (Category cat : Category.values()) { + for (DhsImageCategory cat : DhsImageCategory.values()) { insertGroup(cat.getDisplayName(), DrawableAttribute.CATEGORY); } initializeImageList(); @@ -1016,7 +1016,7 @@ public final class DrawableDB { case MIME_TYPE: return groupManager.getFileIDsWithMimeType((String) groupKey.getValue()); case CATEGORY: - return groupManager.getFileIDsWithCategory((Category) groupKey.getValue()); + return groupManager.getFileIDsWithCategory((DhsImageCategory) groupKey.getValue()); case TAGS: return groupManager.getFileIDsWithTag((TagName) groupKey.getValue()); } @@ -1195,7 +1195,7 @@ public final class DrawableDB { * * @return the number of the with the given category */ - public long getCategoryCount(Category cat) { + public long getCategoryCount(DhsImageCategory cat) { try { TagName tagName = controller.getTagsManager().getTagName(cat); if (nonNull(tagName)) { @@ -1233,7 +1233,7 @@ public final class DrawableDB { DrawableTagsManager tagsManager = controller.getTagsManager(); // get a comma seperated list of TagName ids for non zero categories - String catTagNameIDs = Category.getNonZeroCategories().stream() + String catTagNameIDs = DhsImageCategory.getNonZeroCategories().stream() .map(tagsManager::getTagName) .map(TagName::getId) .map(Object::toString) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java index 5b40c9240c..af26dd2e97 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java @@ -18,7 +18,7 @@ */ package org.sleuthkit.autopsy.imagegallery.datamodel; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import java.lang.ref.SoftReference; import java.text.MessageFormat; import java.util.ArrayList; @@ -85,7 +85,7 @@ public abstract class DrawableFile { private final SimpleBooleanProperty analyzed; - private final SimpleObjectProperty category = new SimpleObjectProperty<>(null); + private final SimpleObjectProperty category = new SimpleObjectProperty<>(null); private String make; @@ -216,17 +216,17 @@ public abstract class DrawableFile { return ""; } - public void setCategory(Category category) { + public void setCategory(DhsImageCategory category) { categoryProperty().set(category); } - public Category getCategory() { + public DhsImageCategory getCategory() { updateCategory(); return category.get(); } - public SimpleObjectProperty categoryProperty() { + public SimpleObjectProperty categoryProperty() { return category; } @@ -238,9 +238,9 @@ public abstract class DrawableFile { category.set(getContentTags().stream() .map(Tag::getName).filter(CategoryManager::isCategoryTagName) .map(TagName::getDisplayName) - .map(Category::fromDisplayName) + .map(DhsImageCategory::fromDisplayName) .sorted().findFirst() //sort by severity and take the first - .orElse(Category.ZERO) + .orElse(DhsImageCategory.ZERO) ); } catch (TskCoreException ex) { LOGGER.log(Level.WARNING, "problem looking up category for " + this.getContentPathSafe(), ex); //NON-NLS diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java index 0497068924..cb30c37bab 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java @@ -18,7 +18,7 @@ */ package org.sleuthkit.autopsy.imagegallery.datamodel; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import com.google.common.eventbus.AsyncEventBus; import com.google.common.eventbus.EventBus; import java.util.Collections; @@ -229,7 +229,7 @@ public class DrawableTagsManager { } } - public TagName getTagName(Category cat) { + public TagName getTagName(DhsImageCategory cat) { try { return getTagName(cat.getDisplayName()); } catch (TskCoreException ex) { diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java index e62c2b6541..7dddfa5ca8 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java @@ -71,7 +71,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB; @@ -332,7 +332,7 @@ public class GroupManager { switch (groupBy.attrName) { //these cases get special treatment case CATEGORY: - values = (List) Arrays.asList(Category.values()); + values = (List) Arrays.asList(DhsImageCategory.values()); break; case TAGS: values = (List) controller.getTagsManager().getTagNamesInUse().stream() @@ -388,7 +388,7 @@ public class GroupManager { switch (groupKey.getAttribute().attrName) { //these cases get special treatment case CATEGORY: - fileIDsToReturn = getFileIDsWithCategory((Category) groupKey.getValue()); + fileIDsToReturn = getFileIDsWithCategory((DhsImageCategory) groupKey.getValue()); break; case TAGS: fileIDsToReturn = getFileIDsWithTag((TagName) groupKey.getValue()); @@ -409,13 +409,13 @@ public class GroupManager { // @@@ This was kind of slow in the profiler. Maybe we should cache it. // Unless the list of file IDs is necessary, use countFilesWithCategory() to get the counts. - public Set getFileIDsWithCategory(Category category) throws TskCoreException { + public Set getFileIDsWithCategory(DhsImageCategory category) throws TskCoreException { Set fileIDsToReturn = Collections.emptySet(); if (nonNull(db)) { try { final DrawableTagsManager tagsManager = controller.getTagsManager(); - if (category == Category.ZERO) { - List< TagName> tns = Stream.of(Category.ONE, Category.TWO, Category.THREE, Category.FOUR, Category.FIVE) + if (category == DhsImageCategory.ZERO) { + List< TagName> tns = Stream.of(DhsImageCategory.ONE, DhsImageCategory.TWO, DhsImageCategory.THREE, DhsImageCategory.FOUR, DhsImageCategory.FIVE) .map(tagsManager::getTagName) .collect(Collectors.toList()); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java index 2841eb5325..44814e2c9a 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java @@ -36,7 +36,7 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; /** * Displays summary statistics (counts) for each group @@ -44,13 +44,13 @@ import org.sleuthkit.autopsy.datamodel.tags.Category; public class SummaryTablePane extends AnchorPane { @FXML - private TableColumn, String> catColumn; + private TableColumn, String> catColumn; @FXML - private TableColumn, Long> countColumn; + private TableColumn, Long> countColumn; @FXML - private TableView> tableView; + private TableView> tableView; private final ImageGalleryController controller; @FXML @@ -67,11 +67,11 @@ public class SummaryTablePane extends AnchorPane { tableView.prefHeightProperty().set(7 * 25); //set up columns - catColumn.setCellValueFactory((TableColumn.CellDataFeatures, String> p) -> new SimpleObjectProperty<>(p.getValue().getKey().getDisplayName())); + catColumn.setCellValueFactory((TableColumn.CellDataFeatures, String> p) -> new SimpleObjectProperty<>(p.getValue().getKey().getDisplayName())); catColumn.setPrefWidth(USE_COMPUTED_SIZE); catColumn.setText(Bundle.SummaryTablePane_catColumn()); - countColumn.setCellValueFactory((TableColumn.CellDataFeatures, Long> p) -> new SimpleObjectProperty<>(p.getValue().getValue())); + countColumn.setCellValueFactory((TableColumn.CellDataFeatures, Long> p) -> new SimpleObjectProperty<>(p.getValue().getValue())); countColumn.setPrefWidth(USE_COMPUTED_SIZE); countColumn.setText(Bundle.SummaryTablePane_countColumn()); @@ -93,9 +93,9 @@ public class SummaryTablePane extends AnchorPane { */ @Subscribe public void handleCategoryChanged(org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager.CategoryChangeEvent evt) { - final ObservableList> data = FXCollections.observableArrayList(); + final ObservableList> data = FXCollections.observableArrayList(); if (Case.isCaseOpen()) { - for (Category cat : Category.values()) { + for (DhsImageCategory cat : DhsImageCategory.values()) { data.add(new Pair<>(cat, controller.getCategoryManager().getCategoryCount(cat))); } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java index 6cb29d46d1..40dad21cf2 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java @@ -49,7 +49,7 @@ import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.actions.CategorizeGroupAction; import org.sleuthkit.autopsy.imagegallery.actions.TagGroupAction; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.DrawableGroup; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupSortBy; @@ -154,13 +154,13 @@ public class Toolbar extends ToolBar { } }); - CategorizeGroupAction cat5GroupAction = new CategorizeGroupAction(Category.FIVE, controller); + CategorizeGroupAction cat5GroupAction = new CategorizeGroupAction(DhsImageCategory.FIVE, controller); catGroupMenuButton.setOnAction(cat5GroupAction); catGroupMenuButton.setText(cat5GroupAction.getText()); catGroupMenuButton.setGraphic(cat5GroupAction.getGraphic()); catGroupMenuButton.showingProperty().addListener(showing -> { if (catGroupMenuButton.isShowing()) { - List categoryMenues = Lists.transform(Arrays.asList(Category.values()), + List categoryMenues = Lists.transform(Arrays.asList(DhsImageCategory.values()), cat -> GuiUtils.createAutoAssigningMenuItem(catGroupMenuButton, new CategorizeGroupAction(cat, controller))); catGroupMenuButton.getItems().setAll(categoryMenues); } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableView.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableView.java index e6d7bf06f2..afed2fd832 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableView.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableView.java @@ -17,7 +17,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; @@ -38,17 +38,17 @@ public interface DrawableView { static final Border HASH_BORDER = new Border(new BorderStroke(Color.PURPLE, BorderStrokeStyle.DASHED, CAT_CORNER_RADII, CAT_BORDER_WIDTHS)); - static final Border CAT1_BORDER = new Border(new BorderStroke(Category.ONE.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS)); + static final Border CAT1_BORDER = new Border(new BorderStroke(DhsImageCategory.ONE.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS)); - static final Border CAT2_BORDER = new Border(new BorderStroke(Category.TWO.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS)); + static final Border CAT2_BORDER = new Border(new BorderStroke(DhsImageCategory.TWO.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS)); - static final Border CAT3_BORDER = new Border(new BorderStroke(Category.THREE.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS)); + static final Border CAT3_BORDER = new Border(new BorderStroke(DhsImageCategory.THREE.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS)); - static final Border CAT4_BORDER = new Border(new BorderStroke(Category.FOUR.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS)); + static final Border CAT4_BORDER = new Border(new BorderStroke(DhsImageCategory.FOUR.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS)); - static final Border CAT5_BORDER = new Border(new BorderStroke(Category.FIVE.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS)); + static final Border CAT5_BORDER = new Border(new BorderStroke(DhsImageCategory.FIVE.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS)); - static final Border CAT0_BORDER = new Border(new BorderStroke(Category.ZERO.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS)); + static final Border CAT0_BORDER = new Border(new BorderStroke(DhsImageCategory.ZERO.getColor(), BorderStrokeStyle.SOLID, CAT_CORNER_RADII, CAT_BORDER_WIDTHS)); Region getCategoryBorderRegion(); @@ -97,7 +97,7 @@ public interface DrawableView { } } - static Border getCategoryBorder(Category category) { + static Border getCategoryBorder(DhsImageCategory category) { if (category != null) { switch (category) { case ONE: @@ -121,14 +121,14 @@ public interface DrawableView { } @ThreadConfined(type = ThreadConfined.ThreadType.ANY) - default Category updateCategory() { + default DhsImageCategory updateCategory() { if (getFile().isPresent()) { - final Category category = getFile().map(DrawableFile::getCategory).orElse(Category.ZERO); - final Border border = hasHashHit() && (category == Category.ZERO) ? HASH_BORDER : getCategoryBorder(category); + final DhsImageCategory category = getFile().map(DrawableFile::getCategory).orElse(DhsImageCategory.ZERO); + final Border border = hasHashHit() && (category == DhsImageCategory.ZERO) ? HASH_BORDER : getCategoryBorder(category); Platform.runLater(() -> getCategoryBorderRegion().setBorder(border)); return category; } else { - return Category.ZERO; + return DhsImageCategory.ZERO; } } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java index bd84611b93..169856ab88 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java @@ -122,7 +122,7 @@ import org.sleuthkit.autopsy.imagegallery.actions.RedoAction; import org.sleuthkit.autopsy.imagegallery.actions.SwingMenuItemAdapter; import org.sleuthkit.autopsy.imagegallery.actions.TagSelectedFilesAction; import org.sleuthkit.autopsy.imagegallery.actions.UndoAction; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.DrawableGroup; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupViewMode; @@ -352,7 +352,7 @@ public class GroupPane extends BorderPane { return grouping.getReadOnlyProperty(); } - private ToggleButton getToggleForCategory(Category category) { + private ToggleButton getToggleForCategory(DhsImageCategory category) { switch (category) { case ZERO: return cat0Toggle; @@ -397,7 +397,7 @@ public class GroupPane extends BorderPane { assert slideShowToggle != null : "fx:id=\"segButton\" was not injected: check your FXML file 'GroupHeader.fxml'."; assert tileToggle != null : "fx:id=\"tileToggle\" was not injected: check your FXML file 'GroupHeader.fxml'."; - for (Category cat : Category.values()) { + for (DhsImageCategory cat : DhsImageCategory.values()) { ToggleButton toggleForCategory = getToggleForCategory(cat); toggleForCategory.setBorder(new Border(new BorderStroke(cat.getColor(), BorderStrokeStyle.SOLID, CORNER_RADII_2, BORDER_WIDTHS_2))); toggleForCategory.getStyleClass().remove("radio-button"); @@ -445,13 +445,13 @@ public class GroupPane extends BorderPane { }); - CategorizeSelectedFilesAction cat5SelectedAction = new CategorizeSelectedFilesAction(Category.FIVE, controller); + CategorizeSelectedFilesAction cat5SelectedAction = new CategorizeSelectedFilesAction(DhsImageCategory.FIVE, controller); catSelectedSplitMenu.setOnAction(cat5SelectedAction); catSelectedSplitMenu.setText(cat5SelectedAction.getText()); catSelectedSplitMenu.setGraphic(cat5SelectedAction.getGraphic()); catSelectedSplitMenu.showingProperty().addListener(showing -> { if (catSelectedSplitMenu.isShowing()) { - List categoryMenues = Lists.transform(Arrays.asList(Category.values()), + List categoryMenues = Lists.transform(Arrays.asList(DhsImageCategory.values()), cat -> GuiUtils.createAutoAssigningMenuItem(catSelectedSplitMenu, new CategorizeSelectedFilesAction(cat, controller))); catSelectedSplitMenu.getItems().setAll(categoryMenues); } @@ -765,7 +765,7 @@ public class GroupPane extends BorderPane { } ObservableSet selected = selectionModel.getSelected(); if (selected.isEmpty() == false) { - Category cat = keyCodeToCat(t.getCode()); + DhsImageCategory cat = keyCodeToCat(t.getCode()); if (cat != null) { new CategorizeAction(controller, cat, selected).handle(null); } @@ -773,27 +773,27 @@ public class GroupPane extends BorderPane { } } - private Category keyCodeToCat(KeyCode t) { + private DhsImageCategory keyCodeToCat(KeyCode t) { if (t != null) { switch (t) { case NUMPAD0: case DIGIT0: - return Category.ZERO; + return DhsImageCategory.ZERO; case NUMPAD1: case DIGIT1: - return Category.ONE; + return DhsImageCategory.ONE; case NUMPAD2: case DIGIT2: - return Category.TWO; + return DhsImageCategory.TWO; case NUMPAD3: case DIGIT3: - return Category.THREE; + return DhsImageCategory.THREE; case NUMPAD4: case DIGIT4: - return Category.FOUR; + return DhsImageCategory.FOUR; case NUMPAD5: case DIGIT5: - return Category.FIVE; + return DhsImageCategory.FIVE; } } return null; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/MetaDataPane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/MetaDataPane.java index 881925a098..60f30564b1 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/MetaDataPane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/MetaDataPane.java @@ -57,7 +57,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; @@ -171,7 +171,7 @@ public class MetaDataPane extends DrawableUIBase { if (p.getKey() == DrawableAttribute.TAGS) { return ((Collection) p.getValue()).stream() .map(TagName::getDisplayName) - .filter(Category::isNotCategoryName) + .filter(DhsImageCategory::isNotCategoryName) .collect(Collectors.joining(" ; ")); } else { return p.getValue().stream() diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java index b40e121102..11d109bbb5 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java @@ -50,7 +50,7 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.datamodel.DhsImageCategory; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.datamodel.VideoFile; import org.sleuthkit.autopsy.imagegallery.gui.VideoPlayer; @@ -306,14 +306,14 @@ public class SlideShowView extends DrawableTileBase { */ @Override @ThreadConfined(type = ThreadType.ANY) - public Category updateCategory() { + public DhsImageCategory updateCategory() { Optional file = getFile(); if (file.isPresent()) { - Category updateCategory = super.updateCategory(); + DhsImageCategory updateCategory = super.updateCategory(); Platform.runLater(() -> getGroupPane().syncCatToggle(file.get())); return updateCategory; } else { - return Category.ZERO; + return DhsImageCategory.ZERO; } } From 3cacda1d22c7347d766e2444550cf06acdc1e77f Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 20 Nov 2017 08:43:26 -0500 Subject: [PATCH 29/90] Remove default version --- .../autopsy/centralrepository/datamodel/EamDb.java | 8 -------- .../modules/hashdatabase/HashDbCreateDatabaseDialog.java | 8 ++++---- .../modules/hashdatabase/HashDbImportDatabaseDialog.java | 2 +- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java index 1011f837cc..d6bee5137f 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java @@ -94,14 +94,6 @@ public interface EamDb { return EamDbUtil.useCentralRepo() && EamDbPlatformEnum.getSelectedPlatform() != EamDbPlatformEnum.DISABLED; } - - /** - * Placeholder version to use for non-read only databases - * @return The version that will be stored in the database - */ - static String getDefaultVersion() { - return ""; - } /** * Get the list of tags recognized as "Bad" diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java index 0ecb3a5ad4..17a69930a2 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java @@ -423,7 +423,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { }//GEN-LAST:event_saveAsButtonActionPerformed @NbBundle.Messages({"HashDbCreateDatabaseDialog.missingOrg=An organization must be selected", - "HashDbCreateDatabaseDialog.duplicateName=A hashset with this name and version already exists", + "HashDbCreateDatabaseDialog.duplicateName=A hashset with this name already exists", "HashDbCreateDatabaseDialog.databaseLookupError=Error accessing central repository", "HashDbCreateDatabaseDialog.databaseCreationError=Error creating new hash set" }) @@ -500,7 +500,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { } else { // Check if a hash set with the same name/version already exists try{ - if(EamDb.getInstance().referenceSetExists(hashSetNameTextField.getText(), EamDb.getDefaultVersion())){ + if(EamDb.getInstance().referenceSetExists(hashSetNameTextField.getText(), "")){ JOptionPane.showMessageDialog(this, NbBundle.getMessage(this.getClass(), "HashDbCreateDatabaseDialog.duplicateName"), @@ -522,9 +522,9 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { try{ int referenceSetID = EamDb.getInstance().newReferenceSet(new EamGlobalSet(selectedOrg.getOrgID(), hashSetNameTextField.getText(), - EamDb.getDefaultVersion(), fileKnown, false)); + "", fileKnown, false)); newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetNameTextField.getText(), - EamDb.getDefaultVersion(), referenceSetID, + "", referenceSetID, true, sendIngestMessagesCheckbox.isSelected(), type, false); } catch (EamDbException | TskCoreException ex){ Logger.getLogger(HashDbImportDatabaseDialog.class.getName()).log(Level.SEVERE, "Error creating new reference set", ex); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index 8b26330e45..a91ea45a16 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -557,7 +557,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { version = versionTextField.getText(); } else { // Editable databases don't have a version - version = EamDb.getDefaultVersion(); + version = ""; } ImportCentralRepoDbProgressDialog progressDialog = new ImportCentralRepoDbProgressDialog(); progressDialog.importFile(hashSetNameTextField.getText(), version, From bb1abf07e43c1b9ceef69fe4e1bb3bcd7324eeaa Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 20 Nov 2017 08:49:59 -0500 Subject: [PATCH 30/90] Clear out new reference set ID list after save --- .../autopsy/modules/hashdatabase/HashLookupSettingsPanel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java index b5c6ca805a..e7bfcecf1e 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java @@ -335,6 +335,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan } else { try { hashSetManager.save(); + newReferenceSetIDs.clear(); } catch (HashDbManager.HashDbManagerException ex) { SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(null, Bundle.HashLookupSettingsPanel_saveFail_message(), Bundle.HashLookupSettingsPanel_saveFail_title(), JOptionPane.ERROR_MESSAGE); From cd6d0ca14c63a54cddc3e83f293920bccd548e90 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 20 Nov 2017 08:58:49 -0500 Subject: [PATCH 31/90] Cleanup --- .../core.jar/org/netbeans/core/startup/Bundle.properties | 4 ++-- .../org/netbeans/core/windows/view/ui/Bundle.properties | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index 2922cd2054..0de39782ca 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Thu, 07 Sep 2017 13:53:53 -0400 +#Wed, 08 Nov 2017 17:45:11 -0500 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 @@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18 SplashRunningTextColor=0x0 SplashRunningTextFontSize=19 -currentVersion=Autopsy 4.4.2 +currentVersion=Autopsy 4.5.0 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 2ac51b0cbd..fa55dddb62 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,4 +1,4 @@ #Updated by build script -#Thu, 07 Sep 2017 13:53:53 -0400 -CTL_MainWindow_Title=Autopsy 4.4.2 -CTL_MainWindow_Title_No_Project=Autopsy 4.4.2 +#Wed, 08 Nov 2017 17:45:11 -0500 +CTL_MainWindow_Title=Autopsy 4.5.0 +CTL_MainWindow_Title_No_Project=Autopsy 4.5.0 From b230a3c63d3b10d0d9dd6063234b0561853fe9de Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 20 Nov 2017 09:12:01 -0500 Subject: [PATCH 32/90] Remove central repo hashset name properties file --- .../modules/hashdatabase/HashDbManager.java | 52 ------------------- 1 file changed, 52 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index 8d03c4e37a..975f36b993 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -700,44 +700,6 @@ public class HashDbManager implements PropertyChangeListener { } } } - - /** - * Save any newly created central repo databases to the properties file. - * @param newHashSets - */ - static void saveNewCentralRepoDatabases(List newHashSets){ - - if(! newHashSets.isEmpty()){ - String newDbs = ""; - for(CentralRepoHashDb db:newHashSets){ - newDbs += makeCentralRepoHashSetString(db); - } - String oldSetting = ModuleSettings.getConfigSetting(CENTRAL_REPO_HASH_SET_SETTINGS, CENTRAL_REPO_HASH_SET_LOCAL_KEY); - String newSetting = ""; - if((oldSetting != null) && (! oldSetting.isEmpty())){ - newSetting = oldSetting; - } - newSetting += newDbs; - ModuleSettings.setConfigSetting(CENTRAL_REPO_HASH_SET_SETTINGS, CENTRAL_REPO_HASH_SET_LOCAL_KEY, newSetting); - } - } - - /** - * Check whether a given central repository hash set was created on this machine. - * @return true if it was created on this machine, false otherwise - */ - static boolean centralRepoWasCreatedLocally(CentralRepoHashDb db){ - String setting = ModuleSettings.getConfigSetting(CENTRAL_REPO_HASH_SET_SETTINGS, CENTRAL_REPO_HASH_SET_LOCAL_KEY); - String dbStr = makeCentralRepoHashSetString(db); - if(setting == null){ - return false; - } - return setting.contains(dbStr); - } - - private static String makeCentralRepoHashSetString(CentralRepoHashDb db){ - return "|" + db.getReferenceSetID() + "." + db.getHashSetName() + "." + db.getVersion() + "|"; - } private boolean hashDbInfoIsNew(HashDbInfo dbInfo){ for(HashDatabase db:this.hashSets){ @@ -810,8 +772,6 @@ public class HashDbManager implements PropertyChangeListener { public HashDb.KnownFilesType getKnownFilesType(); public boolean getSearchDuringIngest(); - - public boolean getDefaultSearchDuringIngest(); void setSearchDuringIngest(boolean useForIngest); @@ -985,12 +945,6 @@ public class HashDbManager implements PropertyChangeListener { public boolean getSearchDuringIngest() { return searchDuringIngest; } - - @Override - public boolean getDefaultSearchDuringIngest(){ - // File type hash sets are on by default - return true; - } @Override public void setSearchDuringIngest(boolean useForIngest) { @@ -1296,12 +1250,6 @@ public class HashDbManager implements PropertyChangeListener { public boolean getSearchDuringIngest() { return searchDuringIngest; } - - @Override - public boolean getDefaultSearchDuringIngest(){ - // Central repo hash sets are off by default, unless created on this machine - return centralRepoWasCreatedLocally(this); - } @Override public void setSearchDuringIngest(boolean useForIngest) { From e5b81aa96ef8bcda7e59b5202e688a86bdbffd0d Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 20 Nov 2017 10:30:39 -0500 Subject: [PATCH 33/90] 3202 make TagNameDefinition non public again --- .../sleuthkit/autopsy/casemodule/Case.java | 5 +-- .../services/TagNameDefinition.java | 8 ++-- .../casemodule/services/TagOptionsPanel.java | 45 ++----------------- .../eventlisteners/CaseEventListener.java | 14 +++--- 4 files changed, 16 insertions(+), 56 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 1cadd0b0b2..2dcc532a37 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -76,7 +76,6 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ReportAddedEvent; import org.sleuthkit.autopsy.casemodule.services.Services; -import org.sleuthkit.autopsy.casemodule.services.TagNameDefinition; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CategoryNode; import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; @@ -1479,8 +1478,8 @@ public class Case { eventPublisher.publish(new ContentTagDeletedEvent(deletedTag)); } - public void notifyTagStatusChanged(TagNameDefinition oldTag, TagNameDefinition newTag) { - eventPublisher.publish(new AutopsyEvent(Events.TAG_STATUS_CHANGED.toString(), oldTag, newTag)); + public void notifyTagStatusChanged(String changedTagName) { + eventPublisher.publish(new AutopsyEvent(Events.TAG_STATUS_CHANGED.toString(), changedTagName, changedTagName)); } /** * Notifies case event subscribers that an artifact tag has been added. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java index 9c81afcaf8..56b142bdb4 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java @@ -40,7 +40,7 @@ import org.sleuthkit.datamodel.TskData; * A tag name definition consisting of a display name, description and color. */ @Immutable -public final class TagNameDefinition implements Comparable { +final class TagNameDefinition implements Comparable { private static final Logger LOGGER = Logger.getLogger(TagNameDefinition.class.getName()); @NbBundle.Messages({"TagNameDefinition.predefTagNames.bookmark.text=Bookmark", @@ -68,7 +68,7 @@ public final class TagNameDefinition implements Comparable { * @param color The color for the tag name. * @param status The status denoted by the tag name. */ - public TagNameDefinition(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown status) { + TagNameDefinition(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown status) { this.displayName = displayName; this.description = description; this.color = color; @@ -84,7 +84,7 @@ public final class TagNameDefinition implements Comparable { * * @return The display name. */ - public String getDisplayName() { + String getDisplayName() { return displayName; } @@ -112,7 +112,7 @@ public final class TagNameDefinition implements Comparable { * * @return a value of TskData.FileKnown which is associated with this tag */ - public TskData.FileKnown getKnownStatus() { + TskData.FileKnown getKnownStatus() { return knownStatus; } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java index 3f8210ae22..712fa6480d 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java @@ -46,7 +46,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { private final DefaultListModel tagTypesListModel; private Set tagTypes; private IngestJobEventPropertyChangeListener ingestJobEventsListener; - private Set updatedStatusTags; + private Set updatedStatusTags; /** * Creates new form TagOptionsPanel @@ -361,7 +361,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { updatePanel(); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); if (originalTagName.getKnownStatus() != newTagType.getKnownStatus() && Case.isCaseOpen()) { - updatedStatusTags.add(new TagPair(originalTagName, newTagType)); + updatedStatusTags.add(newTagType.getDisplayName()); } } }//GEN-LAST:event_editTagNameButtonActionPerformed @@ -422,8 +422,8 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { } private void sendStatusChangedEvents() { - for (TagPair modifiedTag : updatedStatusTags) { - Case.getCurrentCase().notifyTagStatusChanged(modifiedTag.getOldValue(), modifiedTag.getNewValue()); + for (String modifiedTagDisplayName : updatedStatusTags) { + Case.getCurrentCase().notifyTagStatusChanged(modifiedTagDisplayName); } updatedStatusTags.clear(); } @@ -445,7 +445,6 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { boolean enableDelete = enableEdit && !TagNameDefinition.getStandardTagNames().contains(tagNamesList.getSelectedValue().getDisplayName()); deleteTagNameButton.setEnabled(enableDelete); if (isSelected) { - descriptionTextArea.setText(tagNamesList.getSelectedValue().getDescription()); if (tagNamesList.getSelectedValue().getKnownStatus() == TskData.FileKnown.BAD) { notableYesOrNoLabel.setText("Yes"); @@ -468,42 +467,6 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { super.finalize(); } - private class TagPair implements Comparable { - - private TagNameDefinition oldValue; - private TagNameDefinition newValue; - - private TagPair(TagNameDefinition oldV, TagNameDefinition newV) { - oldValue = oldV; - newValue = newV; - } - - private TagNameDefinition getOldValue() { - return oldValue; - } - - private TagNameDefinition getNewValue() { - return newValue; - } - - /** - * Compares this tag name definition with the specified tag name - * definition for order. - * - * @param other The tag name definition to which to compare this tag - * name definition. - * - * @return Negative integer, zero, or a positive integer to indicate - * that this tag name definition is less than, equal to, or - * greater than the specified tag name definition. - */ - @Override - public int compareTo(TagPair other) { - return this.getNewValue().compareTo(other.getNewValue()); - } - - } - /** * A property change listener that listens to ingest job events. */ diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index 6ecc0edb4a..57d56fc8d2 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -33,7 +33,6 @@ import org.sleuthkit.autopsy.casemodule.events.BlackBoardArtifactTagDeletedEvent import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent; -import org.sleuthkit.autopsy.casemodule.services.TagNameDefinition; import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute; @@ -314,17 +313,17 @@ final class CaseEventListener implements PropertyChangeListener { if (!EamDb.isEnabled()) { return; } - TskData.FileKnown status = ((TagNameDefinition) event.getNewValue()).getKnownStatus(); + String modifiedTagName = (String) event.getNewValue(); + List notableTags = TagsManager.getNotableTagDisplayNames(); + TskData.FileKnown status = notableTags.contains(modifiedTagName) ? TskData.FileKnown.BAD : TskData.FileKnown.UNKNOWN; /** * Set knownBad status for all files/artifacts in the given case * that are tagged with the given tag name. */ - System.out.println("TAG " + ((TagNameDefinition) event.getNewValue()).getDisplayName() + " event FROM " + ((TagNameDefinition) event.getOldValue()).getKnownStatus().toString() + " TO " + status.toString()); try { - TagName tagName = Case.getCurrentCase().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(((TagNameDefinition) event.getNewValue()).getDisplayName()); + TagName tagName = Case.getCurrentCase().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(((TagName) event.getNewValue()).getDisplayName()); // First find any matching artifacts List artifactTags = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifactTagsByTagName(tagName); - List notableTags = TagsManager.getNotableTagDisplayNames(); for (BlackboardArtifactTag bbTag : artifactTags) { List convertedArtifacts = EamArtifactUtil.getCorrelationAttributeFromBlackboardArtifact(bbTag.getArtifact(), true, true); for (CorrelationAttribute eamArtifact : convertedArtifacts) { @@ -379,11 +378,10 @@ final class CaseEventListener implements PropertyChangeListener { } } } catch (TskCoreException ex) { - System.out.println("Cannot update "); + LOGGER.log(Level.SEVERE, "Cannot update known status in central repository"); //NON-NLS } catch (EamDbException ex) { - System.out.println("Cannot get CR"); + LOGGER.log(Level.SEVERE, "Cannot get central repository"); //NON-NLS } - } //TAG_STATUS_CHANGED } From 76b1ca6104c7180453784e0cc59fd73126b30d8d Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 20 Nov 2017 11:37:30 -0500 Subject: [PATCH 34/90] 3199 fix misplaced curly bracket in getTagNameDefinitions rewrite --- .../casemodule/services/TagNameDefiniton.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java index e2fa9f4af4..7e7607bf92 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java @@ -214,13 +214,13 @@ final class TagNameDefiniton implements Comparable { // if the Tags.Properties file is up to date parse it tagNames.addAll(readCurrentTagPropertiesFile(tagNameTuples, standardTags)); } - //create standard tags which should always exist which were not already created for whatever reason, such as upgrade - for (String standardTagName : standardTags) { - if (STANDARD_NOTABLE_TAG_DISPLAY_NAMES.contains(standardTagName)) { - tagNames.add(new TagNameDefiniton(standardTagName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.BAD)); - } else { - tagNames.add(new TagNameDefiniton(standardTagName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN)); - } + } + //create standard tags which should always exist which were not already created for whatever reason, such as upgrade + for (String standardTagName : standardTags) { + if (STANDARD_NOTABLE_TAG_DISPLAY_NAMES.contains(standardTagName)) { + tagNames.add(new TagNameDefiniton(standardTagName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.BAD)); + } else { + tagNames.add(new TagNameDefiniton(standardTagName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN)); } } return tagNames; From de618cf8ddb678e2f34d256ef6eea862c9cce2a1 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 20 Nov 2017 12:46:38 -0500 Subject: [PATCH 35/90] 3201 fix casting error in CR case event listener --- .../centralrepository/eventlisteners/CaseEventListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index 57d56fc8d2..fb01f48f2a 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -321,7 +321,7 @@ final class CaseEventListener implements PropertyChangeListener { * that are tagged with the given tag name. */ try { - TagName tagName = Case.getCurrentCase().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(((TagName) event.getNewValue()).getDisplayName()); + TagName tagName = Case.getCurrentCase().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get((String) event.getNewValue()); // First find any matching artifacts List artifactTags = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifactTagsByTagName(tagName); for (BlackboardArtifactTag bbTag : artifactTags) { From 1f349579b010951e1bca9aa8dd25d35f2d31adbd Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 20 Nov 2017 13:00:50 -0500 Subject: [PATCH 36/90] 3202 remove unused arguement from TagStatusChangeTask, add comments --- .../eventlisteners/CaseEventListener.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index fb01f48f2a..ff4db6d8eb 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -99,7 +99,7 @@ final class CaseEventListener implements PropertyChangeListener { } break; case TAG_STATUS_CHANGED: { - jobProcessingExecutor.submit(new TagStatusChangeTask(dbManager, evt)); + jobProcessingExecutor.submit(new TagStatusChangeTask(evt)); } break; case CURRENT_CASE: { @@ -300,11 +300,9 @@ final class CaseEventListener implements PropertyChangeListener { private final class TagStatusChangeTask implements Runnable { - private final EamDb dbManager; private final PropertyChangeEvent event; - private TagStatusChangeTask(EamDb db, PropertyChangeEvent evt) { - dbManager = db; + private TagStatusChangeTask(PropertyChangeEvent evt) { event = evt; } @@ -328,6 +326,7 @@ final class CaseEventListener implements PropertyChangeListener { List convertedArtifacts = EamArtifactUtil.getCorrelationAttributeFromBlackboardArtifact(bbTag.getArtifact(), true, true); for (CorrelationAttribute eamArtifact : convertedArtifacts) { boolean hasOtherBadTags = false; + //if the new status of the tag is unknown UNKNOWN ensure we are not changing the status of BlackboardArtifact which still have other tags with a non-unknown status if (status == TskData.FileKnown.UNKNOWN) { Content content = bbTag.getContent(); if ((content instanceof AbstractFile) && (((AbstractFile) content).getKnown() == TskData.FileKnown.KNOWN)) { @@ -337,9 +336,11 @@ final class CaseEventListener implements PropertyChangeListener { TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); List tags = tagsManager.getBlackboardArtifactTagsByArtifact(bbArtifact); for (BlackboardArtifactTag t : tags) { + //avoid the possibility for threading issues if the tag whose status is currently changing is ever still in the tags manager with the old status if (t.getName().equals(tagName)) { continue; } + //if any other tags on this artifact are Notable in status then this artifact can not have its status changed if (notableTags.contains(t.getName().getDisplayName())) { hasOtherBadTags = true; break; @@ -355,14 +356,17 @@ final class CaseEventListener implements PropertyChangeListener { List fileTags = Case.getCurrentCase().getSleuthkitCase().getContentTagsByTagName(tagName); for (ContentTag contentTag : fileTags) { boolean hasOtherBadTags = false; + //if the new status of the tag is unknown UNKNOWN ensure we are not changing the status of files which still have other tags with a Notable status if (status == TskData.FileKnown.UNKNOWN) { Content content = contentTag.getContent(); TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); List tags = tagsManager.getContentTagsByContent(content); for (ContentTag t : tags) { + //avoid the possibility for threading issues if the tag whose status is currently changing is ever still in the tags manager with the old status if (t.getName().equals(tagName)) { continue; } + //if any other tags on this file are Notable in status then this file can not have its status changed if (notableTags.contains(t.getName().getDisplayName())) { hasOtherBadTags = true; break; From 35048dc10a9a66550fd5304c3e97c9ced7f96069 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 20 Nov 2017 13:45:09 -0500 Subject: [PATCH 37/90] Cleanup --- .../autopsy/modules/hashdatabase/HashDbManager.java | 3 --- .../modules/hashdatabase/HashLookupModuleSettings.java | 2 +- .../core.jar/org/netbeans/core/startup/Bundle.properties | 4 ++-- .../org/netbeans/core/windows/view/ui/Bundle.properties | 6 +++--- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index 5d7a776090..34770aa6fa 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -46,7 +46,6 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalSet; import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupSettings.HashDbInfo; import org.sleuthkit.datamodel.AbstractFile; @@ -71,8 +70,6 @@ public class HashDbManager implements PropertyChangeListener { PropertyChangeSupport changeSupport = new PropertyChangeSupport(HashDbManager.class); private static final Logger logger = Logger.getLogger(HashDbManager.class.getName()); private boolean allDatabasesLoadedCorrectly = false; - private static final String CENTRAL_REPO_HASH_SET_SETTINGS = "CentralRepoHashSets"; - private static final String CENTRAL_REPO_HASH_SET_LOCAL_KEY = "LocallyCreatedHashsets"; /** * Property change event support In events: For both of these enums, the old diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettings.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettings.java index 04d6d0f143..99dd50d291 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupModuleSettings.java @@ -135,7 +135,7 @@ final class HashLookupModuleSettings implements IngestModuleIngestJobSettings { } } - // We didn't find it, so use whatever default value is in the HashDb object + // We didn't find it, so use the value in the HashDb object return db.getSearchDuringIngest(); } diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index 2922cd2054..0de39782ca 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Thu, 07 Sep 2017 13:53:53 -0400 +#Wed, 08 Nov 2017 17:45:11 -0500 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 @@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18 SplashRunningTextColor=0x0 SplashRunningTextFontSize=19 -currentVersion=Autopsy 4.4.2 +currentVersion=Autopsy 4.5.0 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index 2ac51b0cbd..fa55dddb62 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,4 +1,4 @@ #Updated by build script -#Thu, 07 Sep 2017 13:53:53 -0400 -CTL_MainWindow_Title=Autopsy 4.4.2 -CTL_MainWindow_Title_No_Project=Autopsy 4.4.2 +#Wed, 08 Nov 2017 17:45:11 -0500 +CTL_MainWindow_Title=Autopsy 4.5.0 +CTL_MainWindow_Title_No_Project=Autopsy 4.5.0 From da82b9457b0dfc5dd1aa06599badc18aa047ed42 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 20 Nov 2017 14:11:51 -0500 Subject: [PATCH 38/90] 3202 fix logging for possible exceptions in case event listener --- .../centralrepository/eventlisteners/CaseEventListener.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index ff4db6d8eb..cc6dbaf142 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -319,7 +319,7 @@ final class CaseEventListener implements PropertyChangeListener { * that are tagged with the given tag name. */ try { - TagName tagName = Case.getCurrentCase().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get((String) event.getNewValue()); + TagName tagName = Case.getCurrentCase().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(modifiedTagName); // First find any matching artifacts List artifactTags = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifactTagsByTagName(tagName); for (BlackboardArtifactTag bbTag : artifactTags) { @@ -382,9 +382,9 @@ final class CaseEventListener implements PropertyChangeListener { } } } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Cannot update known status in central repository"); //NON-NLS + LOGGER.log(Level.SEVERE, "Cannot update known status in central repository for tag: " + modifiedTagName, ex); //NON-NLS } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Cannot get central repository"); //NON-NLS + LOGGER.log(Level.SEVERE, "Cannot get central repository for tag: " + modifiedTagName, ex); //NON-NLS } } //TAG_STATUS_CHANGED } From 55fe85935d6f84250e38598724f5c88d9126c3e3 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Mon, 20 Nov 2017 16:29:09 -0500 Subject: [PATCH 39/90] Revert "Merge branch '3199-ConsolidateDefaultTags' of https://github.com/wschaeferB/autopsy into develop" This reverts commit f4811ed8a44e3ddf71dac3e96f3ead8044fdb01c, reversing changes made to 4ad996b36955f602832c55acd90239c06a4b3c29. --- Core/nbproject/project.xml | 1 - .../casemodule/services/NewTagNameDialog.java | 6 +- .../casemodule/services/TagNameDefiniton.java | 90 ++----------------- .../casemodule/services/TagOptionsPanel.form | 2 +- .../casemodule/services/TagOptionsPanel.java | 3 +- .../casemodule/services/TagsManager.java | 58 ++++-------- .../datamodel/AbstractSqlEamDb.java | 27 ++++++ .../centralrepository/datamodel/EamDb.java | 14 +++ .../datamodel/PostgresEamDb.java | 11 +++ .../datamodel/PostgresEamDbSettings.java | 30 +++++++ .../datamodel/SqliteEamDb.java | 11 ++- .../datamodel/SqliteEamDbSettings.java | 27 +++++- .../eventlisteners/CaseEventListener.java | 57 +++++++----- .../optionspanel/ManageTagsDialog.java | 12 ++- .../actions/CategorizeAction.java | 2 +- .../actions/CategorizeGroupAction.java | 2 +- .../CategorizeSelectedFilesAction.java | 2 +- .../imagegallery/datamodel}/Category.java | 2 +- .../datamodel/CategoryManager.java | 2 - .../datamodel/DrawableAttribute.java | 1 - .../imagegallery/datamodel/DrawableDB.java | 1 - .../imagegallery/datamodel/DrawableFile.java | 1 - .../datamodel/DrawableTagsManager.java | 16 +++- .../datamodel/grouping/GroupManager.java | 2 +- .../imagegallery/gui/SummaryTablePane.java | 2 +- .../autopsy/imagegallery/gui/Toolbar.java | 2 +- .../gui/drawableviews/DrawableView.java | 2 +- .../gui/drawableviews/GroupPane.java | 2 +- .../gui/drawableviews/MetaDataPane.java | 2 +- .../gui/drawableviews/SlideShowView.java | 2 +- 30 files changed, 213 insertions(+), 179 deletions(-) rename {Core/src/org/sleuthkit/autopsy/datamodel/tags => ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel}/Category.java (98%) mode change 100644 => 100755 diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 394198f6c9..987b2ffe78 100755 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -304,7 +304,6 @@ org.sleuthkit.autopsy.corecomponents org.sleuthkit.autopsy.coreutils org.sleuthkit.autopsy.datamodel - org.sleuthkit.autopsy.datamodel.tags org.sleuthkit.autopsy.datasourceprocessors org.sleuthkit.autopsy.directorytree org.sleuthkit.autopsy.events diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.java index b7b2e66ebc..ff21ac283b 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * -* Copyright 2011-2017 Basis Technology Corp. +* Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -117,9 +117,7 @@ final class NewTagNameDialog extends javax.swing.JDialog { JOptionPane.ERROR_MESSAGE); return; } - - //if a tag name contains illegal characters and is not the name of one of the standard tags - if (TagsManager.containsIllegalCharacters(newTagDisplayName) && !TagNameDefiniton.getStandardTagNames().contains(newTagDisplayName)) { + if (TagsManager.containsIllegalCharacters(newTagDisplayName)) { JOptionPane.showMessageDialog(null, NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.message"), NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.title"), diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java index 8c7d29baa3..101d68fa4c 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2011-2016 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,22 +18,14 @@ */ package org.sleuthkit.autopsy.casemodule.services; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; import javax.annotation.concurrent.Immutable; -import org.openide.util.Exceptions; -import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.datamodel.TagName; -import org.sleuthkit.autopsy.datamodel.tags.Category; -import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.TskData; /** * A tag name definition consisting of a display name, description and color. @@ -41,40 +33,24 @@ import org.sleuthkit.datamodel.TskData; @Immutable final class TagNameDefiniton implements Comparable { - @NbBundle.Messages({"TagNameDefiniton.predefTagNames.bookmark.text=Bookmark", - "TagNameDefiniton.predefTagNames.followUp.text=Follow Up", - "TagNameDefiniton.predefTagNames.notableItem.text=Notable Item"}) private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS - - private static final List STANDARD_NOTABLE_TAG_DISPLAY_NAMES = Arrays.asList(Bundle.TagNameDefiniton_predefTagNames_notableItem_text(), Category.ONE.getDisplayName(), Category.TWO.getDisplayName(), Category.THREE.getDisplayName()); // NON-NLS - private static final List STANDARD_TAG_DISPLAY_NAMES = Arrays.asList(Bundle.TagNameDefiniton_predefTagNames_bookmark_text(), Bundle.TagNameDefiniton_predefTagNames_followUp_text(), - Bundle.TagNameDefiniton_predefTagNames_notableItem_text(), Category.ONE.getDisplayName(), - Category.TWO.getDisplayName(), Category.THREE.getDisplayName(), - Category.FOUR.getDisplayName(), Category.FIVE.getDisplayName()); private final String displayName; private final String description; private final TagName.HTML_COLOR color; - private final TskData.FileKnown knownStatusDenoted; /** * Constructs a tag name definition consisting of a display name, - * description, color and knownStatus. + * description and color. * * @param displayName The display name for the tag name. * @param description The description for the tag name. * @param color The color for the tag name. - * @param knownStatus The status denoted by the tag. */ - TagNameDefiniton(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown status) { + TagNameDefiniton(String displayName, String description, TagName.HTML_COLOR color) { this.displayName = displayName; this.description = description; this.color = color; - this.knownStatusDenoted = status; - } - - static List getStandardTagNames() { - return STANDARD_TAG_DISPLAY_NAMES; } /** @@ -104,16 +80,6 @@ final class TagNameDefiniton implements Comparable { return color; } - /** - * Whether or not the status that this tag implies is the Notable status - * - * @return true if the Notable status is implied by this tag, false - * otherwise. - */ - boolean isNotable() { - return knownStatusDenoted == TskData.FileKnown.BAD; - } - /** * Compares this tag name definition with the specified tag name definition * for order. @@ -174,58 +140,22 @@ final class TagNameDefiniton implements Comparable { * that is used by the tags settings file. */ private String toSettingsFormat() { - return displayName + "," + description + "," + color.name() + "," + knownStatusDenoted.toString(); - } - - private TagName saveToCase(SleuthkitCase caseDb) { - TagName tagName = null; - try { - tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatusDenoted); - } catch (TskCoreException ex) { - Exceptions.printStackTrace(ex); - } - return tagName; + return displayName + "," + description + "," + color.name(); } /** - * Gets tag name definitions from the tag settings file as well as the - * default tag name definitions. + * Gets tag name definitions from the tag settings file. * * @return A set of tag name definition objects. */ static synchronized Set getTagNameDefinitions() { Set tagNames = new HashSet<>(); - List standardTags = new ArrayList<>(STANDARD_TAG_DISPLAY_NAMES); //modifiable copy of default tags list for us to keep track of which ones already exist String setting = ModuleSettings.getConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY); if (null != setting && !setting.isEmpty()) { List tagNameTuples = Arrays.asList(setting.split(";")); - List notableTags = new ArrayList<>(); - String badTagsStr = ModuleSettings.getConfigSetting("CentralRepository", "db.badTags"); // NON-NLS - if (badTagsStr == null || badTagsStr.isEmpty()) { //if there were no bad tags in the central repo properties file use the default list - notableTags.addAll(STANDARD_NOTABLE_TAG_DISPLAY_NAMES); - } else { //otherwise use the list that was in the central repository properties file - notableTags.addAll(Arrays.asList(badTagsStr.split(","))); - } - for (String tagNameTuple : tagNameTuples) { //for each tag listed in the tags properties file - String[] tagNameAttributes = tagNameTuple.split(","); //get the attributes - if (tagNameAttributes.length == 3) { //if there are only 3 attributes so Tags.properties does not contain any tag definitions with knownStatus - standardTags.remove(tagNameAttributes[0]); //remove tag from default tags we need to create still - if (notableTags.contains(tagNameAttributes[0])) { //if tag should be notable mark create it as such - tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.BAD)); - } else { //otherwise create it as unknown - tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.UNKNOWN)); //add the default value for that tag - } - } else if (tagNameAttributes.length == 4) { //if there are 4 attributes its a current list we can use the values present - standardTags.remove(tagNameAttributes[0]); //remove tag from default tags we need to create still - tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.valueOf(tagNameAttributes[3]))); - } - } - } - for (String standardTagName : standardTags) { //create standard tags which should always exist which were not already created for whatever reason, such as upgrade - if (STANDARD_NOTABLE_TAG_DISPLAY_NAMES.contains(standardTagName)) { - tagNames.add(new TagNameDefiniton(standardTagName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.BAD)); - } else { - tagNames.add(new TagNameDefiniton(standardTagName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN)); + for (String tagNameTuple : tagNameTuples) { + String[] tagNameAttributes = tagNameTuple.split(","); + tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]))); } } return tagNames; @@ -243,10 +173,6 @@ final class TagNameDefiniton implements Comparable { setting.append(";"); } setting.append(tagName.toSettingsFormat()); - if (Case.isCaseOpen()) { - SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase(); - tagName.saveToCase(caseDb); - } } ModuleSettings.setConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY, setting.toString()); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form index c58201621a..3f33f848c0 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form @@ -52,7 +52,7 @@ - +
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java index 681cc95472..c1c9beb5b2 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java @@ -27,7 +27,6 @@ import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.datamodel.TagName; -import org.sleuthkit.datamodel.TskData; /** * A panel to allow the user to create and delete custom tag types. @@ -191,7 +190,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { NewTagNameDialog.BUTTON_PRESSED result = dialog.getResult(); if (result == NewTagNameDialog.BUTTON_PRESSED.OK) { String newTagDisplayName = dialog.getTagName(); - TagNameDefiniton newTagType = new TagNameDefiniton(newTagDisplayName, DEFAULT_DESCRIPTION, DEFAULT_COLOR, TskData.FileKnown.UNKNOWN); + TagNameDefiniton newTagType = new TagNameDefiniton(newTagDisplayName, DEFAULT_DESCRIPTION, DEFAULT_COLOR); /* * If tag name already exists, don't add the tag name. */ diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index adfcbf0029..c592e463cb 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -20,13 +20,14 @@ package org.sleuthkit.autopsy.casemodule.services; import java.io.Closeable; import java.io.IOException; -import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; +import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -36,7 +37,6 @@ import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.TskData; /** * A per case Autopsy service that manages the addition of content and artifact @@ -45,7 +45,8 @@ import org.sleuthkit.datamodel.TskData; public class TagsManager implements Closeable { private static final Logger LOGGER = Logger.getLogger(TagsManager.class.getName()); - + @NbBundle.Messages("TagsManager.predefTagNames.bookmark.text=Bookmark") + private static final Set STANDARD_TAG_DISPLAY_NAMES = new HashSet<>(Arrays.asList(Bundle.TagsManager_predefTagNames_bookmark_text())); private final SleuthkitCase caseDb; /** @@ -82,11 +83,11 @@ public class TagsManager implements Closeable { * querying the case database for tag types. */ public static Set getTagDisplayNames() throws TskCoreException { - Set tagDisplayNames = new HashSet<>(); + Set tagDisplayNames = new HashSet<>(STANDARD_TAG_DISPLAY_NAMES); Set customNames = TagNameDefiniton.getTagNameDefinitions(); customNames.forEach((tagType) -> { tagDisplayNames.add(tagType.getDisplayName()); - }); + }); try { TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); for (TagName tagName : tagsManager.getAllTagNames()) { @@ -96,17 +97,7 @@ public class TagsManager implements Closeable { /* * No current case, nothing more to add to the set. */ - } - return tagDisplayNames; - } - - public static List getNotableTagDisplayNames() { - List tagDisplayNames = new ArrayList<>(); - for (TagNameDefiniton tagDef : TagNameDefiniton.getTagNameDefinitions()) { - if (tagDef.isNotable()) { - tagDisplayNames.add(tagDef.getDisplayName()); - } - } + } return tagDisplayNames; } @@ -195,7 +186,7 @@ public class TagsManager implements Closeable { * name to the case database. */ public synchronized TagName addTagName(String displayName) throws TagNameAlreadyExistsException, TskCoreException { - return addTagName(displayName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN); + return addTagName(displayName, "", TagName.HTML_COLOR.NONE); } /** @@ -214,7 +205,7 @@ public class TagsManager implements Closeable { * name to the case database. */ public synchronized TagName addTagName(String displayName, String description) throws TagNameAlreadyExistsException, TskCoreException { - return addTagName(displayName, description, TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN); + return addTagName(displayName, description, TagName.HTML_COLOR.NONE); } /** @@ -233,32 +224,13 @@ public class TagsManager implements Closeable { * name to the case database. */ public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color) throws TagNameAlreadyExistsException, TskCoreException { - return addTagName(displayName, description, color, TskData.FileKnown.UNKNOWN); - } - - /** - * Adds a tag name entry to the case database and adds a corresponding tag - * type to the current user's custom tag types. - * - * @param displayName The display name for the new tag type. - * @param description The description for the new tag type. - * @param color The color to associate with the new tag type. - * @param knownStatus The knownStatus to be used for the tag when - * correlating on the tagged item - * - * @return A TagName object that can be used to add instances of the tag - * type to the case database. - * - * @throws TagNameAlreadyExistsException If the tag name already exists. - * @throws TskCoreException If there is an error adding the tag - * name to the case database. - */ - public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus) throws TagNameAlreadyExistsException, TskCoreException { try { - TagName tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatus); - Set customTypes = TagNameDefiniton.getTagNameDefinitions(); - customTypes.add(new TagNameDefiniton(displayName, description, color, knownStatus)); - TagNameDefiniton.setTagNameDefinitions(customTypes); + TagName tagName = caseDb.addTagName(displayName, description, color); + if (!STANDARD_TAG_DISPLAY_NAMES.contains(displayName)) { + Set customTypes = TagNameDefiniton.getTagNameDefinitions(); + customTypes.add(new TagNameDefiniton(displayName, description, color)); + TagNameDefiniton.setTagNameDefinitions(customTypes); + } return tagName; } catch (TskCoreException ex) { List existingTagNames = caseDb.getAllTagNames(); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index f9c2435472..7c7d22066e 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -53,6 +53,7 @@ public abstract class AbstractSqlEamDb implements EamDb { private int bulkArtifactsCount; protected int bulkArtifactsThreshold; private final Map> bulkArtifacts; + private final List badTags; /** * Connect to the DB and initialize it. @@ -60,6 +61,7 @@ public abstract class AbstractSqlEamDb implements EamDb { * @throws UnknownHostException, EamDbException */ protected AbstractSqlEamDb() throws EamDbException { + badTags = new ArrayList<>(); bulkArtifactsCount = 0; bulkArtifacts = new HashMap<>(); @@ -74,6 +76,31 @@ public abstract class AbstractSqlEamDb implements EamDb { */ protected abstract Connection connect() throws EamDbException; + /** + * Get the list of tags recognized as "Bad" + * + * @return The list of bad tags + */ + @Override + public List getBadTags() { + synchronized (badTags) { + return new ArrayList<>(badTags); + } + } + + /** + * Set the tags recognized as "Bad" + * + * @param tags The tags to consider bad + */ + @Override + public void setBadTags(List tags) { + synchronized (badTags) { + badTags.clear(); + badTags.addAll(tags); + } + } + /** * Add a new name/value pair in the db_info table. * diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java index 5f2cdfa816..1011f837cc 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java @@ -103,6 +103,20 @@ public interface EamDb { return ""; } + /** + * Get the list of tags recognized as "Bad" + * + * @return The list of bad tags + */ + List getBadTags(); + + /** + * Set the tags recognized as "Bad" + * + * @param tags The tags to consider bad + */ + void setBadTags(List tags); + /** * Add a new name/value pair in the db_info table. * diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java index c139554c9c..cecba78f4e 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.centralrepository.datamodel; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; +import java.util.List; import java.util.logging.Level; import org.apache.commons.dbcp2.BasicDataSource; import org.sleuthkit.autopsy.coreutils.Logger; @@ -186,4 +187,14 @@ public class PostgresEamDb extends AbstractSqlEamDb { return CONFLICT_CLAUSE; } + @Override + public List getBadTags() { + return dbSettings.getBadTags(); + } + + @Override + public void setBadTags(List badTags) { + dbSettings.setBadTags(badTags); + } + } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java index bfb3f04b32..6179a58342 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java @@ -24,6 +24,8 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Properties; import java.util.logging.Level; @@ -45,6 +47,7 @@ public final class PostgresEamDbSettings { private final int DEFAULT_BULK_THRESHHOLD = 1000; private final String DEFAULT_USERNAME = ""; private final String DEFAULT_PASSWORD = ""; + private final String DEFAULT_BAD_TAGS = "Evidence"; // NON-NLS private final String VALIDATION_QUERY = "SELECT version()"; // NON-NLS private final String JDBC_BASE_URI = "jdbc:postgresql://"; // NON-NLS private final String JDBC_DRIVER = "org.postgresql.Driver"; // NON-NLS @@ -56,6 +59,7 @@ public final class PostgresEamDbSettings { private int bulkThreshold; private String userName; private String password; + private List badTags; public PostgresEamDbSettings() { loadSettings(); @@ -116,6 +120,16 @@ public final class PostgresEamDbSettings { password = DEFAULT_PASSWORD; } } + + String badTagsStr = ModuleSettings.getConfigSetting("CentralRepository", "db.badTags"); // NON-NLS + if (badTagsStr == null) { + badTagsStr = DEFAULT_BAD_TAGS; + } + if(badTagsStr.isEmpty()){ + badTags = new ArrayList<>(); + } else { + badTags = new ArrayList<>(Arrays.asList(badTagsStr.split(","))); + } } public void saveSettings() { @@ -129,6 +143,8 @@ public final class PostgresEamDbSettings { } catch (TextConverterException ex) { LOGGER.log(Level.SEVERE, "Failed to convert password from text to hex text.", ex); } + + ModuleSettings.setConfigSetting("CentralRepository", "db.badTags", String.join(",", badTags)); // NON-NLS } /** @@ -617,6 +633,20 @@ public final class PostgresEamDbSettings { this.password = password; } + /** + * @return the badTags + */ + public List getBadTags() { + return badTags; + } + + /** + * @param badTags the badTags to set + */ + public void setBadTags(List badTags) { + this.badTags = badTags; + } + /** * @return the VALIDATION_QUERY */ diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java index 3e79f5abca..719a58385b 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java @@ -200,7 +200,16 @@ public class SqliteEamDb extends AbstractSqlEamDb { return ""; } - + @Override + public List getBadTags() { + return dbSettings.getBadTags(); + } + + @Override + public void setBadTags(List badTags) { + dbSettings.setBadTags(badTags); + } + /** * Add a new name/value pair in the db_info table. * diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java index b4ea1aa8a2..fa50118924 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java @@ -26,6 +26,8 @@ import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.regex.Pattern; @@ -42,6 +44,7 @@ public final class SqliteEamDbSettings { private final String DEFAULT_DBNAME = "central_repository.db"; // NON-NLS private final String DEFAULT_DBDIRECTORY = PlatformUtil.getUserDirectory() + File.separator + "central_repository"; // NON-NLS private final int DEFAULT_BULK_THRESHHOLD = 1000; + private final String DEFAULT_BAD_TAGS = "Evidence"; // NON-NLS private final String JDBC_DRIVER = "org.sqlite.JDBC"; // NON-NLS private final String JDBC_BASE_URI = "jdbc:sqlite:"; // NON-NLS private final String VALIDATION_QUERY = "SELECT count(*) from sqlite_master"; // NON-NLS @@ -56,6 +59,7 @@ public final class SqliteEamDbSettings { private String dbName; private String dbDirectory; private int bulkThreshold; + private List badTags; public SqliteEamDbSettings() { loadSettings(); @@ -86,7 +90,15 @@ public final class SqliteEamDbSettings { this.bulkThreshold = DEFAULT_BULK_THRESHHOLD; } - + String badTagsStr = ModuleSettings.getConfigSetting("CentralRepository", "db.badTags"); // NON-NLS + if (badTagsStr == null) { + badTagsStr = DEFAULT_BAD_TAGS; + } + if (badTagsStr.isEmpty()) { + badTags = new ArrayList<>(); + } else { + badTags = new ArrayList<>(Arrays.asList(badTagsStr.split(","))); + } } public void saveSettings() { @@ -95,6 +107,7 @@ public final class SqliteEamDbSettings { ModuleSettings.setConfigSetting("CentralRepository", "db.sqlite.dbName", getDbName()); // NON-NLS ModuleSettings.setConfigSetting("CentralRepository", "db.sqlite.dbDirectory", getDbDirectory()); // NON-NLS ModuleSettings.setConfigSetting("CentralRepository", "db.sqlite.bulkThreshold", Integer.toString(getBulkThreshold())); // NON-NLS + ModuleSettings.setConfigSetting("CentralRepository", "db.badTags", String.join(",", badTags)); // NON-NLS } /** @@ -489,7 +502,19 @@ public final class SqliteEamDbSettings { } } + /** + * @return the badTags + */ + public List getBadTags() { + return badTags; + } + /** + * @param badTags the badTags to set + */ + public void setBadTags(List badTags) { + this.badTags = badTags; + } /** * @return the dbDirectory diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index dbe17d6e6d..a68b0cba8d 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -130,7 +130,7 @@ final class CaseEventListener implements PropertyChangeListener { final ContentTagAddedEvent tagAddedEvent = (ContentTagAddedEvent) event; final ContentTag tagAdded = tagAddedEvent.getAddedTag(); - if (TagsManager.getNotableTagDisplayNames().contains(tagAdded.getName().getDisplayName())) { + if (dbManager.getBadTags().contains(tagAdded.getName().getDisplayName())) { if (tagAdded.getContent() instanceof AbstractFile) { af = (AbstractFile) tagAdded.getContent(); knownStatus = TskData.FileKnown.BAD; @@ -151,7 +151,7 @@ final class CaseEventListener implements PropertyChangeListener { long contentID = tagDeletedEvent.getDeletedTagInfo().getContentID(); String tagName = tagDeletedEvent.getDeletedTagInfo().getName().getDisplayName(); - if (!TagsManager.getNotableTagDisplayNames().contains(tagName)) { + if (!dbManager.getBadTags().contains(tagName)) { // If the tag that got removed isn't on the list of central repo tags, do nothing return; } @@ -164,7 +164,7 @@ final class CaseEventListener implements PropertyChangeListener { if (tags.stream() .map(tag -> tag.getName().getDisplayName()) - .filter(TagsManager.getNotableTagDisplayNames()::contains) + .filter(dbManager.getBadTags()::contains) .collect(Collectors.toList()) .isEmpty()) { @@ -227,7 +227,7 @@ final class CaseEventListener implements PropertyChangeListener { final BlackBoardArtifactTagAddedEvent tagAddedEvent = (BlackBoardArtifactTagAddedEvent) event; final BlackboardArtifactTag tagAdded = tagAddedEvent.getAddedTag(); - if (TagsManager.getNotableTagDisplayNames().contains(tagAdded.getName().getDisplayName())) { + if (dbManager.getBadTags().contains(tagAdded.getName().getDisplayName())) { content = tagAdded.getContent(); bbArtifact = tagAdded.getArtifact(); knownStatus = TskData.FileKnown.BAD; @@ -245,7 +245,7 @@ final class CaseEventListener implements PropertyChangeListener { long artifactID = tagDeletedEvent.getDeletedTagInfo().getArtifactID(); String tagName = tagDeletedEvent.getDeletedTagInfo().getName().getDisplayName(); - if (!TagsManager.getNotableTagDisplayNames().contains(tagName)) { + if (!dbManager.getBadTags().contains(tagName)) { // If the tag that got removed isn't on the list of central repo tags, do nothing return; } @@ -259,7 +259,7 @@ final class CaseEventListener implements PropertyChangeListener { if (tags.stream() .map(tag -> tag.getName().getDisplayName()) - .filter(TagsManager.getNotableTagDisplayNames()::contains) + .filter(dbManager.getBadTags()::contains) .collect(Collectors.toList()) .isEmpty()) { @@ -350,23 +350,38 @@ final class CaseEventListener implements PropertyChangeListener { if ((null == event.getOldValue()) && (event.getNewValue() instanceof Case)) { Case curCase = (Case) event.getNewValue(); IngestEventsListener.resetCeModuleInstanceCount(); - - CorrelationCase curCeCase = new CorrelationCase( - -1, - curCase.getName(), // unique case ID - EamOrganization.getDefault(), - curCase.getDisplayName(), - curCase.getCreatedDate(), - curCase.getNumber(), - curCase.getExaminer(), - curCase.getExaminerEmail(), - curCase.getExaminerPhone(), - curCase.getCaseNotes()); - - if (!EamDb.isEnabled()) { - return; + try { + // only add default evidence tag if case is open and it doesn't already exist in the tags list. + if (Case.isCaseOpen() + && Case.getCurrentCase().getServices().getTagsManager().getAllTagNames().stream() + .map(tag -> tag.getDisplayName()) + .filter(tagName -> Bundle.caseeventlistener_evidencetag().equals(tagName)) + .collect(Collectors.toList()) + .isEmpty()) { + curCase.getServices().getTagsManager().addTagName(Bundle.caseeventlistener_evidencetag()); + } + } catch (TagsManager.TagNameAlreadyExistsException ex) { + LOGGER.info("Evidence tag already exists"); // NON-NLS + } catch (TskCoreException ex) { + LOGGER.log(Level.SEVERE, "Error adding tag.", ex); // NON-NLS } + CorrelationCase curCeCase = new CorrelationCase( + -1, + curCase.getName(), // unique case ID + EamOrganization.getDefault(), + curCase.getDisplayName(), + curCase.getCreatedDate(), + curCase.getNumber(), + curCase.getExaminer(), + curCase.getExaminerEmail(), + curCase.getExaminerPhone(), + curCase.getCaseNotes()); + + if (!EamDb.isEnabled()) { + return; + } + try { // NOTE: Cannot determine if the opened case is a new case or a reopened case, // so check for existing name in DB and insert if missing. diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java index ff179c3032..1960ee3df4 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.logging.Level; +import java.util.stream.Collectors; import javax.swing.JFrame; import javax.swing.table.DefaultTableModel; import javax.swing.event.TableModelEvent; @@ -90,11 +91,15 @@ final class ManageTagsDialog extends javax.swing.JDialog { lbWarnings.setText(Bundle.ManageTagsDialog_init_failedConnection_msg()); return; } - List badTags = TagsManager.getNotableTagDisplayNames(); + List badTags = dbManager.getBadTags(); - List tagNames = new ArrayList<>(); + List tagNames = new ArrayList<>(badTags); try { - tagNames.addAll(TagsManager.getTagDisplayNames()); + tagNames.addAll( + TagsManager.getTagDisplayNames() + .stream() + .filter(tagName -> !badTags.contains(tagName)) + .collect(Collectors.toList())); } catch (TskCoreException ex) { LOGGER.log(Level.WARNING, "Could not get list of tags in case", ex); lbWarnings.setText(Bundle.ManageTagsDialog_init_failedGettingTags_msg()); @@ -257,6 +262,7 @@ final class ManageTagsDialog extends javax.swing.JDialog { } try { EamDb dbManager = EamDb.getInstance(); + dbManager.setBadTags(badTags); dbManager.saveSettings(); } catch (EamDbException ex) { LOGGER.log(Level.SEVERE, "Failed to connect to central repository database."); // NON-NLS diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java index e55078018e..0cbef7e5d1 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java @@ -40,7 +40,7 @@ import org.controlsfx.control.action.ActionUtils; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java index 439bb59512..cc2ede2ce5 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java @@ -38,7 +38,7 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.ImageGalleryPreferences; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.datamodel.TskCoreException; /** diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeSelectedFilesAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeSelectedFilesAction.java index be8c3644bb..ef70b0f1f6 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeSelectedFilesAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeSelectedFilesAction.java @@ -19,7 +19,7 @@ package org.sleuthkit.autopsy.imagegallery.actions; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.Category; /** * diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/tags/Category.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Category.java old mode 100644 new mode 100755 similarity index 98% rename from Core/src/org/sleuthkit/autopsy/datamodel/tags/Category.java rename to ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Category.java index 39d624110f..1b2bd604b0 --- a/Core/src/org/sleuthkit/autopsy/datamodel/tags/Category.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Category.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.datamodel.tags; +package org.sleuthkit.autopsy.imagegallery.datamodel; import com.google.common.collect.ImmutableList; import java.util.Map; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java index 33bc9a58d4..f18e96795b 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java @@ -35,12 +35,10 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; - /** * Provides a cached view of the number of files per category, and fires * {@link CategoryChangeEvent}s when files are categorized. diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java index 0ac5142f3c..96e37d0a83 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.imagegallery.datamodel; -import org.sleuthkit.autopsy.datamodel.tags.Category; import java.util.Arrays; import java.util.Collection; import java.util.Collections; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index 5426ac205a..9f8a6c924e 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.imagegallery.datamodel; -import org.sleuthkit.autopsy.datamodel.tags.Category; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java index 5b40c9240c..2f86c47ad6 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.imagegallery.datamodel; -import org.sleuthkit.autopsy.datamodel.tags.Category; import java.lang.ref.SoftReference; import java.text.MessageFormat; import java.util.ArrayList; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java index 0497068924..2172aacf51 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.imagegallery.datamodel; -import org.sleuthkit.autopsy.datamodel.tags.Category; import com.google.common.eventbus.AsyncEventBus; import com.google.common.eventbus.EventBus; import java.util.Collections; @@ -52,9 +51,19 @@ public class DrawableTagsManager { private static final Logger LOGGER = Logger.getLogger(DrawableTagsManager.class.getName()); + private static final String FOLLOW_UP = Bundle.DrawableTagsManager_followUp(); + private static final String BOOKMARK = Bundle.DrawableTagsManager_bookMark(); private static Image FOLLOW_UP_IMAGE; private static Image BOOKMARK_IMAGE; + public static String getFollowUpText() { + return FOLLOW_UP; + } + + public static String getBookmarkText() { + return BOOKMARK; + } + final private Object autopsyTagsManagerLock = new Object(); private TagsManager autopsyTagsManager; @@ -138,7 +147,7 @@ public class DrawableTagsManager { public TagName getFollowUpTagName() throws TskCoreException { synchronized (autopsyTagsManagerLock) { if (Objects.isNull(followUpTagName)) { - followUpTagName = getTagName(NbBundle.getMessage(DrawableTagsManager.class, "DrawableTagsManager.followUp")); + followUpTagName = getTagName(FOLLOW_UP); } return followUpTagName; } @@ -147,13 +156,12 @@ public class DrawableTagsManager { private Object getBookmarkTagName() throws TskCoreException { synchronized (autopsyTagsManagerLock) { if (Objects.isNull(bookmarkTagName)) { - bookmarkTagName = getTagName(NbBundle.getMessage(DrawableTagsManager.class, "DrawableTagsManager.bookMark")); + bookmarkTagName = getTagName(BOOKMARK); } return bookmarkTagName; } } - /** * get all the TagNames that are not categories * diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java index e62c2b6541..5c02f5abd1 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java @@ -71,7 +71,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java index 2841eb5325..708568fe41 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java @@ -36,7 +36,7 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.Category; /** * Displays summary statistics (counts) for each group diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java index 6cb29d46d1..bdc43c1c06 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java @@ -49,7 +49,7 @@ import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.actions.CategorizeGroupAction; import org.sleuthkit.autopsy.imagegallery.actions.TagGroupAction; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.DrawableGroup; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupSortBy; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableView.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableView.java index e6d7bf06f2..6668657619 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableView.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableView.java @@ -17,7 +17,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java index bd84611b93..6fc8074248 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java @@ -122,7 +122,7 @@ import org.sleuthkit.autopsy.imagegallery.actions.RedoAction; import org.sleuthkit.autopsy.imagegallery.actions.SwingMenuItemAdapter; import org.sleuthkit.autopsy.imagegallery.actions.TagSelectedFilesAction; import org.sleuthkit.autopsy.imagegallery.actions.UndoAction; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.DrawableGroup; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupViewMode; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/MetaDataPane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/MetaDataPane.java index 881925a098..bf6597ecb5 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/MetaDataPane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/MetaDataPane.java @@ -57,7 +57,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java index b40e121102..94e56cf93c 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java @@ -50,7 +50,7 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.datamodel.VideoFile; import org.sleuthkit.autopsy.imagegallery.gui.VideoPlayer; From e086f68933d25e0000271a2bf75c33b61b9ff356 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 20 Nov 2017 16:57:54 -0500 Subject: [PATCH 40/90] 3199 remove remaining reference to datamodel.tags package --- Core/nbproject/project.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 394198f6c9..987b2ffe78 100755 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -304,7 +304,6 @@ org.sleuthkit.autopsy.corecomponents org.sleuthkit.autopsy.coreutils org.sleuthkit.autopsy.datamodel - org.sleuthkit.autopsy.datamodel.tags org.sleuthkit.autopsy.datasourceprocessors org.sleuthkit.autopsy.directorytree org.sleuthkit.autopsy.events From cf07e646e416c2778754a3d45f7f04392042a7d5 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Mon, 20 Nov 2017 17:37:03 -0500 Subject: [PATCH 41/90] Revert "Revert "Merge branch '3199-ConsolidateDefaultTags' of https://github.com/wschaeferB/autopsy into develop"" This reverts commit 55fe85935d6f84250e38598724f5c88d9126c3e3. --- Core/nbproject/project.xml | 1 + .../casemodule/services/NewTagNameDialog.java | 6 +- .../casemodule/services/TagNameDefiniton.java | 90 +++++++++++++++++-- .../casemodule/services/TagOptionsPanel.form | 2 +- .../casemodule/services/TagOptionsPanel.java | 3 +- .../casemodule/services/TagsManager.java | 58 ++++++++---- .../datamodel/AbstractSqlEamDb.java | 27 ------ .../centralrepository/datamodel/EamDb.java | 14 --- .../datamodel/PostgresEamDb.java | 11 --- .../datamodel/PostgresEamDbSettings.java | 30 ------- .../datamodel/SqliteEamDb.java | 11 +-- .../datamodel/SqliteEamDbSettings.java | 27 +----- .../eventlisteners/CaseEventListener.java | 55 +++++------- .../optionspanel/ManageTagsDialog.java | 12 +-- .../autopsy/datamodel/tags}/Category.java | 2 +- .../actions/CategorizeAction.java | 2 +- .../actions/CategorizeGroupAction.java | 2 +- .../CategorizeSelectedFilesAction.java | 2 +- .../datamodel/CategoryManager.java | 2 + .../datamodel/DrawableAttribute.java | 1 + .../imagegallery/datamodel/DrawableDB.java | 1 + .../imagegallery/datamodel/DrawableFile.java | 1 + .../datamodel/DrawableTagsManager.java | 16 +--- .../datamodel/grouping/GroupManager.java | 2 +- .../imagegallery/gui/SummaryTablePane.java | 2 +- .../autopsy/imagegallery/gui/Toolbar.java | 2 +- .../gui/drawableviews/DrawableView.java | 2 +- .../gui/drawableviews/GroupPane.java | 2 +- .../gui/drawableviews/MetaDataPane.java | 2 +- .../gui/drawableviews/SlideShowView.java | 2 +- 30 files changed, 178 insertions(+), 212 deletions(-) rename {ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel => Core/src/org/sleuthkit/autopsy/datamodel/tags}/Category.java (98%) mode change 100755 => 100644 diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 987b2ffe78..394198f6c9 100755 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -304,6 +304,7 @@ org.sleuthkit.autopsy.corecomponents org.sleuthkit.autopsy.coreutils org.sleuthkit.autopsy.datamodel + org.sleuthkit.autopsy.datamodel.tags org.sleuthkit.autopsy.datasourceprocessors org.sleuthkit.autopsy.directorytree org.sleuthkit.autopsy.events diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.java index ff21ac283b..b7b2e66ebc 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/NewTagNameDialog.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * -* Copyright 2011-2016 Basis Technology Corp. +* Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -117,7 +117,9 @@ final class NewTagNameDialog extends javax.swing.JDialog { JOptionPane.ERROR_MESSAGE); return; } - if (TagsManager.containsIllegalCharacters(newTagDisplayName)) { + + //if a tag name contains illegal characters and is not the name of one of the standard tags + if (TagsManager.containsIllegalCharacters(newTagDisplayName) && !TagNameDefiniton.getStandardTagNames().contains(newTagDisplayName)) { JOptionPane.showMessageDialog(null, NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.message"), NbBundle.getMessage(NewTagNameDialog.class, "NewTagNameDialog.JOptionPane.tagNameIllegalCharacters.title"), diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java index 101d68fa4c..8c7d29baa3 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefiniton.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2016 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,14 +18,22 @@ */ package org.sleuthkit.autopsy.casemodule.services; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; import javax.annotation.concurrent.Immutable; +import org.openide.util.Exceptions; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.datamodel.TagName; +import org.sleuthkit.autopsy.datamodel.tags.Category; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; /** * A tag name definition consisting of a display name, description and color. @@ -33,24 +41,40 @@ import org.sleuthkit.datamodel.TagName; @Immutable final class TagNameDefiniton implements Comparable { + @NbBundle.Messages({"TagNameDefiniton.predefTagNames.bookmark.text=Bookmark", + "TagNameDefiniton.predefTagNames.followUp.text=Follow Up", + "TagNameDefiniton.predefTagNames.notableItem.text=Notable Item"}) private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS + + private static final List STANDARD_NOTABLE_TAG_DISPLAY_NAMES = Arrays.asList(Bundle.TagNameDefiniton_predefTagNames_notableItem_text(), Category.ONE.getDisplayName(), Category.TWO.getDisplayName(), Category.THREE.getDisplayName()); // NON-NLS + private static final List STANDARD_TAG_DISPLAY_NAMES = Arrays.asList(Bundle.TagNameDefiniton_predefTagNames_bookmark_text(), Bundle.TagNameDefiniton_predefTagNames_followUp_text(), + Bundle.TagNameDefiniton_predefTagNames_notableItem_text(), Category.ONE.getDisplayName(), + Category.TWO.getDisplayName(), Category.THREE.getDisplayName(), + Category.FOUR.getDisplayName(), Category.FIVE.getDisplayName()); private final String displayName; private final String description; private final TagName.HTML_COLOR color; + private final TskData.FileKnown knownStatusDenoted; /** * Constructs a tag name definition consisting of a display name, - * description and color. + * description, color and knownStatus. * * @param displayName The display name for the tag name. * @param description The description for the tag name. * @param color The color for the tag name. + * @param knownStatus The status denoted by the tag. */ - TagNameDefiniton(String displayName, String description, TagName.HTML_COLOR color) { + TagNameDefiniton(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown status) { this.displayName = displayName; this.description = description; this.color = color; + this.knownStatusDenoted = status; + } + + static List getStandardTagNames() { + return STANDARD_TAG_DISPLAY_NAMES; } /** @@ -80,6 +104,16 @@ final class TagNameDefiniton implements Comparable { return color; } + /** + * Whether or not the status that this tag implies is the Notable status + * + * @return true if the Notable status is implied by this tag, false + * otherwise. + */ + boolean isNotable() { + return knownStatusDenoted == TskData.FileKnown.BAD; + } + /** * Compares this tag name definition with the specified tag name definition * for order. @@ -140,22 +174,58 @@ final class TagNameDefiniton implements Comparable { * that is used by the tags settings file. */ private String toSettingsFormat() { - return displayName + "," + description + "," + color.name(); + return displayName + "," + description + "," + color.name() + "," + knownStatusDenoted.toString(); + } + + private TagName saveToCase(SleuthkitCase caseDb) { + TagName tagName = null; + try { + tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatusDenoted); + } catch (TskCoreException ex) { + Exceptions.printStackTrace(ex); + } + return tagName; } /** - * Gets tag name definitions from the tag settings file. + * Gets tag name definitions from the tag settings file as well as the + * default tag name definitions. * * @return A set of tag name definition objects. */ static synchronized Set getTagNameDefinitions() { Set tagNames = new HashSet<>(); + List standardTags = new ArrayList<>(STANDARD_TAG_DISPLAY_NAMES); //modifiable copy of default tags list for us to keep track of which ones already exist String setting = ModuleSettings.getConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY); if (null != setting && !setting.isEmpty()) { List tagNameTuples = Arrays.asList(setting.split(";")); - for (String tagNameTuple : tagNameTuples) { - String[] tagNameAttributes = tagNameTuple.split(","); - tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]))); + List notableTags = new ArrayList<>(); + String badTagsStr = ModuleSettings.getConfigSetting("CentralRepository", "db.badTags"); // NON-NLS + if (badTagsStr == null || badTagsStr.isEmpty()) { //if there were no bad tags in the central repo properties file use the default list + notableTags.addAll(STANDARD_NOTABLE_TAG_DISPLAY_NAMES); + } else { //otherwise use the list that was in the central repository properties file + notableTags.addAll(Arrays.asList(badTagsStr.split(","))); + } + for (String tagNameTuple : tagNameTuples) { //for each tag listed in the tags properties file + String[] tagNameAttributes = tagNameTuple.split(","); //get the attributes + if (tagNameAttributes.length == 3) { //if there are only 3 attributes so Tags.properties does not contain any tag definitions with knownStatus + standardTags.remove(tagNameAttributes[0]); //remove tag from default tags we need to create still + if (notableTags.contains(tagNameAttributes[0])) { //if tag should be notable mark create it as such + tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.BAD)); + } else { //otherwise create it as unknown + tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.UNKNOWN)); //add the default value for that tag + } + } else if (tagNameAttributes.length == 4) { //if there are 4 attributes its a current list we can use the values present + standardTags.remove(tagNameAttributes[0]); //remove tag from default tags we need to create still + tagNames.add(new TagNameDefiniton(tagNameAttributes[0], tagNameAttributes[1], TagName.HTML_COLOR.valueOf(tagNameAttributes[2]), TskData.FileKnown.valueOf(tagNameAttributes[3]))); + } + } + } + for (String standardTagName : standardTags) { //create standard tags which should always exist which were not already created for whatever reason, such as upgrade + if (STANDARD_NOTABLE_TAG_DISPLAY_NAMES.contains(standardTagName)) { + tagNames.add(new TagNameDefiniton(standardTagName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.BAD)); + } else { + tagNames.add(new TagNameDefiniton(standardTagName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN)); } } return tagNames; @@ -173,6 +243,10 @@ final class TagNameDefiniton implements Comparable { setting.append(";"); } setting.append(tagName.toSettingsFormat()); + if (Case.isCaseOpen()) { + SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase(); + tagName.saveToCase(caseDb); + } } ModuleSettings.setConfigSetting(TAGS_SETTINGS_NAME, TAG_NAMES_SETTING_KEY, setting.toString()); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form index 3f33f848c0..c58201621a 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.form @@ -52,7 +52,7 @@ - +
diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java index c1c9beb5b2..681cc95472 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java @@ -27,6 +27,7 @@ import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.datamodel.TagName; +import org.sleuthkit.datamodel.TskData; /** * A panel to allow the user to create and delete custom tag types. @@ -190,7 +191,7 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { NewTagNameDialog.BUTTON_PRESSED result = dialog.getResult(); if (result == NewTagNameDialog.BUTTON_PRESSED.OK) { String newTagDisplayName = dialog.getTagName(); - TagNameDefiniton newTagType = new TagNameDefiniton(newTagDisplayName, DEFAULT_DESCRIPTION, DEFAULT_COLOR); + TagNameDefiniton newTagType = new TagNameDefiniton(newTagDisplayName, DEFAULT_DESCRIPTION, DEFAULT_COLOR, TskData.FileKnown.UNKNOWN); /* * If tag name already exists, don't add the tag name. */ diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index c592e463cb..adfcbf0029 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -20,14 +20,13 @@ package org.sleuthkit.autopsy.casemodule.services; import java.io.Closeable; import java.io.IOException; -import java.util.Arrays; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; -import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -37,6 +36,7 @@ import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; /** * A per case Autopsy service that manages the addition of content and artifact @@ -45,8 +45,7 @@ import org.sleuthkit.datamodel.TskCoreException; public class TagsManager implements Closeable { private static final Logger LOGGER = Logger.getLogger(TagsManager.class.getName()); - @NbBundle.Messages("TagsManager.predefTagNames.bookmark.text=Bookmark") - private static final Set STANDARD_TAG_DISPLAY_NAMES = new HashSet<>(Arrays.asList(Bundle.TagsManager_predefTagNames_bookmark_text())); + private final SleuthkitCase caseDb; /** @@ -83,11 +82,11 @@ public class TagsManager implements Closeable { * querying the case database for tag types. */ public static Set getTagDisplayNames() throws TskCoreException { - Set tagDisplayNames = new HashSet<>(STANDARD_TAG_DISPLAY_NAMES); + Set tagDisplayNames = new HashSet<>(); Set customNames = TagNameDefiniton.getTagNameDefinitions(); customNames.forEach((tagType) -> { tagDisplayNames.add(tagType.getDisplayName()); - }); + }); try { TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); for (TagName tagName : tagsManager.getAllTagNames()) { @@ -97,7 +96,17 @@ public class TagsManager implements Closeable { /* * No current case, nothing more to add to the set. */ - } + } + return tagDisplayNames; + } + + public static List getNotableTagDisplayNames() { + List tagDisplayNames = new ArrayList<>(); + for (TagNameDefiniton tagDef : TagNameDefiniton.getTagNameDefinitions()) { + if (tagDef.isNotable()) { + tagDisplayNames.add(tagDef.getDisplayName()); + } + } return tagDisplayNames; } @@ -186,7 +195,7 @@ public class TagsManager implements Closeable { * name to the case database. */ public synchronized TagName addTagName(String displayName) throws TagNameAlreadyExistsException, TskCoreException { - return addTagName(displayName, "", TagName.HTML_COLOR.NONE); + return addTagName(displayName, "", TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN); } /** @@ -205,7 +214,7 @@ public class TagsManager implements Closeable { * name to the case database. */ public synchronized TagName addTagName(String displayName, String description) throws TagNameAlreadyExistsException, TskCoreException { - return addTagName(displayName, description, TagName.HTML_COLOR.NONE); + return addTagName(displayName, description, TagName.HTML_COLOR.NONE, TskData.FileKnown.UNKNOWN); } /** @@ -224,13 +233,32 @@ public class TagsManager implements Closeable { * name to the case database. */ public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color) throws TagNameAlreadyExistsException, TskCoreException { + return addTagName(displayName, description, color, TskData.FileKnown.UNKNOWN); + } + + /** + * Adds a tag name entry to the case database and adds a corresponding tag + * type to the current user's custom tag types. + * + * @param displayName The display name for the new tag type. + * @param description The description for the new tag type. + * @param color The color to associate with the new tag type. + * @param knownStatus The knownStatus to be used for the tag when + * correlating on the tagged item + * + * @return A TagName object that can be used to add instances of the tag + * type to the case database. + * + * @throws TagNameAlreadyExistsException If the tag name already exists. + * @throws TskCoreException If there is an error adding the tag + * name to the case database. + */ + public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus) throws TagNameAlreadyExistsException, TskCoreException { try { - TagName tagName = caseDb.addTagName(displayName, description, color); - if (!STANDARD_TAG_DISPLAY_NAMES.contains(displayName)) { - Set customTypes = TagNameDefiniton.getTagNameDefinitions(); - customTypes.add(new TagNameDefiniton(displayName, description, color)); - TagNameDefiniton.setTagNameDefinitions(customTypes); - } + TagName tagName = caseDb.addOrUpdateTagName(displayName, description, color, knownStatus); + Set customTypes = TagNameDefiniton.getTagNameDefinitions(); + customTypes.add(new TagNameDefiniton(displayName, description, color, knownStatus)); + TagNameDefiniton.setTagNameDefinitions(customTypes); return tagName; } catch (TskCoreException ex) { List existingTagNames = caseDb.getAllTagNames(); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index 7c7d22066e..f9c2435472 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -53,7 +53,6 @@ public abstract class AbstractSqlEamDb implements EamDb { private int bulkArtifactsCount; protected int bulkArtifactsThreshold; private final Map> bulkArtifacts; - private final List badTags; /** * Connect to the DB and initialize it. @@ -61,7 +60,6 @@ public abstract class AbstractSqlEamDb implements EamDb { * @throws UnknownHostException, EamDbException */ protected AbstractSqlEamDb() throws EamDbException { - badTags = new ArrayList<>(); bulkArtifactsCount = 0; bulkArtifacts = new HashMap<>(); @@ -76,31 +74,6 @@ public abstract class AbstractSqlEamDb implements EamDb { */ protected abstract Connection connect() throws EamDbException; - /** - * Get the list of tags recognized as "Bad" - * - * @return The list of bad tags - */ - @Override - public List getBadTags() { - synchronized (badTags) { - return new ArrayList<>(badTags); - } - } - - /** - * Set the tags recognized as "Bad" - * - * @param tags The tags to consider bad - */ - @Override - public void setBadTags(List tags) { - synchronized (badTags) { - badTags.clear(); - badTags.addAll(tags); - } - } - /** * Add a new name/value pair in the db_info table. * diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java index 1011f837cc..5f2cdfa816 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java @@ -103,20 +103,6 @@ public interface EamDb { return ""; } - /** - * Get the list of tags recognized as "Bad" - * - * @return The list of bad tags - */ - List getBadTags(); - - /** - * Set the tags recognized as "Bad" - * - * @param tags The tags to consider bad - */ - void setBadTags(List tags); - /** * Add a new name/value pair in the db_info table. * diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java index cecba78f4e..c139554c9c 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDb.java @@ -21,7 +21,6 @@ package org.sleuthkit.autopsy.centralrepository.datamodel; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; -import java.util.List; import java.util.logging.Level; import org.apache.commons.dbcp2.BasicDataSource; import org.sleuthkit.autopsy.coreutils.Logger; @@ -187,14 +186,4 @@ public class PostgresEamDb extends AbstractSqlEamDb { return CONFLICT_CLAUSE; } - @Override - public List getBadTags() { - return dbSettings.getBadTags(); - } - - @Override - public void setBadTags(List badTags) { - dbSettings.setBadTags(badTags); - } - } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java index 6179a58342..bfb3f04b32 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java @@ -24,8 +24,6 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Properties; import java.util.logging.Level; @@ -47,7 +45,6 @@ public final class PostgresEamDbSettings { private final int DEFAULT_BULK_THRESHHOLD = 1000; private final String DEFAULT_USERNAME = ""; private final String DEFAULT_PASSWORD = ""; - private final String DEFAULT_BAD_TAGS = "Evidence"; // NON-NLS private final String VALIDATION_QUERY = "SELECT version()"; // NON-NLS private final String JDBC_BASE_URI = "jdbc:postgresql://"; // NON-NLS private final String JDBC_DRIVER = "org.postgresql.Driver"; // NON-NLS @@ -59,7 +56,6 @@ public final class PostgresEamDbSettings { private int bulkThreshold; private String userName; private String password; - private List badTags; public PostgresEamDbSettings() { loadSettings(); @@ -120,16 +116,6 @@ public final class PostgresEamDbSettings { password = DEFAULT_PASSWORD; } } - - String badTagsStr = ModuleSettings.getConfigSetting("CentralRepository", "db.badTags"); // NON-NLS - if (badTagsStr == null) { - badTagsStr = DEFAULT_BAD_TAGS; - } - if(badTagsStr.isEmpty()){ - badTags = new ArrayList<>(); - } else { - badTags = new ArrayList<>(Arrays.asList(badTagsStr.split(","))); - } } public void saveSettings() { @@ -143,8 +129,6 @@ public final class PostgresEamDbSettings { } catch (TextConverterException ex) { LOGGER.log(Level.SEVERE, "Failed to convert password from text to hex text.", ex); } - - ModuleSettings.setConfigSetting("CentralRepository", "db.badTags", String.join(",", badTags)); // NON-NLS } /** @@ -633,20 +617,6 @@ public final class PostgresEamDbSettings { this.password = password; } - /** - * @return the badTags - */ - public List getBadTags() { - return badTags; - } - - /** - * @param badTags the badTags to set - */ - public void setBadTags(List badTags) { - this.badTags = badTags; - } - /** * @return the VALIDATION_QUERY */ diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java index 719a58385b..3e79f5abca 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java @@ -200,16 +200,7 @@ public class SqliteEamDb extends AbstractSqlEamDb { return ""; } - @Override - public List getBadTags() { - return dbSettings.getBadTags(); - } - - @Override - public void setBadTags(List badTags) { - dbSettings.setBadTags(badTags); - } - + /** * Add a new name/value pair in the db_info table. * diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java index fa50118924..b4ea1aa8a2 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java @@ -26,8 +26,6 @@ import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.regex.Pattern; @@ -44,7 +42,6 @@ public final class SqliteEamDbSettings { private final String DEFAULT_DBNAME = "central_repository.db"; // NON-NLS private final String DEFAULT_DBDIRECTORY = PlatformUtil.getUserDirectory() + File.separator + "central_repository"; // NON-NLS private final int DEFAULT_BULK_THRESHHOLD = 1000; - private final String DEFAULT_BAD_TAGS = "Evidence"; // NON-NLS private final String JDBC_DRIVER = "org.sqlite.JDBC"; // NON-NLS private final String JDBC_BASE_URI = "jdbc:sqlite:"; // NON-NLS private final String VALIDATION_QUERY = "SELECT count(*) from sqlite_master"; // NON-NLS @@ -59,7 +56,6 @@ public final class SqliteEamDbSettings { private String dbName; private String dbDirectory; private int bulkThreshold; - private List badTags; public SqliteEamDbSettings() { loadSettings(); @@ -90,15 +86,7 @@ public final class SqliteEamDbSettings { this.bulkThreshold = DEFAULT_BULK_THRESHHOLD; } - String badTagsStr = ModuleSettings.getConfigSetting("CentralRepository", "db.badTags"); // NON-NLS - if (badTagsStr == null) { - badTagsStr = DEFAULT_BAD_TAGS; - } - if (badTagsStr.isEmpty()) { - badTags = new ArrayList<>(); - } else { - badTags = new ArrayList<>(Arrays.asList(badTagsStr.split(","))); - } + } public void saveSettings() { @@ -107,7 +95,6 @@ public final class SqliteEamDbSettings { ModuleSettings.setConfigSetting("CentralRepository", "db.sqlite.dbName", getDbName()); // NON-NLS ModuleSettings.setConfigSetting("CentralRepository", "db.sqlite.dbDirectory", getDbDirectory()); // NON-NLS ModuleSettings.setConfigSetting("CentralRepository", "db.sqlite.bulkThreshold", Integer.toString(getBulkThreshold())); // NON-NLS - ModuleSettings.setConfigSetting("CentralRepository", "db.badTags", String.join(",", badTags)); // NON-NLS } /** @@ -502,19 +489,7 @@ public final class SqliteEamDbSettings { } } - /** - * @return the badTags - */ - public List getBadTags() { - return badTags; - } - /** - * @param badTags the badTags to set - */ - public void setBadTags(List badTags) { - this.badTags = badTags; - } /** * @return the dbDirectory diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index a68b0cba8d..dbe17d6e6d 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -130,7 +130,7 @@ final class CaseEventListener implements PropertyChangeListener { final ContentTagAddedEvent tagAddedEvent = (ContentTagAddedEvent) event; final ContentTag tagAdded = tagAddedEvent.getAddedTag(); - if (dbManager.getBadTags().contains(tagAdded.getName().getDisplayName())) { + if (TagsManager.getNotableTagDisplayNames().contains(tagAdded.getName().getDisplayName())) { if (tagAdded.getContent() instanceof AbstractFile) { af = (AbstractFile) tagAdded.getContent(); knownStatus = TskData.FileKnown.BAD; @@ -151,7 +151,7 @@ final class CaseEventListener implements PropertyChangeListener { long contentID = tagDeletedEvent.getDeletedTagInfo().getContentID(); String tagName = tagDeletedEvent.getDeletedTagInfo().getName().getDisplayName(); - if (!dbManager.getBadTags().contains(tagName)) { + if (!TagsManager.getNotableTagDisplayNames().contains(tagName)) { // If the tag that got removed isn't on the list of central repo tags, do nothing return; } @@ -164,7 +164,7 @@ final class CaseEventListener implements PropertyChangeListener { if (tags.stream() .map(tag -> tag.getName().getDisplayName()) - .filter(dbManager.getBadTags()::contains) + .filter(TagsManager.getNotableTagDisplayNames()::contains) .collect(Collectors.toList()) .isEmpty()) { @@ -227,7 +227,7 @@ final class CaseEventListener implements PropertyChangeListener { final BlackBoardArtifactTagAddedEvent tagAddedEvent = (BlackBoardArtifactTagAddedEvent) event; final BlackboardArtifactTag tagAdded = tagAddedEvent.getAddedTag(); - if (dbManager.getBadTags().contains(tagAdded.getName().getDisplayName())) { + if (TagsManager.getNotableTagDisplayNames().contains(tagAdded.getName().getDisplayName())) { content = tagAdded.getContent(); bbArtifact = tagAdded.getArtifact(); knownStatus = TskData.FileKnown.BAD; @@ -245,7 +245,7 @@ final class CaseEventListener implements PropertyChangeListener { long artifactID = tagDeletedEvent.getDeletedTagInfo().getArtifactID(); String tagName = tagDeletedEvent.getDeletedTagInfo().getName().getDisplayName(); - if (!dbManager.getBadTags().contains(tagName)) { + if (!TagsManager.getNotableTagDisplayNames().contains(tagName)) { // If the tag that got removed isn't on the list of central repo tags, do nothing return; } @@ -259,7 +259,7 @@ final class CaseEventListener implements PropertyChangeListener { if (tags.stream() .map(tag -> tag.getName().getDisplayName()) - .filter(dbManager.getBadTags()::contains) + .filter(TagsManager.getNotableTagDisplayNames()::contains) .collect(Collectors.toList()) .isEmpty()) { @@ -350,37 +350,22 @@ final class CaseEventListener implements PropertyChangeListener { if ((null == event.getOldValue()) && (event.getNewValue() instanceof Case)) { Case curCase = (Case) event.getNewValue(); IngestEventsListener.resetCeModuleInstanceCount(); - try { - // only add default evidence tag if case is open and it doesn't already exist in the tags list. - if (Case.isCaseOpen() - && Case.getCurrentCase().getServices().getTagsManager().getAllTagNames().stream() - .map(tag -> tag.getDisplayName()) - .filter(tagName -> Bundle.caseeventlistener_evidencetag().equals(tagName)) - .collect(Collectors.toList()) - .isEmpty()) { - curCase.getServices().getTagsManager().addTagName(Bundle.caseeventlistener_evidencetag()); - } - } catch (TagsManager.TagNameAlreadyExistsException ex) { - LOGGER.info("Evidence tag already exists"); // NON-NLS - } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Error adding tag.", ex); // NON-NLS - } - + CorrelationCase curCeCase = new CorrelationCase( - -1, - curCase.getName(), // unique case ID - EamOrganization.getDefault(), - curCase.getDisplayName(), - curCase.getCreatedDate(), - curCase.getNumber(), - curCase.getExaminer(), - curCase.getExaminerEmail(), - curCase.getExaminerPhone(), - curCase.getCaseNotes()); + -1, + curCase.getName(), // unique case ID + EamOrganization.getDefault(), + curCase.getDisplayName(), + curCase.getCreatedDate(), + curCase.getNumber(), + curCase.getExaminer(), + curCase.getExaminerEmail(), + curCase.getExaminerPhone(), + curCase.getCaseNotes()); - if (!EamDb.isEnabled()) { - return; - } + if (!EamDb.isEnabled()) { + return; + } try { // NOTE: Cannot determine if the opened case is a new case or a reopened case, diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java index 1960ee3df4..ff179c3032 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageTagsDialog.java @@ -25,7 +25,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.logging.Level; -import java.util.stream.Collectors; import javax.swing.JFrame; import javax.swing.table.DefaultTableModel; import javax.swing.event.TableModelEvent; @@ -91,15 +90,11 @@ final class ManageTagsDialog extends javax.swing.JDialog { lbWarnings.setText(Bundle.ManageTagsDialog_init_failedConnection_msg()); return; } - List badTags = dbManager.getBadTags(); + List badTags = TagsManager.getNotableTagDisplayNames(); - List tagNames = new ArrayList<>(badTags); + List tagNames = new ArrayList<>(); try { - tagNames.addAll( - TagsManager.getTagDisplayNames() - .stream() - .filter(tagName -> !badTags.contains(tagName)) - .collect(Collectors.toList())); + tagNames.addAll(TagsManager.getTagDisplayNames()); } catch (TskCoreException ex) { LOGGER.log(Level.WARNING, "Could not get list of tags in case", ex); lbWarnings.setText(Bundle.ManageTagsDialog_init_failedGettingTags_msg()); @@ -262,7 +257,6 @@ final class ManageTagsDialog extends javax.swing.JDialog { } try { EamDb dbManager = EamDb.getInstance(); - dbManager.setBadTags(badTags); dbManager.saveSettings(); } catch (EamDbException ex) { LOGGER.log(Level.SEVERE, "Failed to connect to central repository database."); // NON-NLS diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Category.java b/Core/src/org/sleuthkit/autopsy/datamodel/tags/Category.java old mode 100755 new mode 100644 similarity index 98% rename from ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Category.java rename to Core/src/org/sleuthkit/autopsy/datamodel/tags/Category.java index 1b2bd604b0..39d624110f --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/Category.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/tags/Category.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.imagegallery.datamodel; +package org.sleuthkit.autopsy.datamodel.tags; import com.google.common.collect.ImmutableList; import java.util.Map; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java index 0cbef7e5d1..e55078018e 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeAction.java @@ -40,7 +40,7 @@ import org.controlsfx.control.action.ActionUtils; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.datamodel.tags.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java index cc2ede2ce5..439bb59512 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeGroupAction.java @@ -38,7 +38,7 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.ImageGalleryPreferences; -import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.datamodel.tags.Category; import org.sleuthkit.datamodel.TskCoreException; /** diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeSelectedFilesAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeSelectedFilesAction.java index ef70b0f1f6..be8c3644bb 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeSelectedFilesAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/CategorizeSelectedFilesAction.java @@ -19,7 +19,7 @@ package org.sleuthkit.autopsy.imagegallery.actions; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.datamodel.tags.Category; /** * diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java index f18e96795b..33bc9a58d4 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/CategoryManager.java @@ -35,10 +35,12 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; +import org.sleuthkit.autopsy.datamodel.tags.Category; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; + /** * Provides a cached view of the number of files per category, and fires * {@link CategoryChangeEvent}s when files are categorized. diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java index 96e37d0a83..0ac5142f3c 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableAttribute.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.imagegallery.datamodel; +import org.sleuthkit.autopsy.datamodel.tags.Category; import java.util.Arrays; import java.util.Collection; import java.util.Collections; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index 9f8a6c924e..5426ac205a 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.imagegallery.datamodel; +import org.sleuthkit.autopsy.datamodel.tags.Category; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java index 2f86c47ad6..5b40c9240c 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.imagegallery.datamodel; +import org.sleuthkit.autopsy.datamodel.tags.Category; import java.lang.ref.SoftReference; import java.text.MessageFormat; import java.util.ArrayList; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java index 2172aacf51..0497068924 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableTagsManager.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.imagegallery.datamodel; +import org.sleuthkit.autopsy.datamodel.tags.Category; import com.google.common.eventbus.AsyncEventBus; import com.google.common.eventbus.EventBus; import java.util.Collections; @@ -51,19 +52,9 @@ public class DrawableTagsManager { private static final Logger LOGGER = Logger.getLogger(DrawableTagsManager.class.getName()); - private static final String FOLLOW_UP = Bundle.DrawableTagsManager_followUp(); - private static final String BOOKMARK = Bundle.DrawableTagsManager_bookMark(); private static Image FOLLOW_UP_IMAGE; private static Image BOOKMARK_IMAGE; - public static String getFollowUpText() { - return FOLLOW_UP; - } - - public static String getBookmarkText() { - return BOOKMARK; - } - final private Object autopsyTagsManagerLock = new Object(); private TagsManager autopsyTagsManager; @@ -147,7 +138,7 @@ public class DrawableTagsManager { public TagName getFollowUpTagName() throws TskCoreException { synchronized (autopsyTagsManagerLock) { if (Objects.isNull(followUpTagName)) { - followUpTagName = getTagName(FOLLOW_UP); + followUpTagName = getTagName(NbBundle.getMessage(DrawableTagsManager.class, "DrawableTagsManager.followUp")); } return followUpTagName; } @@ -156,12 +147,13 @@ public class DrawableTagsManager { private Object getBookmarkTagName() throws TskCoreException { synchronized (autopsyTagsManagerLock) { if (Objects.isNull(bookmarkTagName)) { - bookmarkTagName = getTagName(BOOKMARK); + bookmarkTagName = getTagName(NbBundle.getMessage(DrawableTagsManager.class, "DrawableTagsManager.bookMark")); } return bookmarkTagName; } } + /** * get all the TagNames that are not categories * diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java index 5c02f5abd1..e62c2b6541 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java @@ -71,7 +71,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.datamodel.tags.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java index 708568fe41..2841eb5325 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/SummaryTablePane.java @@ -36,7 +36,7 @@ import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.datamodel.tags.Category; /** * Displays summary statistics (counts) for each group diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java index bdc43c1c06..6cb29d46d1 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/Toolbar.java @@ -49,7 +49,7 @@ import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.actions.CategorizeGroupAction; import org.sleuthkit.autopsy.imagegallery.actions.TagGroupAction; -import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.datamodel.tags.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.DrawableGroup; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupSortBy; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableView.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableView.java index 6668657619..e6d7bf06f2 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableView.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/DrawableView.java @@ -17,7 +17,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.datamodel.tags.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java index 6fc8074248..bd84611b93 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/GroupPane.java @@ -122,7 +122,7 @@ import org.sleuthkit.autopsy.imagegallery.actions.RedoAction; import org.sleuthkit.autopsy.imagegallery.actions.SwingMenuItemAdapter; import org.sleuthkit.autopsy.imagegallery.actions.TagSelectedFilesAction; import org.sleuthkit.autopsy.imagegallery.actions.UndoAction; -import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.datamodel.tags.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.DrawableGroup; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupViewMode; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/MetaDataPane.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/MetaDataPane.java index bf6597ecb5..881925a098 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/MetaDataPane.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/MetaDataPane.java @@ -57,7 +57,7 @@ import org.sleuthkit.autopsy.casemodule.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.datamodel.tags.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java index 94e56cf93c..b40e121102 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/gui/drawableviews/SlideShowView.java @@ -50,7 +50,7 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined; import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType; import org.sleuthkit.autopsy.imagegallery.FXMLConstructor; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.imagegallery.datamodel.Category; +import org.sleuthkit.autopsy.datamodel.tags.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.datamodel.VideoFile; import org.sleuthkit.autopsy.imagegallery.gui.VideoPlayer; From 8623c96b4595b508ab90d0142f14536f5f07951b Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 20 Nov 2017 18:28:45 -0500 Subject: [PATCH 42/90] 3201 remove calls to buttons that no longer exist for managing tags --- .../centralrepository/optionspanel/GlobalSettingsPanel.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java index 79373bc4d8..8b6ce90e96 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java @@ -478,10 +478,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i private boolean enableButtonSubComponents(Boolean enable) { boolean ingestRunning = IngestManager.getInstance().isIngestRunning(); pnCorrelationProperties.setEnabled(enable && !ingestRunning); - pnTagManagement.setEnabled(enable && !ingestRunning); bnManageTypes.setEnabled(enable && !ingestRunning); - bnManageTags.setEnabled(enable && !ingestRunning); - manageTagsTextArea.setEnabled(enable && !ingestRunning); correlationPropertiesTextArea.setEnabled(enable && !ingestRunning); organizationPanel.setEnabled(enable && !ingestRunning); organizationTextArea.setEnabled(enable && !ingestRunning); From dbe357c6444522f0d8b472acaa634dcf5589a75e Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Tue, 21 Nov 2017 10:58:41 -0500 Subject: [PATCH 43/90] Partial implementation. --- .../autoingest/AutoIngestJobNodeData.java | 37 +++++++++++++++++-- .../autoingest/AutoIngestManager.java | 9 +++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java index e2b267fded..e3ecf177e1 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java @@ -31,7 +31,7 @@ import javax.lang.model.type.TypeKind; */ final class AutoIngestJobNodeData { - private static final int CURRENT_VERSION = 1; + private static final int CURRENT_VERSION = 2; private static final int DEFAULT_PRIORITY = 0; /* @@ -47,7 +47,7 @@ final class AutoIngestJobNodeData { * data. This avoids the need to continuously enlarge the buffer. Once the * buffer has all the necessary data, it will be resized as appropriate. */ - private static final int MAX_POSSIBLE_NODE_DATA_SIZE = 131629; + private static final int MAX_POSSIBLE_NODE_DATA_SIZE = 131637; /* * Version 0 fields. @@ -73,6 +73,11 @@ final class AutoIngestJobNodeData { private long processingStageStartDate; private String processingStageDetailsDescription; // 'byte' length used in byte array private long processingStageDetailsStartDate; + + /* + * Version 2 fields. + */ + private long dataSourceSize; /** * Gets the current version of the auto ingest job coordination service node @@ -109,6 +114,7 @@ final class AutoIngestJobNodeData { setProcessingStage(job.getProcessingStage()); setProcessingStageStartDate(job.getProcessingStageStartDate()); setProcessingStageDetails(job.getProcessingStageDetails()); + //DLG: } /** @@ -143,6 +149,7 @@ final class AutoIngestJobNodeData { this.processingStageStartDate = 0L; this.processingStageDetailsDescription = ""; this.processingStageDetailsStartDate = 0L; + this.dataSourceSize = 0L; /* * Get fields from node data. @@ -177,6 +184,10 @@ final class AutoIngestJobNodeData { this.processingStageDetailsDescription = getStringFromBuffer(buffer, TypeKind.BYTE); this.processingStageDetailsStartDate = buffer.getLong(); this.processingHostName = getStringFromBuffer(buffer, TypeKind.SHORT); + + if (this.version >= 2) { + this.dataSourceSize = buffer.getLong(); + } } } catch (BufferUnderflowException ex) { @@ -498,6 +509,22 @@ final class AutoIngestJobNodeData { void setProcessingHostName(String processingHost) { this.processingHostName = processingHost; } + + /** + * DLG: + */ + long getDataSourceSize() { + return this.dataSourceSize; + } + + /** + * DLG: + * + * @param DLG: + */ + void setDataSourceSize(long dataSourceSize) { + this.dataSourceSize = dataSourceSize; + } /** * Gets the node data as a byte array that can be sent to the coordination @@ -515,7 +542,7 @@ final class AutoIngestJobNodeData { buffer.putLong(this.completedDate); buffer.putInt(this.errorsOccurred ? 1 : 0); - if (this.version > 0) { + if (this.version >= 1) { // Write version buffer.putInt(this.version); @@ -531,6 +558,10 @@ final class AutoIngestJobNodeData { putStringIntoBuffer(this.processingStageDetailsDescription, buffer, TypeKind.BYTE); buffer.putLong(this.processingStageDetailsStartDate); putStringIntoBuffer(processingHostName, buffer, TypeKind.SHORT); + + if (this.version >= 2) { + buffer.putLong(this.dataSourceSize); + } } // Prepare the array diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 35b563b961..d537c76146 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -2263,6 +2263,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen return; } + collectMetrics(/*DLG:*/); exportFiles(dataSource); } @@ -2543,6 +2544,14 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen currentJob.setIngestJob(null); } } + + /* + * DLG: + */ + private void collectMetrics(/*DLG:*/) { + + AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(currentJob); + } /** * Exports any files from the data source for the current job that From 49a631f351a276a08910a89e4796edaad133eecd Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 21 Nov 2017 11:17:52 -0500 Subject: [PATCH 44/90] Refactoring hash set import --- .../hashdatabase/EncaseHashSetParser.java | 83 ++-- .../HashDbImportDatabaseDialog.java | 5 +- .../modules/hashdatabase/HashSetParser.java | 49 +++ .../hashdatabase/IdxHashSetParser.java | 113 ++++++ .../ImportCentralRepoDbProgressDialog.java | 358 ++++++------------ 5 files changed, 322 insertions(+), 286 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java create mode 100644 Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java index df9d78b7a3..9d2d4709be 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java @@ -22,31 +22,24 @@ import java.io.InputStream; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; -import java.lang.StringBuilder; import java.util.Arrays; -import java.util.List; -import java.util.ArrayList; import java.util.logging.Level; -import javax.swing.JOptionPane; import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.TskCoreException; -class EncaseHashSetParser { - final byte[] encaseHeader = {(byte)0x48, (byte)0x41, (byte)0x53, (byte)0x48, (byte)0x0d, (byte)0x0a, (byte)0xff, (byte)0x00, +class EncaseHashSetParser implements HashSetParser { + private final byte[] encaseHeader = {(byte)0x48, (byte)0x41, (byte)0x53, (byte)0x48, (byte)0x0d, (byte)0x0a, (byte)0xff, (byte)0x00, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00}; - InputStream inputStream; - final int expectedHashes; - int totalHashesRead = 0; + private InputStream inputStream; + private final long expectedHashCount; + private int totalHashesRead = 0; /** * Opens the import file and parses the header. * @param filename The Encase hashset * @throws TskCoreException There was an error opening/reading the file or it is not the correct format */ - @NbBundle.Messages({"EncaseHashSetParser.fileOpenError.text=Error reading import file", - "EncaseHashSetParser.wrongFormat.text=Hashset is not Encase format"}) EncaseHashSetParser(String filename) throws TskCoreException{ try{ inputStream = new BufferedInputStream(new FileInputStream(filename)); @@ -55,16 +48,14 @@ class EncaseHashSetParser { byte[] header = new byte[16]; readBuffer(header, 16); if(! Arrays.equals(header, encaseHeader)){ - displayError(NbBundle.getMessage(this.getClass(), - "EncaseHashSetParser.wrongFormat.text")); close(); throw new TskCoreException("File " + filename + " does not have an Encase header"); } - // Read in the expected number of hashes + // Read in the expected number of hashes (little endian) byte[] sizeBuffer = new byte[4]; readBuffer(sizeBuffer, 4); - expectedHashes = ((sizeBuffer[3] & 0xff) << 24) | ((sizeBuffer[2] & 0xff) << 16) + expectedHashCount = ((sizeBuffer[3] & 0xff) << 24) | ((sizeBuffer[2] & 0xff) << 16) | ((sizeBuffer[1] & 0xff) << 8) | (sizeBuffer[0] & 0xff); // Read in a bunch of nulls @@ -80,8 +71,6 @@ class EncaseHashSetParser { readBuffer(typeBuffer, 0x28); } catch (IOException ex){ - displayError(NbBundle.getMessage(this.getClass(), - "EncaseHashSetParser.fileOpenError.text")); close(); throw new TskCoreException("Error reading " + filename, ex); } catch (TskCoreException ex){ @@ -90,21 +79,34 @@ class EncaseHashSetParser { } } - int getExpectedHashes(){ - return expectedHashes; + /** + * Get the expected number of hashes in the file. + * This number can be an estimate. + * @return The expected hash count + */ + @Override + public long getExpectedHashCount(){ + return expectedHashCount; } - synchronized boolean doneReading(){ - if(inputStream == null){ - return true; - } - - return(totalHashesRead >= expectedHashes); + /** + * Check if there are more hashes to read + * @return true if we've read all expected hash values, false otherwise + */ + @Override + public boolean doneReading(){ + return(totalHashesRead >= expectedHashCount); } - synchronized String getNextHash() throws TskCoreException{ + /** + * Get the next hash to import + * @return The hash as a string, or null if the end of file was reached without error + * @throws TskCoreException + */ + @Override + public String getNextHash() throws TskCoreException{ if(inputStream == null){ - return null; + throw new TskCoreException("Attempting to read from null inputStream"); } byte[] hashBytes = new byte[16]; @@ -122,14 +124,16 @@ class EncaseHashSetParser { totalHashesRead++; return sb.toString(); } catch (IOException ex){ - // Log it and return what we've got Logger.getLogger(EncaseHashSetParser.class.getName()).log(Level.SEVERE, "Ran out of data while reading Encase hash sets", ex); - close(); throw new TskCoreException("Error reading hash", ex); } } - synchronized final void close(){ + /** + * Closes the import file + */ + @Override + public final void close(){ if(inputStream != null){ try{ inputStream.close(); @@ -142,26 +146,13 @@ class EncaseHashSetParser { } @NbBundle.Messages({"EncaseHashSetParser.outOfData.text=Ran out of data while parsing file"}) - private synchronized void readBuffer(byte[] buffer, int length) throws TskCoreException, IOException { + private void readBuffer(byte[] buffer, int length) throws TskCoreException, IOException { if(inputStream == null){ throw new TskCoreException("readBuffer called on null inputStream"); } if(length != inputStream.read(buffer)){ - displayError(NbBundle.getMessage(this.getClass(), - "EncaseHashSetParser.outOfData.text")); close(); - throw new TskCoreException("Ran out of data while parsing Encase file"); - } - } - - @NbBundle.Messages({"EncaseHashSetParser.error.title=Error importing Encase hashset"}) - private void displayError(String errorText){ - if(RuntimeProperties.runningWithGUI()){ - JOptionPane.showMessageDialog(null, - errorText, - NbBundle.getMessage(this.getClass(), - "EncaseHashSetParser.error.title"), - JOptionPane.ERROR_MESSAGE); + throw new TskCoreException("Ran out of data unexpectedly while parsing Encase file"); } } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index a91ea45a16..670b7e8d19 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -447,7 +447,8 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { @NbBundle.Messages({"HashDbImportDatabaseDialog.missingVersion=A version must be entered", "HashDbImportDatabaseDialog.missingOrg=An organization must be selected", "HashDbImportDatabaseDialog.duplicateName=A hashset with this name and version already exists", - "HashDbImportDatabaseDialog.databaseLookupError=Error accessing central repository" + "HashDbImportDatabaseDialog.databaseLookupError=Error accessing central repository", + "HashDbImportDatabaseDialog.mustEnterHashSetNameMsg=A hash set name must be entered." }) private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed // Note that the error handlers in this method call return without disposing of the @@ -456,7 +457,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { if (hashSetNameTextField.getText().isEmpty()) { JOptionPane.showMessageDialog(this, NbBundle.getMessage(this.getClass(), - "HashDbCreateDatabaseDialog.mustEnterHashSetNameMsg"), + "HashDbImportDatabaseDialog.mustEnterHashSetNameMsg"), NbBundle.getMessage(this.getClass(), "HashDbImportDatabaseDialog.importHashDbErr"), JOptionPane.ERROR_MESSAGE); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java new file mode 100644 index 0000000000..fc45856af9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java @@ -0,0 +1,49 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011 - 2017 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.modules.hashdatabase; + +import org.sleuthkit.datamodel.TskCoreException; + +interface HashSetParser { + + /** + * Get the next hash to import + * @return The hash as a string, or null if the end of file was reached without error + * @throws TskCoreException + */ + String getNextHash() throws TskCoreException; + + /** + * Check if there are more hashes to read + * @return true if we've read all expected hash values, false otherwise + */ + boolean doneReading(); + + /** + * Get the expected number of hashes in the file. + * This number can be an estimate. + * @return The expected hash count + */ + long getExpectedHashCount(); + + /** + * Closes the import file + */ + void close(); +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java new file mode 100644 index 0000000000..9176002eda --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java @@ -0,0 +1,113 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011 - 2017 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.modules.hashdatabase; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.logging.Level; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Parser for idx files + */ +class IdxHashSetParser implements HashSetParser { + private String filename; + private BufferedReader reader; + private final long totalHashes; + private boolean doneReading = false; + + IdxHashSetParser(String filename) throws TskCoreException{ + this.filename = filename; + try{ + reader = new BufferedReader(new FileReader(filename)); + } catch (FileNotFoundException ex){ + throw new TskCoreException("Error opening file " + filename, ex); + } + + // Estimate the total number of hashes in the file since counting them all can be slow + File importFile = new File(filename); + long fileSize = importFile.length(); + totalHashes = fileSize / 0x33 + 1; // IDX file lines are generally 0x33 bytes long. We add one to prevent this from being zero + } + + /** + * Get the next hash to import + * @return The hash as a string, or null if the end of file was reached without error + * @throws TskCoreException + */ + @Override + public String getNextHash() throws TskCoreException { + String line; + + try{ + while ((line = reader.readLine()) != null) { + + String[] parts = line.split("\\|"); + + // Header lines start with a 41 character dummy hash, 1 character longer than a SHA-1 hash + if (parts.length != 2 || parts[0].length() == 41) { + continue; + } + + return parts[0].toLowerCase(); + } + } catch (IOException ex){ + throw new TskCoreException("Error reading file " + filename, ex); + } + + // We've run out of data + doneReading = true; + return null; + } + + /** + * Check if there are more hashes to read + * @return true if we've read all expected hash values, false otherwise + */ + @Override + public boolean doneReading() { + return doneReading; + } + + /** + * Get the expected number of hashes in the file. + * This number can be an estimate. + * @return The expected hash count + */ + @Override + public long getExpectedHashCount() { + return totalHashes; + } + + /** + * Closes the import file + */ + @Override + public void close() { + try{ + reader.close(); + } catch (IOException ex){ + Logger.getLogger(IdxHashSetParser.class.getName()).log(Level.SEVERE, "Error closing file " + filename, ex); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 240e4c19a5..9712edf904 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -19,12 +19,8 @@ package org.sleuthkit.autopsy.modules.hashdatabase; import java.awt.Color; -import java.awt.Cursor; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; import java.util.HashSet; import java.util.Set; import java.util.logging.Level; @@ -32,8 +28,8 @@ import javax.swing.JFrame; import javax.swing.SwingWorker; import javax.swing.WindowConstants; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.Executors; -import javax.swing.JOptionPane; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttribute; @@ -50,18 +46,8 @@ import org.sleuthkit.datamodel.TskData; */ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements PropertyChangeListener{ - private CentralRepoImportWorker worker; - - /** - * - * @param hashSetName - * @param version - * @param orgId - * @param searchDuringIngest - * @param sendIngestMessages - * @param knownFilesType - * @param importFile - */ + private CentralRepoImportWorker worker; // Swing worker that will import the file and send updates to the dialog + @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.title.text=Central Repository Import Progress", }) ImportCentralRepoDbProgressDialog() { @@ -78,29 +64,16 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P bnOk.setEnabled(false); } - @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.unknownFormat.message=Hash set to import is an unknown format"}) void importFile(String hashSetName, String version, int orgId, boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, - boolean readOnly, String importFileName){ - setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - - File importFile = new File(importFileName); - if(importFileName.toLowerCase().endsWith(".idx")){ - worker = new ImportIDXWorker(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages, - knownFilesType, readOnly, importFile); - } else if(importFileName.toLowerCase().endsWith(".hash")){ - worker = new ImportEncaseWorker(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages, - knownFilesType, readOnly, importFile); - } else { - // We've gotten here with a format that can't be processed - JOptionPane.showMessageDialog(null, Bundle.ImportCentralRepoDbProgressDialog_unknownFormat_message()); - return; - } + boolean readOnly, String importFileName){ + + worker = new CentralRepoImportWorker(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages, + knownFilesType, readOnly, importFileName); worker.addPropertyChangeListener(this); worker.execute(); setLocationRelativeTo((JFrame) WindowManager.getDefault().getMainWindow()); - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); this.setVisible(true); } @@ -111,53 +84,67 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P return null; } - @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.linesProcessed= hashes processed"}) + + /** + * Updates the dialog from events from the worker. + * The two events we handle are progress updates and + * the done event. + * @param evt + */ + @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.errorParsingFile.message=Error parsing hash set file"}) @Override public void propertyChange(PropertyChangeEvent evt) { if("progress".equals(evt.getPropertyName())){ - progressBar.setValue(worker.getProgressPercentage()); + // The progress has been updated. Update the progress bar and text + progressBar.setValue(worker.getProgress()); lbProgress.setText(getProgressString()); } else if ("state".equals(evt.getPropertyName()) && (SwingWorker.StateValue.DONE.equals(evt.getNewValue()))) { - // Disable cancel and enable ok + + // The worker is done processing + // Disable cancel button and enable ok bnCancel.setEnabled(false); bnOk.setEnabled(true); - if(worker.getError().isEmpty()){ + if(worker.getImportSuccess()){ + // If the import succeeded, finish the progress bar and display the + // total number of imported hashes progressBar.setValue(progressBar.getMaximum()); lbProgress.setText(getProgressString()); } else { + // If there was an error, reset the progress bar and display an error message progressBar.setValue(0); lbProgress.setForeground(Color.red); - lbProgress.setText(worker.getError()); + lbProgress.setText(Bundle.ImportCentralRepoDbProgressDialog_errorParsingFile_message()); } } } + @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.linesProcessed.message= hashes processed"}) private String getProgressString(){ - return worker.getLinesProcessed() + Bundle.ImportCentralRepoDbProgressDialog_linesProcessed(); + return worker.getLinesProcessed() + Bundle.ImportCentralRepoDbProgressDialog_linesProcessed_message(); } - abstract class CentralRepoImportWorker extends SwingWorker{ - final int HASH_IMPORT_THRESHOLD = 10000; - final String hashSetName; - final String version; - final int orgId; - final boolean searchDuringIngest; - final boolean sendIngestMessages; - final HashDbManager.HashDb.KnownFilesType knownFilesType; - final boolean readOnly; - final File importFile; - long totalHashes = 1; - int referenceSetID = -1; - HashDbManager.CentralRepoHashSet newHashDb = null; - final AtomicLong numLines = new AtomicLong(); - String errorString = ""; + class CentralRepoImportWorker extends SwingWorker{ + private final int HASH_IMPORT_THRESHOLD = 10000; + private final String hashSetName; + private final String version; + private final int orgId; + private final boolean searchDuringIngest; + private final boolean sendIngestMessages; + private final HashDbManager.HashDb.KnownFilesType knownFilesType; + private final boolean readOnly; + private final String importFileName; + private long totalHashes = 1; + private int referenceSetID = -1; + private HashDbManager.CentralRepoHashSet newHashDb = null; + private final AtomicLong numLines = new AtomicLong(); + private final AtomicBoolean importSuccess = new AtomicBoolean(); CentralRepoImportWorker(String hashSetName, String version, int orgId, boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, - boolean readOnly, File importFile){ + boolean readOnly, String importFileName){ this.hashSetName = hashSetName; this.version = version; @@ -166,11 +153,12 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P this.sendIngestMessages = sendIngestMessages; this.knownFilesType = knownFilesType; this.readOnly = readOnly; - this.importFile = importFile; + this.importFileName = importFileName; this.numLines.set(0); + this.importSuccess.set(false); } - HashDbManager.CentralRepoHashSet getDatabase(){ + synchronized HashDbManager.CentralRepoHashSet getDatabase(){ return newHashDb; } @@ -178,20 +166,81 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P return numLines.get(); } - int getProgressPercentage(){ - return this.getProgress(); + boolean getImportSuccess(){ + return importSuccess.get(); } - String getError(){ - return errorString; + @Override + protected Void doInBackground() throws Exception { + + // Create the hash set parser + HashSetParser hashSetParser; + if(importFileName.toLowerCase().endsWith(".idx")){ + hashSetParser = new IdxHashSetParser(importFileName); + } else + if(importFileName.toLowerCase().endsWith(".hash")){ + hashSetParser = new EncaseHashSetParser(importFileName); + } else { + // We've gotten here with a format that can't be processed + throw new TskCoreException("Hash set to import is an unknown format : " + importFileName); + } + + try{ + totalHashes = hashSetParser.getExpectedHashCount(); + + TskData.FileKnown knownStatus; + if (knownFilesType.equals(HashDbManager.HashDb.KnownFilesType.KNOWN)) { + knownStatus = TskData.FileKnown.KNOWN; + } else { + knownStatus = TskData.FileKnown.BAD; + } + + // Create an empty hashset in the central repository + referenceSetID = EamDb.getInstance().newReferenceSet(new EamGlobalSet(orgId, hashSetName, version, knownStatus, readOnly)); + + EamDb dbManager = EamDb.getInstance(); + CorrelationAttribute.Type contentType = dbManager.getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); // get "FILES" type + + Set globalInstances = new HashSet<>(); + + while (! hashSetParser.doneReading()) { + if(isCancelled()){ + return null; + } + + String newHash = hashSetParser.getNextHash(); + + if(newHash != null){ + EamGlobalFileInstance eamGlobalFileInstance = new EamGlobalFileInstance( + referenceSetID, + newHash, + knownStatus, + ""); + + globalInstances.add(eamGlobalFileInstance); + + if(numLines.incrementAndGet() % HASH_IMPORT_THRESHOLD == 0){ + dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType); + globalInstances.clear(); + + int progress = (int)(numLines.get() * 100 / totalHashes); + if(progress < 100){ + this.setProgress(progress); + } else { + this.setProgress(99); + } + } + } + } + + dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType); + this.setProgress(100); + return null; + } finally { + hashSetParser.close(); + } } - /** - * Should be called in the constructor to set the max number of hashes. - * The value can be updated later after parsing the import file. - */ - abstract void setEstimatedTotalHashes(); - void deleteIncompleteSet(){ if(referenceSetID >= 0){ @@ -209,10 +258,8 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } } - @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.importHashsetError=Error importing hash set", - "ImportCentralRepoDbProgressDialog.addDbError.message=Error adding new hash set"}) @Override - protected void done() { + synchronized protected void done() { if(isCancelled()){ // If the user hit cancel, delete this incomplete hash set from the central repo @@ -226,184 +273,19 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetName, version, referenceSetID, searchDuringIngest, sendIngestMessages, knownFilesType, readOnly); + importSuccess.set(true); } catch (TskCoreException ex){ - JOptionPane.showMessageDialog(null, Bundle.ImportCentralRepoDbProgressDialog_addDbError_message()); Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error adding imported hash set", ex); } } catch (Exception ex) { // Delete this incomplete hash set from the central repo deleteIncompleteSet(); - errorString = Bundle.ImportCentralRepoDbProgressDialog_importHashsetError(); + Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error importing hash set", ex); } } } - class ImportEncaseWorker extends CentralRepoImportWorker{ - - ImportEncaseWorker(String hashSetName, String version, int orgId, - boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, - boolean readOnly, File importFile){ - super(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages, knownFilesType, readOnly, importFile); - - setEstimatedTotalHashes(); - } - - - /** - * Encase files have a 0x480 byte header, then each hash takes 18 bytes - * @return Approximate number of hashes in the file - */ - @Override - final void setEstimatedTotalHashes(){ - long fileSize = importFile.length(); - if(fileSize < 0x492){ - totalHashes = 1; // There's room for at most one hash - } - totalHashes = (fileSize - 0x492) / 18; - } - - @Override - protected Void doInBackground() throws Exception { - - EncaseHashSetParser encaseParser = new EncaseHashSetParser(importFile.getAbsolutePath()); - totalHashes = encaseParser.getExpectedHashes(); - - TskData.FileKnown knownStatus; - if (knownFilesType.equals(HashDbManager.HashDb.KnownFilesType.KNOWN)) { - knownStatus = TskData.FileKnown.KNOWN; - } else { - knownStatus = TskData.FileKnown.BAD; - } - - // Create an empty hashset in the central repository - referenceSetID = EamDb.getInstance().newReferenceSet(new EamGlobalSet(orgId, hashSetName, version, knownStatus, readOnly)); - - EamDb dbManager = EamDb.getInstance(); - CorrelationAttribute.Type contentType = dbManager.getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); // get "FILES" type - - Set globalInstances = new HashSet<>(); - - while (! encaseParser.doneReading()) { - if(isCancelled()){ - return null; - } - - String newHash = encaseParser.getNextHash(); - - if(newHash != null){ - EamGlobalFileInstance eamGlobalFileInstance = new EamGlobalFileInstance( - referenceSetID, - newHash, - knownStatus, - ""); - - globalInstances.add(eamGlobalFileInstance); - numLines.incrementAndGet(); - - if(numLines.get() % HASH_IMPORT_THRESHOLD == 0){ - dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType); - globalInstances.clear(); - - int progress = (int)(numLines.get() * 100 / totalHashes); - if(progress < 100){ - this.setProgress(progress); - } else { - this.setProgress(99); - } - } - } - } - - dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType); - this.setProgress(100); - return null; - } - } - - - class ImportIDXWorker extends CentralRepoImportWorker{ - - ImportIDXWorker(String hashSetName, String version, int orgId, - boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, - boolean readOnly, File importFile){ - super(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages, knownFilesType, readOnly, importFile); - - setEstimatedTotalHashes(); - } - - /** - * Doing an actual count of the number of lines in a large idx file (such - * as the nsrl) is slow, so just get something in the general area for the - * progress bar. - * @return Approximate number of hashes in the file - */ - @Override - final void setEstimatedTotalHashes(){ - long fileSize = importFile.length(); - totalHashes = fileSize / 0x33 + 1; // IDX file lines are generally 0x33 bytes long, and we don't want this to be zero - } - - @Override - protected Void doInBackground() throws Exception { - - TskData.FileKnown knownStatus; - if (knownFilesType.equals(HashDbManager.HashDb.KnownFilesType.KNOWN)) { - knownStatus = TskData.FileKnown.KNOWN; - } else { - knownStatus = TskData.FileKnown.BAD; - } - - // Create an empty hashset in the central repository - referenceSetID = EamDb.getInstance().newReferenceSet(new EamGlobalSet(orgId, hashSetName, version, knownStatus, readOnly)); - - EamDb dbManager = EamDb.getInstance(); - CorrelationAttribute.Type contentType = dbManager.getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); // get "FILES" type - BufferedReader reader = new BufferedReader(new FileReader(importFile)); - String line; - Set globalInstances = new HashSet<>(); - - while ((line = reader.readLine()) != null) { - if(isCancelled()){ - return null; - } - - String[] parts = line.split("\\|"); - - // Header lines start with a 41 character dummy hash, 1 character longer than a SHA-1 hash - if (parts.length != 2 || parts[0].length() == 41) { - continue; - } - - EamGlobalFileInstance eamGlobalFileInstance = new EamGlobalFileInstance( - referenceSetID, - parts[0].toLowerCase(), - knownStatus, - ""); - - globalInstances.add(eamGlobalFileInstance); - numLines.incrementAndGet(); - - if(numLines.get() % HASH_IMPORT_THRESHOLD == 0){ - dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType); - globalInstances.clear(); - - int progress = (int)(numLines.get() * 100 / totalHashes); - if(progress < 100){ - this.setProgress(progress); - } else { - this.setProgress(99); - } - } - } - - dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType); - this.setProgress(100); - - return null; - } - } - /** * 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 From cc5c98fcb06f6a978e008eaa18ae9f9ae3afa415 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 21 Nov 2017 13:15:04 -0500 Subject: [PATCH 45/90] Cleanup --- .../hashdatabase/EncaseHashSetParser.java | 26 +++--- .../hashdatabase/IdxHashSetParser.java | 10 +-- .../ImportCentralRepoDbProgressDialog.java | 79 ++++++++++++++----- 3 files changed, 79 insertions(+), 36 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java index 9d2d4709be..cfc4b0b384 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java @@ -24,24 +24,30 @@ import java.io.FileInputStream; import java.io.IOException; import java.util.Arrays; import java.util.logging.Level; -import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.TskCoreException; +/** + * Parser for Encase format hash sets (*.hash) + */ class EncaseHashSetParser implements HashSetParser { private final byte[] encaseHeader = {(byte)0x48, (byte)0x41, (byte)0x53, (byte)0x48, (byte)0x0d, (byte)0x0a, (byte)0xff, (byte)0x00, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00}; - private InputStream inputStream; - private final long expectedHashCount; - private int totalHashesRead = 0; + private final String filename; // Name of the input file (saved for logging) + private InputStream inputStream; // File stream for file being imported + private final long expectedHashCount; // Number of hashes we expect to read from the file + private int totalHashesRead = 0; // Number of hashes that have been read /** * Opens the import file and parses the header. - * @param filename The Encase hashset + * If this is successful, the file will be set up to call getNextHash() to + * read the hash values. + * @param filename The Encase hash set * @throws TskCoreException There was an error opening/reading the file or it is not the correct format */ EncaseHashSetParser(String filename) throws TskCoreException{ try{ + this.filename = filename; inputStream = new BufferedInputStream(new FileInputStream(filename)); // Read in and test the 16 byte header @@ -70,6 +76,8 @@ class EncaseHashSetParser implements HashSetParser { byte[] typeBuffer = new byte[0x28]; readBuffer(typeBuffer, 0x28); + // At this point we're past the header and ready to read in the hashes + } catch (IOException ex){ close(); throw new TskCoreException("Error reading " + filename, ex); @@ -124,8 +132,7 @@ class EncaseHashSetParser implements HashSetParser { totalHashesRead++; return sb.toString(); } catch (IOException ex){ - Logger.getLogger(EncaseHashSetParser.class.getName()).log(Level.SEVERE, "Ran out of data while reading Encase hash sets", ex); - throw new TskCoreException("Error reading hash", ex); + throw new TskCoreException("Ran out of data while reading Encase hash set " + filename, ex); } } @@ -138,21 +145,20 @@ class EncaseHashSetParser implements HashSetParser { try{ inputStream.close(); } catch (IOException ex){ - Logger.getLogger(EncaseHashSetParser.class.getName()).log(Level.SEVERE, "Error closing Encase hash set", ex); + Logger.getLogger(EncaseHashSetParser.class.getName()).log(Level.SEVERE, "Error closing Encase hash set " + filename, ex); } finally { inputStream = null; } } } - @NbBundle.Messages({"EncaseHashSetParser.outOfData.text=Ran out of data while parsing file"}) private void readBuffer(byte[] buffer, int length) throws TskCoreException, IOException { if(inputStream == null){ throw new TskCoreException("readBuffer called on null inputStream"); } if(length != inputStream.read(buffer)){ close(); - throw new TskCoreException("Ran out of data unexpectedly while parsing Encase file"); + throw new TskCoreException("Ran out of data unexpectedly while parsing Encase file " + filename); } } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java index 9176002eda..af66b994e1 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java @@ -28,13 +28,13 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.TskCoreException; /** - * Parser for idx files + * Parser for idx files (*.idx) */ class IdxHashSetParser implements HashSetParser { - private String filename; - private BufferedReader reader; - private final long totalHashes; - private boolean doneReading = false; + private final String filename; // Name of the input file (saved for logging) + private BufferedReader reader; // Input file + private final long totalHashes; // Estimated number of hashes + private boolean doneReading = false; // Flag for if we've hit the end of the file IdxHashSetParser(String filename) throws TskCoreException{ this.filename = filename; diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 9712edf904..12f62ba8b1 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -29,6 +29,7 @@ import javax.swing.SwingWorker; import javax.swing.WindowConstants; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.Executors; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; @@ -42,7 +43,7 @@ import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; /** - * + * Imports a hash set into the central repository and updates a progress dialog */ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements PropertyChangeListener{ @@ -60,10 +61,24 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } private void customizeComponents(){ + // This is preventing the user from closing the dialog using the X setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + bnOk.setEnabled(false); } + /** + * Import the selected hash set into the central repository. + * Will bring up a progress dialog while the import is in progress. + * @param hashSetName + * @param version + * @param orgId + * @param searchDuringIngest + * @param sendIngestMessages + * @param knownFilesType + * @param readOnly + * @param importFileName + */ void importFile(String hashSetName, String version, int orgId, boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, boolean readOnly, String importFileName){ @@ -77,6 +92,11 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P this.setVisible(true); } + /** + * Get the HashDb object for the newly imported data. + * Should be called after importFile completes. + * @return The new HashDb object or null if the import failed/was canceled + */ HashDbManager.HashDb getDatabase(){ if(worker != null){ return worker.getDatabase(); @@ -123,10 +143,10 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.linesProcessed.message= hashes processed"}) private String getProgressString(){ - return worker.getLinesProcessed() + Bundle.ImportCentralRepoDbProgressDialog_linesProcessed_message(); + return worker.getNumHashesProcessed() + Bundle.ImportCentralRepoDbProgressDialog_linesProcessed_message(); } - class CentralRepoImportWorker extends SwingWorker{ + private class CentralRepoImportWorker extends SwingWorker{ private final int HASH_IMPORT_THRESHOLD = 10000; private final String hashSetName; private final String version; @@ -136,10 +156,9 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P private final HashDbManager.HashDb.KnownFilesType knownFilesType; private final boolean readOnly; private final String importFileName; - private long totalHashes = 1; - private int referenceSetID = -1; private HashDbManager.CentralRepoHashSet newHashDb = null; - private final AtomicLong numLines = new AtomicLong(); + private final AtomicInteger referenceSetID = new AtomicInteger(); + private final AtomicLong hashCount = new AtomicLong(); private final AtomicBoolean importSuccess = new AtomicBoolean(); CentralRepoImportWorker(String hashSetName, String version, int orgId, @@ -154,18 +173,31 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P this.knownFilesType = knownFilesType; this.readOnly = readOnly; this.importFileName = importFileName; - this.numLines.set(0); + this.hashCount.set(0); this.importSuccess.set(false); + this.referenceSetID.set(-1); } + /** + * Get the newly created database + * @return the imported database. May be null if an error occurred or the user canceled + */ synchronized HashDbManager.CentralRepoHashSet getDatabase(){ return newHashDb; } - long getLinesProcessed(){ - return numLines.get(); + /** + * Get the number of hashes that have been read in so far + * @return current hash count + */ + long getNumHashesProcessed(){ + return hashCount.get(); } + /** + * Check if the import was successful or if there was an error. + * @return true if the import process completed without error, false otherwise + */ boolean getImportSuccess(){ return importSuccess.get(); } @@ -186,8 +218,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } try{ - totalHashes = hashSetParser.getExpectedHashCount(); - + // Conver to the FileKnown enum used by EamGlobalSet TskData.FileKnown knownStatus; if (knownFilesType.equals(HashDbManager.HashDb.KnownFilesType.KNOWN)) { knownStatus = TskData.FileKnown.KNOWN; @@ -196,11 +227,14 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } // Create an empty hashset in the central repository - referenceSetID = EamDb.getInstance().newReferenceSet(new EamGlobalSet(orgId, hashSetName, version, knownStatus, readOnly)); - EamDb dbManager = EamDb.getInstance(); - CorrelationAttribute.Type contentType = dbManager.getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); // get "FILES" type + referenceSetID.set(dbManager.newReferenceSet(new EamGlobalSet(orgId, hashSetName, version, knownStatus, readOnly))); + // Get the "FILES" content type. This is a database lookup so we + // only want to do it once. + CorrelationAttribute.Type contentType = dbManager.getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); + + // Holds the current batch of hashes that need to be written to the central repo Set globalInstances = new HashSet<>(); while (! hashSetParser.doneReading()) { @@ -212,18 +246,20 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P if(newHash != null){ EamGlobalFileInstance eamGlobalFileInstance = new EamGlobalFileInstance( - referenceSetID, + referenceSetID.get(), newHash, knownStatus, ""); globalInstances.add(eamGlobalFileInstance); - if(numLines.incrementAndGet() % HASH_IMPORT_THRESHOLD == 0){ + // If we've hit the threshold for writing the hashes, write them + // all to the central repo + if(hashCount.incrementAndGet() % HASH_IMPORT_THRESHOLD == 0){ dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType); globalInstances.clear(); - int progress = (int)(numLines.get() * 100 / totalHashes); + int progress = (int)(hashCount.get() * 100 / hashSetParser.getExpectedHashCount()); if(progress < 100){ this.setProgress(progress); } else { @@ -233,6 +269,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } } + // Add any remaining hashes to the central repo dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType); this.setProgress(100); return null; @@ -241,15 +278,15 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } } - void deleteIncompleteSet(){ - if(referenceSetID >= 0){ + private void deleteIncompleteSet(){ + if(referenceSetID.get() >= 0){ // This can be slow on large reference sets Executors.newSingleThreadExecutor().execute(new Runnable() { @Override public void run() { try{ - EamDb.getInstance().deleteReferenceSet(referenceSetID); + EamDb.getInstance().deleteReferenceSet(referenceSetID.get()); } catch (EamDbException ex2){ Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error deleting incomplete hash set from central repository", ex2); } @@ -271,7 +308,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P get(); try{ newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetName, version, - referenceSetID, + referenceSetID.get(), searchDuringIngest, sendIngestMessages, knownFilesType, readOnly); importSuccess.set(true); } catch (TskCoreException ex){ From 05615a4b15b022b21de70f624cb69c1c3ad83859 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 21 Nov 2017 14:43:50 -0500 Subject: [PATCH 46/90] Add kdb parser --- .../HashDbImportDatabaseDialog.java | 4 +- .../ImportCentralRepoDbProgressDialog.java | 5 +- .../hashdatabase/KdbHashSetParser.java | 147 ++++++++++++++++++ 3 files changed, 152 insertions(+), 4 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index 670b7e8d19..f0055fc181 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -88,11 +88,11 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { fileChooser.setMultiSelectionEnabled(false); } - @NbBundle.Messages({"HashDbImportDatabaseDialog.centralRepoExtFilter.text=Hash Database File (.idx or .hash only)"}) + @NbBundle.Messages({"HashDbImportDatabaseDialog.centralRepoExtFilter.text=Hash Database File (.kdb, .idx or .hash)"}) private void updateFileChooserFilter() { fileChooser.resetChoosableFileFilters(); if(centralRepoRadioButton.isSelected()){ - String[] EXTENSION = new String[]{"hash", "Hash", "idx"}; //NON-NLS + String[] EXTENSION = new String[]{"kdb", "idx", "hash", "Hash"}; //NON-NLS FileNameExtensionFilter filter = new FileNameExtensionFilter( NbBundle.getMessage(this.getClass(), "HashDbImportDatabaseDialog.centralRepoExtFilter.text"), EXTENSION); fileChooser.setFileFilter(filter); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 12f62ba8b1..0a6e6cf644 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -209,9 +209,10 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P HashSetParser hashSetParser; if(importFileName.toLowerCase().endsWith(".idx")){ hashSetParser = new IdxHashSetParser(importFileName); - } else - if(importFileName.toLowerCase().endsWith(".hash")){ + } else if(importFileName.toLowerCase().endsWith(".hash")){ hashSetParser = new EncaseHashSetParser(importFileName); + } else if(importFileName.toLowerCase().endsWith(".kdb")){ + hashSetParser = new KdbHashSetParser(importFileName); } else { // We've gotten here with a format that can't be processed throw new TskCoreException("Hash set to import is an unknown format : " + importFileName); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java new file mode 100644 index 0000000000..944780936b --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java @@ -0,0 +1,147 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.modules.hashdatabase; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.logging.Level; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * + */ +public class KdbHashSetParser implements HashSetParser { + private final String JDBC_DRIVER = "org.sqlite.JDBC"; // NON-NLS + private final String JDBC_BASE_URI = "jdbc:sqlite:"; // NON-NLS + + private final String filename; // Name of the input file (saved for logging) + private final long totalHashes; // Estimated number of hashes + private int totalHashesRead = 0; // Number of hashes that have been read + private Connection conn; + private Statement statement; + private ResultSet resultSet; + + + KdbHashSetParser(String filename) throws TskCoreException{ + this.filename = filename; + + conn = null; + statement = null; + resultSet = null; + + try{ + // Open the database + StringBuilder connectionURL = new StringBuilder(); + connectionURL.append(JDBC_BASE_URI); + connectionURL.append(filename); + Class.forName(JDBC_DRIVER); + conn = DriverManager.getConnection(connectionURL.toString()); + + // Get the number of hashes in the table + statement = conn.createStatement(); + resultSet = statement.executeQuery("SELECT count(*) AS count FROM hashes"); + if (resultSet.next()) { + totalHashes = resultSet.getLong("count"); + } else { + close(); + throw new TskCoreException("Error getting hash count from database " + filename); + } + + // Get the hashes + resultSet = statement.executeQuery("SELECT md5 FROM hashes"); + + // At this point, getNextHash can read each hash from the result set + + } catch (ClassNotFoundException | SQLException ex){ + throw new TskCoreException("Error opening/reading database " + filename, ex); + } + + } + + /** + * Get the next hash to import + * @return The hash as a string, or null if the end of file was reached without error + * @throws TskCoreException + */ + @Override + public String getNextHash() throws TskCoreException { + + try{ + if(resultSet.next()){ + byte[] hashBytes = resultSet.getBytes("md5"); + StringBuilder sb = new StringBuilder(); + for (byte b : hashBytes) { + sb.append(String.format("%02x", b)); + } + + if(sb.toString().length() != 32){ + throw new TskCoreException("Hash has incorrect length: " + sb.toString()); + } + + totalHashesRead++; + return sb.toString(); + } else { + throw new TskCoreException("Could not read expected number of hashes from database " + filename); + } + } catch (SQLException ex){ + throw new TskCoreException("Error reading hash from result set for database " + filename, ex); + } + } + + /** + * Check if there are more hashes to read + * @return true if we've read all expected hash values, false otherwise + */ + @Override + public boolean doneReading() { + return(totalHashesRead >= totalHashes); + } + + /** + * Get the expected number of hashes in the file. + * This number can be an estimate. + * @return The expected hash count + */ + @Override + public long getExpectedHashCount() { + return totalHashes; + } + + /** + * Closes the import file + */ + @Override + public final void close() { + if(statement != null){ + try { + statement.close(); + } catch (SQLException ex) { + Logger.getLogger(KdbHashSetParser.class.getName()).log(Level.SEVERE, "Error closing prepared statement.", ex); + } + } + + if(resultSet != null){ + try { + resultSet.close(); + } catch (SQLException ex) { + Logger.getLogger(KdbHashSetParser.class.getName()).log(Level.SEVERE, "Error closing result set.", ex); + } + } + + if(conn != null){ + try { + conn.close(); + } catch (SQLException ex) { + Logger.getLogger(KdbHashSetParser.class.getName()).log(Level.SEVERE, "Error closing connection.", ex); + } + } + } +} From 1c646aa184e06b3b593078a9fdaaf7eeb9157deb Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 21 Nov 2017 14:47:08 -0500 Subject: [PATCH 47/90] Fixed version check to only apply if hash set is read only --- .../modules/hashdatabase/HashDbImportDatabaseDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index 670b7e8d19..2937d53983 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -465,7 +465,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { } if(centralRepoRadioButton.isSelected()){ - if(versionTextField.getText().isEmpty()){ + if(readOnlyCheckbox.isSelected() && versionTextField.getText().isEmpty()){ JOptionPane.showMessageDialog(this, NbBundle.getMessage(this.getClass(), "HashDbImportDatabaseDialog.missingVersion"), From 0057a18c49aea94c2b8944bb52631551f8a17493 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 21 Nov 2017 15:41:09 -0500 Subject: [PATCH 48/90] Move clearing of list of new hash sets Formatting --- .../hashdatabase/EncaseHashSetParser.java | 93 ++++----- .../hashdatabase/HashLookupSettingsPanel.java | 112 +++++------ .../modules/hashdatabase/HashSetParser.java | 20 +- .../hashdatabase/IdxHashSetParser.java | 45 +++-- .../ImportCentralRepoDbProgressDialog.java | 179 +++++++++--------- 5 files changed, 236 insertions(+), 213 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java index cfc4b0b384..8ea9bc3c46 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java @@ -31,95 +31,100 @@ import org.sleuthkit.datamodel.TskCoreException; * Parser for Encase format hash sets (*.hash) */ class EncaseHashSetParser implements HashSetParser { - private final byte[] encaseHeader = {(byte)0x48, (byte)0x41, (byte)0x53, (byte)0x48, (byte)0x0d, (byte)0x0a, (byte)0xff, (byte)0x00, - (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00}; + + private final byte[] encaseHeader = {(byte) 0x48, (byte) 0x41, (byte) 0x53, (byte) 0x48, (byte) 0x0d, (byte) 0x0a, (byte) 0xff, (byte) 0x00, + (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00}; private final String filename; // Name of the input file (saved for logging) private InputStream inputStream; // File stream for file being imported private final long expectedHashCount; // Number of hashes we expect to read from the file private int totalHashesRead = 0; // Number of hashes that have been read - + /** - * Opens the import file and parses the header. - * If this is successful, the file will be set up to call getNextHash() to - * read the hash values. + * Opens the import file and parses the header. If this is successful, the + * file will be set up to call getNextHash() to read the hash values. + * * @param filename The Encase hash set - * @throws TskCoreException There was an error opening/reading the file or it is not the correct format + * @throws TskCoreException There was an error opening/reading the file or + * it is not the correct format */ - EncaseHashSetParser(String filename) throws TskCoreException{ - try{ + EncaseHashSetParser(String filename) throws TskCoreException { + try { this.filename = filename; inputStream = new BufferedInputStream(new FileInputStream(filename)); - + // Read in and test the 16 byte header byte[] header = new byte[16]; readBuffer(header, 16); - if(! Arrays.equals(header, encaseHeader)){ + if (!Arrays.equals(header, encaseHeader)) { close(); throw new TskCoreException("File " + filename + " does not have an Encase header"); } - + // Read in the expected number of hashes (little endian) byte[] sizeBuffer = new byte[4]; readBuffer(sizeBuffer, 4); expectedHashCount = ((sizeBuffer[3] & 0xff) << 24) | ((sizeBuffer[2] & 0xff) << 16) - | ((sizeBuffer[1] & 0xff) << 8) | (sizeBuffer[0] & 0xff); - + | ((sizeBuffer[1] & 0xff) << 8) | (sizeBuffer[0] & 0xff); + // Read in a bunch of nulls byte[] filler = new byte[0x3f4]; readBuffer(filler, 0x3f4); - + // Read in the hash set name byte[] nameBuffer = new byte[0x50]; readBuffer(nameBuffer, 0x50); - + // Read in the hash set type byte[] typeBuffer = new byte[0x28]; - readBuffer(typeBuffer, 0x28); - + readBuffer(typeBuffer, 0x28); + // At this point we're past the header and ready to read in the hashes - - } catch (IOException ex){ + } catch (IOException ex) { close(); throw new TskCoreException("Error reading " + filename, ex); - } catch (TskCoreException ex){ + } catch (TskCoreException ex) { close(); throw ex; } } - + /** - * Get the expected number of hashes in the file. - * This number can be an estimate. + * Get the expected number of hashes in the file. This number can be an + * estimate. + * * @return The expected hash count */ @Override - public long getExpectedHashCount(){ + public long getExpectedHashCount() { return expectedHashCount; } - + /** * Check if there are more hashes to read + * * @return true if we've read all expected hash values, false otherwise */ @Override - public boolean doneReading(){ - return(totalHashesRead >= expectedHashCount); + public boolean doneReading() { + return (totalHashesRead >= expectedHashCount); } - + /** * Get the next hash to import - * @return The hash as a string, or null if the end of file was reached without error - * @throws TskCoreException + * + * @return The hash as a string, or null if the end of file was reached + * without error + * @throws TskCoreException */ @Override - public String getNextHash() throws TskCoreException{ - if(inputStream == null){ + public String getNextHash() throws TskCoreException { + if (inputStream == null) { throw new TskCoreException("Attempting to read from null inputStream"); } - + byte[] hashBytes = new byte[16]; byte[] divider = new byte[2]; - try{ + try { readBuffer(hashBytes, 16); readBuffer(divider, 2); @@ -131,32 +136,32 @@ class EncaseHashSetParser implements HashSetParser { totalHashesRead++; return sb.toString(); - } catch (IOException ex){ + } catch (IOException ex) { throw new TskCoreException("Ran out of data while reading Encase hash set " + filename, ex); } } - + /** * Closes the import file */ @Override - public final void close(){ - if(inputStream != null){ - try{ + public final void close() { + if (inputStream != null) { + try { inputStream.close(); - } catch (IOException ex){ + } catch (IOException ex) { Logger.getLogger(EncaseHashSetParser.class.getName()).log(Level.SEVERE, "Error closing Encase hash set " + filename, ex); } finally { inputStream = null; } } } - + private void readBuffer(byte[] buffer, int length) throws TskCoreException, IOException { - if(inputStream == null){ + if (inputStream == null) { throw new TskCoreException("readBuffer called on null inputStream"); } - if(length != inputStream.read(buffer)){ + if (length != inputStream.read(buffer)) { close(); throw new TskCoreException("Ran out of data unexpectedly while parsing Encase file " + filename); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java index e7bfcecf1e..17c629c50a 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java @@ -127,7 +127,6 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan hashDbOrgLabel.setText(NO_SELECTION_TEXT); hashDbReadOnlyLabel.setText(NO_SELECTION_TEXT); indexPathLabel.setText(NO_SELECTION_TEXT); - // Update indexing components. hashDbIndexStatusLabel.setText(NO_SELECTION_TEXT); @@ -162,14 +161,14 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan // Update descriptive labels. hashDbNameLabel.setText(db.getHashSetName()); - hashDbTypeLabel.setText(db.getKnownFilesType().getDisplayName()); - try{ - if(db.isUpdateable()){ + hashDbTypeLabel.setText(db.getKnownFilesType().getDisplayName()); + try { + if (db.isUpdateable()) { hashDbReadOnlyLabel.setText(Bundle.HashLookupSettingsPanel_editable()); } else { hashDbReadOnlyLabel.setText(Bundle.HashLookupSettingsPanel_readOnly()); } - } catch (TskCoreException ex){ + } catch (TskCoreException ex) { hashDbReadOnlyLabel.setText(Bundle.HashLookupSettingsPanel_updateStatusError()); } @@ -180,30 +179,30 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan addHashesToDatabaseButton.setEnabled(false); } - if(db instanceof SleuthkitHashSet){ - SleuthkitHashSet hashDb = (SleuthkitHashSet)db; - + if (db instanceof SleuthkitHashSet) { + SleuthkitHashSet hashDb = (SleuthkitHashSet) db; + // Disable the central repo fields hashDbVersionLabel.setText(Bundle.HashLookupSettingsPanel_notApplicable()); hashDbOrgLabel.setText(Bundle.HashLookupSettingsPanel_notApplicable()); - + // Enable the delete button if ingest is not running deleteDatabaseButton.setEnabled(!ingestIsRunning); - + try { hashDbLocationLabel.setText(shortenPath(db.getDatabasePath())); } catch (TskCoreException ex) { Logger.getLogger(HashLookupSettingsPanel.class.getName()).log(Level.SEVERE, "Error getting database path of " + db.getHashSetName() + " hash database", ex); //NON-NLS hashDbLocationLabel.setText(ERROR_GETTING_PATH_TEXT); } - + try { indexPathLabel.setText(shortenPath(hashDb.getIndexPath())); } catch (TskCoreException ex) { Logger.getLogger(HashLookupSettingsPanel.class.getName()).log(Level.SEVERE, "Error getting index path of " + db.getHashSetName() + " hash database", ex); //NON-NLS indexPathLabel.setText(ERROR_GETTING_PATH_TEXT); } - + // Update indexing components. try { if (hashDb.isIndexing()) { @@ -245,15 +244,15 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan indexButton.setEnabled(false); } } else { - + // Disable the file type fields/buttons indexPathLabel.setText(Bundle.HashLookupSettingsPanel_notApplicable()); hashDbIndexStatusLabel.setText(Bundle.HashLookupSettingsPanel_notApplicable()); hashDbLocationLabel.setText(Bundle.HashLookupSettingsPanel_centralRepo()); indexButton.setEnabled(false); deleteDatabaseButton.setEnabled(false); - - CentralRepoHashSet crDb = (CentralRepoHashSet)db; + + CentralRepoHashSet crDb = (CentralRepoHashSet) db; hashDbVersionLabel.setText(crDb.getVersion()); hashDbOrgLabel.setText(crDb.getOrgName()); @@ -302,13 +301,17 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan @Override @Messages({"HashLookupSettingsPanel.saveFail.message=Couldn't save hash db settings.", "HashLookupSettingsPanel.saveFail.title=Save Fail"}) - public void saveSettings() { + public void saveSettings() { + + // Clear out the list of unsaved hashes + newReferenceSetIDs.clear(); + //Checking for for any unindexed databases List unindexed = new ArrayList<>(); for (HashDb db : hashSetManager.getAllHashSets()) { - if(db instanceof SleuthkitHashSet){ + if (db instanceof SleuthkitHashSet) { try { - SleuthkitHashSet hashDatabase = (SleuthkitHashSet)db; + SleuthkitHashSet hashDatabase = (SleuthkitHashSet) db; if (!hashDatabase.hasIndex()) { unindexed.add(hashDatabase); } @@ -320,10 +323,10 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan // If there are unindexed databases, give the user the option to index them now. This // needs to be on the EDT, and will save the hash settings after completing - if(! unindexed.isEmpty()){ - SwingUtilities.invokeLater(new Runnable(){ + if (!unindexed.isEmpty()) { + SwingUtilities.invokeLater(new Runnable() { @Override - public void run(){ + public void run() { //If unindexed ones are found, show a popup box that will either index them, or remove them. if (unindexed.size() == 1) { showInvalidIndex(false, unindexed); @@ -335,7 +338,6 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan } else { try { hashSetManager.save(); - newReferenceSetIDs.clear(); } catch (HashDbManager.HashDbManagerException ex) { SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(null, Bundle.HashLookupSettingsPanel_saveFail_message(), Bundle.HashLookupSettingsPanel_saveFail_title(), JOptionPane.ERROR_MESSAGE); @@ -363,20 +365,20 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan */ if (IngestManager.getInstance().isIngestRunning() == false) { // Remove any new central repo hash sets from the database - for(int refID:newReferenceSetIDs){ - try{ - if(EamDb.isEnabled()){ + for (int refID : newReferenceSetIDs) { + try { + if (EamDb.isEnabled()) { EamDb.getInstance().deleteReferenceSet(refID); } else { // This is the case where the user imported a database, then switched over to the central // repo panel and disabled it before cancelling. We can't delete the database at this point. Logger.getLogger(HashLookupSettingsPanel.class.getName()).log(Level.WARNING, "Error reverting central repository hash sets"); //NON-NLS } - } catch (EamDbException ex){ + } catch (EamDbException ex) { Logger.getLogger(HashLookupSettingsPanel.class.getName()).log(Level.SEVERE, "Error reverting central repository hash sets", ex); //NON-NLS } } - + HashDbManager.getInstance().loadLastSavedConfiguration(); } } @@ -398,7 +400,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan * unindexed, along with solutions. This method is related to * ModalNoButtons, to be removed at a later date. * - * @param plural Whether or not there are multiple unindexed databases + * @param plural Whether or not there are multiple unindexed databases * @param unindexed The list of unindexed databases. Can be of size 1. */ private void showInvalidIndex(boolean plural, List unindexed) { @@ -471,8 +473,8 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan getSelectionModel().setSelectionInterval(index, index); } } - - public void selectRowByDatabase(HashDb db){ + + public void selectRowByDatabase(HashDb db) { setSelection(hashSetTableModel.getIndexByDatabase(db)); } @@ -510,7 +512,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan return hashSets.get(rowIndex).getDisplayName(); } - private boolean isValid(int rowIndex) { + private boolean isValid(int rowIndex) { try { return hashSets.get(rowIndex).isValid(); } catch (TskCoreException ex) { @@ -543,15 +545,15 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan } } - int getIndexByDatabase(HashDb db){ + int getIndexByDatabase(HashDb db) { for (int i = 0; i < hashSets.size(); ++i) { if (hashSets.get(i).equals(db)) { return i; } } - return -1; + return -1; } - + @Deprecated int getIndexByName(String name) { for (int i = 0; i < hashSets.size(); ++i) { @@ -934,11 +936,11 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan private void createDatabaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createDatabaseButtonActionPerformed HashDb hashDb = new HashDbCreateDatabaseDialog().getHashDatabase(); if (null != hashDb) { - if(hashDb instanceof CentralRepoHashSet){ - int newDbIndex = ((CentralRepoHashSet)hashDb).getReferenceSetID(); + if (hashDb instanceof CentralRepoHashSet) { + int newDbIndex = ((CentralRepoHashSet) hashDb).getReferenceSetID(); newReferenceSetIDs.add(newDbIndex); } - + hashSetTableModel.refreshModel(); ((HashSetTable) hashSetTable).selectRowByDatabase(hashDb); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); @@ -960,7 +962,7 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan // Add a listener for the INDEXING_DONE event. This listener will update // the UI. - SleuthkitHashSet hashDb = (SleuthkitHashSet)hashDatabase; + SleuthkitHashSet hashDb = (SleuthkitHashSet) hashDatabase; hashDb.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { @@ -988,11 +990,11 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan private void importDatabaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importDatabaseButtonActionPerformed HashDb hashDb = new HashDbImportDatabaseDialog().getHashDatabase(); if (null != hashDb) { - if(hashDb instanceof CentralRepoHashSet){ - int newReferenceSetID = ((CentralRepoHashSet)hashDb).getReferenceSetID(); + if (hashDb instanceof CentralRepoHashSet) { + int newReferenceSetID = ((CentralRepoHashSet) hashDb).getReferenceSetID(); newReferenceSetIDs.add(newReferenceSetID); } - + hashSetTableModel.refreshModel(); ((HashSetTable) hashSetTable).selectRowByDatabase(hashDb); firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); @@ -1002,21 +1004,21 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan @Messages({}) private void deleteDatabaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteDatabaseButtonActionPerformed if (JOptionPane.showConfirmDialog(null, - NbBundle.getMessage(this.getClass(), - "HashDbConfigPanel.deleteDbActionConfirmMsg"), - NbBundle.getMessage(this.getClass(), "HashDbConfigPanel.deleteDbActionMsg"), - JOptionPane.YES_NO_OPTION, - JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { - HashDb hashDb = ((HashSetTable) hashSetTable).getSelection(); - if (hashDb != null) { - try { - hashSetManager.removeHashDatabaseNoSave(hashDb); - } catch (HashDbManager.HashDbManagerException ex) { - JOptionPane.showMessageDialog(null, Bundle.HashLookupSettingsPanel_removeDatabaseFailure_message(hashDb.getHashSetName())); + NbBundle.getMessage(this.getClass(), + "HashDbConfigPanel.deleteDbActionConfirmMsg"), + NbBundle.getMessage(this.getClass(), "HashDbConfigPanel.deleteDbActionMsg"), + JOptionPane.YES_NO_OPTION, + JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { + HashDb hashDb = ((HashSetTable) hashSetTable).getSelection(); + if (hashDb != null) { + try { + hashSetManager.removeHashDatabaseNoSave(hashDb); + } catch (HashDbManager.HashDbManagerException ex) { + JOptionPane.showMessageDialog(null, Bundle.HashLookupSettingsPanel_removeDatabaseFailure_message(hashDb.getHashSetName())); + } + hashSetTableModel.refreshModel(); + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); } - hashSetTableModel.refreshModel(); - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - } } }//GEN-LAST:event_deleteDatabaseButtonActionPerformed diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java index fc45856af9..8a7a3ae034 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashSetParser.java @@ -21,27 +21,31 @@ package org.sleuthkit.autopsy.modules.hashdatabase; import org.sleuthkit.datamodel.TskCoreException; interface HashSetParser { - + /** * Get the next hash to import - * @return The hash as a string, or null if the end of file was reached without error - * @throws TskCoreException + * + * @return The hash as a string, or null if the end of file was reached + * without error + * @throws TskCoreException */ String getNextHash() throws TskCoreException; - + /** * Check if there are more hashes to read + * * @return true if we've read all expected hash values, false otherwise */ boolean doneReading(); - + /** - * Get the expected number of hashes in the file. - * This number can be an estimate. + * Get the expected number of hashes in the file. This number can be an + * estimate. + * * @return The expected hash count */ long getExpectedHashCount(); - + /** * Closes the import file */ diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java index af66b994e1..0c1b694e1b 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java @@ -31,35 +31,38 @@ import org.sleuthkit.datamodel.TskCoreException; * Parser for idx files (*.idx) */ class IdxHashSetParser implements HashSetParser { + private final String filename; // Name of the input file (saved for logging) private BufferedReader reader; // Input file private final long totalHashes; // Estimated number of hashes private boolean doneReading = false; // Flag for if we've hit the end of the file - - IdxHashSetParser(String filename) throws TskCoreException{ + + IdxHashSetParser(String filename) throws TskCoreException { this.filename = filename; - try{ + try { reader = new BufferedReader(new FileReader(filename)); - } catch (FileNotFoundException ex){ + } catch (FileNotFoundException ex) { throw new TskCoreException("Error opening file " + filename, ex); } - + // Estimate the total number of hashes in the file since counting them all can be slow File importFile = new File(filename); long fileSize = importFile.length(); totalHashes = fileSize / 0x33 + 1; // IDX file lines are generally 0x33 bytes long. We add one to prevent this from being zero } - + /** * Get the next hash to import - * @return The hash as a string, or null if the end of file was reached without error - * @throws TskCoreException + * + * @return The hash as a string, or null if the end of file was reached + * without error + * @throws TskCoreException */ @Override public String getNextHash() throws TskCoreException { String line; - - try{ + + try { while ((line = reader.readLine()) != null) { String[] parts = line.split("\\|"); @@ -68,45 +71,47 @@ class IdxHashSetParser implements HashSetParser { if (parts.length != 2 || parts[0].length() == 41) { continue; } - + return parts[0].toLowerCase(); } - } catch (IOException ex){ + } catch (IOException ex) { throw new TskCoreException("Error reading file " + filename, ex); } - + // We've run out of data doneReading = true; return null; } - + /** * Check if there are more hashes to read + * * @return true if we've read all expected hash values, false otherwise */ @Override public boolean doneReading() { return doneReading; } - + /** - * Get the expected number of hashes in the file. - * This number can be an estimate. + * Get the expected number of hashes in the file. This number can be an + * estimate. + * * @return The expected hash count */ @Override public long getExpectedHashCount() { return totalHashes; } - + /** * Closes the import file */ @Override public void close() { - try{ + try { reader.close(); - } catch (IOException ex){ + } catch (IOException ex) { Logger.getLogger(IdxHashSetParser.class.getName()).log(Level.SEVERE, "Error closing file " + filename, ex); } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 12f62ba8b1..8e799f4164 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -45,31 +45,31 @@ import org.sleuthkit.datamodel.TskData; /** * Imports a hash set into the central repository and updates a progress dialog */ -class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements PropertyChangeListener{ +class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements PropertyChangeListener { private CentralRepoImportWorker worker; // Swing worker that will import the file and send updates to the dialog - @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.title.text=Central Repository Import Progress", - }) + @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.title.text=Central Repository Import Progress",}) ImportCentralRepoDbProgressDialog() { super((JFrame) WindowManager.getDefault().getMainWindow(), Bundle.ImportCentralRepoDbProgressDialog_title_text(), true); - - initComponents(); + + initComponents(); customizeComponents(); } - - private void customizeComponents(){ + + private void customizeComponents() { // This is preventing the user from closing the dialog using the X setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - + bnOk.setEnabled(false); } - + /** - * Import the selected hash set into the central repository. - * Will bring up a progress dialog while the import is in progress. + * Import the selected hash set into the central repository. Will bring up a + * progress dialog while the import is in progress. + * * @param hashSetName * @param version * @param orgId @@ -77,57 +77,57 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P * @param sendIngestMessages * @param knownFilesType * @param readOnly - * @param importFileName + * @param importFileName */ void importFile(String hashSetName, String version, int orgId, boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, - boolean readOnly, String importFileName){ + boolean readOnly, String importFileName) { - worker = new CentralRepoImportWorker(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages, + worker = new CentralRepoImportWorker(hashSetName, version, orgId, searchDuringIngest, sendIngestMessages, knownFilesType, readOnly, importFileName); worker.addPropertyChangeListener(this); worker.execute(); - - setLocationRelativeTo((JFrame) WindowManager.getDefault().getMainWindow()); + + setLocationRelativeTo((JFrame) WindowManager.getDefault().getMainWindow()); this.setVisible(true); } - + /** - * Get the HashDb object for the newly imported data. - * Should be called after importFile completes. + * Get the HashDb object for the newly imported data. Should be called after + * importFile completes. + * * @return The new HashDb object or null if the import failed/was canceled */ - HashDbManager.HashDb getDatabase(){ - if(worker != null){ + HashDbManager.HashDb getDatabase() { + if (worker != null) { return worker.getDatabase(); } return null; } - - + /** - * Updates the dialog from events from the worker. - * The two events we handle are progress updates and - * the done event. - * @param evt + * Updates the dialog from events from the worker. The two events we handle + * are progress updates and the done event. + * + * @param evt */ @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.errorParsingFile.message=Error parsing hash set file"}) @Override public void propertyChange(PropertyChangeEvent evt) { - - if("progress".equals(evt.getPropertyName())){ + + if ("progress".equals(evt.getPropertyName())) { // The progress has been updated. Update the progress bar and text progressBar.setValue(worker.getProgress()); lbProgress.setText(getProgressString()); } else if ("state".equals(evt.getPropertyName()) && (SwingWorker.StateValue.DONE.equals(evt.getNewValue()))) { - + // The worker is done processing // Disable cancel button and enable ok bnCancel.setEnabled(false); bnOk.setEnabled(true); - - if(worker.getImportSuccess()){ + + if (worker.getImportSuccess()) { // If the import succeeded, finish the progress bar and display the // total number of imported hashes progressBar.setValue(progressBar.getMaximum()); @@ -140,13 +140,14 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } } } - + @NbBundle.Messages({"ImportCentralRepoDbProgressDialog.linesProcessed.message= hashes processed"}) - private String getProgressString(){ + private String getProgressString() { return worker.getNumHashesProcessed() + Bundle.ImportCentralRepoDbProgressDialog_linesProcessed_message(); } - - private class CentralRepoImportWorker extends SwingWorker{ + + private class CentralRepoImportWorker extends SwingWorker { + private final int HASH_IMPORT_THRESHOLD = 10000; private final String hashSetName; private final String version; @@ -160,11 +161,11 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P private final AtomicInteger referenceSetID = new AtomicInteger(); private final AtomicLong hashCount = new AtomicLong(); private final AtomicBoolean importSuccess = new AtomicBoolean(); - + CentralRepoImportWorker(String hashSetName, String version, int orgId, - boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, - boolean readOnly, String importFileName){ - + boolean searchDuringIngest, boolean sendIngestMessages, HashDbManager.HashDb.KnownFilesType knownFilesType, + boolean readOnly, String importFileName) { + this.hashSetName = hashSetName; this.version = version; this.orgId = orgId; @@ -177,47 +178,53 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P this.importSuccess.set(false); this.referenceSetID.set(-1); } - + /** * Get the newly created database - * @return the imported database. May be null if an error occurred or the user canceled + * + * @return the imported database. May be null if an error occurred or + * the user canceled */ - synchronized HashDbManager.CentralRepoHashSet getDatabase(){ + synchronized HashDbManager.CentralRepoHashSet getDatabase() { return newHashDb; } - + /** * Get the number of hashes that have been read in so far + * * @return current hash count */ - long getNumHashesProcessed(){ + long getNumHashesProcessed() { return hashCount.get(); } - + /** * Check if the import was successful or if there was an error. - * @return true if the import process completed without error, false otherwise + * + * @return true if the import process completed without error, false + * otherwise */ - boolean getImportSuccess(){ + boolean getImportSuccess() { return importSuccess.get(); } - + @Override protected Void doInBackground() throws Exception { - + // Create the hash set parser HashSetParser hashSetParser; - if(importFileName.toLowerCase().endsWith(".idx")){ + if (importFileName.toLowerCase().endsWith(".idx")) { hashSetParser = new IdxHashSetParser(importFileName); - } else - if(importFileName.toLowerCase().endsWith(".hash")){ - hashSetParser = new EncaseHashSetParser(importFileName); } else { - // We've gotten here with a format that can't be processed - throw new TskCoreException("Hash set to import is an unknown format : " + importFileName); + if (importFileName.toLowerCase().endsWith(".hash")) { + hashSetParser = new EncaseHashSetParser(importFileName); + } else { + // We've gotten here with a format that can't be processed + throw new TskCoreException("Hash set to import is an unknown format : " + importFileName); + } } - try{ + try { // Conver to the FileKnown enum used by EamGlobalSet TskData.FileKnown knownStatus; if (knownFilesType.equals(HashDbManager.HashDb.KnownFilesType.KNOWN)) { @@ -225,7 +232,7 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } else { knownStatus = TskData.FileKnown.BAD; } - + // Create an empty hashset in the central repository EamDb dbManager = EamDb.getInstance(); referenceSetID.set(dbManager.newReferenceSet(new EamGlobalSet(orgId, hashSetName, version, knownStatus, readOnly))); @@ -237,30 +244,30 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P // Holds the current batch of hashes that need to be written to the central repo Set globalInstances = new HashSet<>(); - while (! hashSetParser.doneReading()) { - if(isCancelled()){ + while (!hashSetParser.doneReading()) { + if (isCancelled()) { return null; } String newHash = hashSetParser.getNextHash(); - if(newHash != null){ + if (newHash != null) { EamGlobalFileInstance eamGlobalFileInstance = new EamGlobalFileInstance( - referenceSetID.get(), - newHash, - knownStatus, + referenceSetID.get(), + newHash, + knownStatus, ""); globalInstances.add(eamGlobalFileInstance); // If we've hit the threshold for writing the hashes, write them // all to the central repo - if(hashCount.incrementAndGet() % HASH_IMPORT_THRESHOLD == 0){ + if (hashCount.incrementAndGet() % HASH_IMPORT_THRESHOLD == 0) { dbManager.bulkInsertReferenceTypeEntries(globalInstances, contentType); globalInstances.clear(); - int progress = (int)(hashCount.get() * 100 / hashSetParser.getExpectedHashCount()); - if(progress < 100){ + int progress = (int) (hashCount.get() * 100 / hashSetParser.getExpectedHashCount()); + if (progress < 100) { this.setProgress(progress); } else { this.setProgress(99); @@ -277,41 +284,41 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P hashSetParser.close(); } } - - private void deleteIncompleteSet(){ - if(referenceSetID.get() >= 0){ - + + private void deleteIncompleteSet() { + if (referenceSetID.get() >= 0) { + // This can be slow on large reference sets Executors.newSingleThreadExecutor().execute(new Runnable() { - @Override + @Override public void run() { - try{ + try { EamDb.getInstance().deleteReferenceSet(referenceSetID.get()); - } catch (EamDbException ex2){ + } catch (EamDbException ex2) { Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error deleting incomplete hash set from central repository", ex2); } } }); } } - + @Override synchronized protected void done() { - - if(isCancelled()){ + + if (isCancelled()) { // If the user hit cancel, delete this incomplete hash set from the central repo deleteIncompleteSet(); return; } - + try { get(); - try{ - newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetName, version, - referenceSetID.get(), + try { + newHashDb = HashDbManager.getInstance().addExistingCentralRepoHashSet(hashSetName, version, + referenceSetID.get(), searchDuringIngest, sendIngestMessages, knownFilesType, readOnly); importSuccess.set(true); - } catch (TskCoreException ex){ + } catch (TskCoreException ex) { Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error adding imported hash set", ex); } } catch (Exception ex) { @@ -319,10 +326,10 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P deleteIncompleteSet(); Logger.getLogger(ImportCentralRepoDbProgressDialog.class.getName()).log(Level.SEVERE, "Error importing hash set", ex); } - } - + } + } - + /** * 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 @@ -416,4 +423,4 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P private javax.swing.JLabel lbProgress; private javax.swing.JProgressBar progressBar; // End of variables declaration//GEN-END:variables -} \ No newline at end of file +} From 5f8b860545e6d8e77e0e04a44ba7d9b9ff825044 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 22 Nov 2017 01:05:08 -0500 Subject: [PATCH 49/90] 'collectMetrics()' method implemented. --- .../autoingest/AutoIngestManager.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index d537c76146..199cb8a8db 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -98,6 +98,9 @@ import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobStartResult; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestModuleError; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.SleuthkitCase; /** * An auto ingest manager is responsible for processing auto ingest jobs defined @@ -2263,7 +2266,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen return; } - collectMetrics(/*DLG:*/); + collectMetrics(caseForJob.getSleuthkitCase(), dataSource); exportFiles(dataSource); } @@ -2548,9 +2551,18 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen /* * DLG: */ - private void collectMetrics(/*DLG:*/) { - + private void collectMetrics(SleuthkitCase caseDb, AutoIngestDataSource dataSource) throws CoordinationServiceException, InterruptedException { + List contentList = dataSource.getContent(); + long dataSourceSize = 0; + for (Content content : contentList) { + // DLG: Why multiply Content objects? + // DLG: What to do if more than one? + dataSourceSize = ((DataSource)content).getContentSize(caseDb); + } AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(currentJob); + nodeData.setDataSourceSize(dataSourceSize); + String manifestNodePath = currentJob.getManifest().getFilePath().toString(); + coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, nodeData.toArray()); } /** From 6f2fae67afeee05cf7f25178282f0d2ac235c93d Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Wed, 22 Nov 2017 08:21:48 -0500 Subject: [PATCH 50/90] Cleanup --- .../hashdatabase/EncaseHashSetParser.java | 1 - .../ImportCentralRepoDbProgressDialog.java | 8 +- .../hashdatabase/KdbHashSetParser.java | 95 +++++++++++-------- 3 files changed, 56 insertions(+), 48 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java index 8ea9bc3c46..4c6a58d9bf 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/EncaseHashSetParser.java @@ -162,7 +162,6 @@ class EncaseHashSetParser implements HashSetParser { throw new TskCoreException("readBuffer called on null inputStream"); } if (length != inputStream.read(buffer)) { - close(); throw new TskCoreException("Ran out of data unexpectedly while parsing Encase file " + filename); } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 3421a06044..a2e9522893 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -220,12 +220,8 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P } else if(importFileName.toLowerCase().endsWith(".kdb")){ hashSetParser = new KdbHashSetParser(importFileName); } else { - if (importFileName.toLowerCase().endsWith(".hash")) { - hashSetParser = new EncaseHashSetParser(importFileName); - } else { - // We've gotten here with a format that can't be processed - throw new TskCoreException("Hash set to import is an unknown format : " + importFileName); - } + // We've gotten here with a format that can't be processed + throw new TskCoreException("Hash set to import is an unknown format : " + importFileName); } try { diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java index 944780936b..5935784087 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/KdbHashSetParser.java @@ -1,13 +1,25 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * Autopsy Forensic Browser + * + * Copyright 2011 - 2017 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.modules.hashdatabase; import java.sql.Connection; import java.sql.DriverManager; -import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; @@ -16,35 +28,35 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.TskCoreException; /** - * + * Parser for Autopsy/TSK-created databases (*.kdb) */ public class KdbHashSetParser implements HashSetParser { + private final String JDBC_DRIVER = "org.sqlite.JDBC"; // NON-NLS private final String JDBC_BASE_URI = "jdbc:sqlite:"; // NON-NLS private final String filename; // Name of the input file (saved for logging) private final long totalHashes; // Estimated number of hashes - private int totalHashesRead = 0; // Number of hashes that have been read + private int totalHashesRead = 0; // Number of hashes that have been read private Connection conn; private Statement statement; private ResultSet resultSet; - - - KdbHashSetParser(String filename) throws TskCoreException{ + + KdbHashSetParser(String filename) throws TskCoreException { this.filename = filename; - + conn = null; statement = null; resultSet = null; - - try{ + + try { // Open the database StringBuilder connectionURL = new StringBuilder(); connectionURL.append(JDBC_BASE_URI); connectionURL.append(filename); Class.forName(JDBC_DRIVER); - conn = DriverManager.getConnection(connectionURL.toString()); - + conn = DriverManager.getConnection(connectionURL.toString()); + // Get the number of hashes in the table statement = conn.createStatement(); resultSet = statement.executeQuery("SELECT count(*) AS count FROM hashes"); @@ -54,94 +66,95 @@ public class KdbHashSetParser implements HashSetParser { close(); throw new TskCoreException("Error getting hash count from database " + filename); } - + // Get the hashes resultSet = statement.executeQuery("SELECT md5 FROM hashes"); - + // At this point, getNextHash can read each hash from the result set - - } catch (ClassNotFoundException | SQLException ex){ + } catch (ClassNotFoundException | SQLException ex) { throw new TskCoreException("Error opening/reading database " + filename, ex); } - + } - + /** * Get the next hash to import - * @return The hash as a string, or null if the end of file was reached without error - * @throws TskCoreException + * + * @return The hash as a string + * @throws TskCoreException */ @Override public String getNextHash() throws TskCoreException { - - try{ - if(resultSet.next()){ + + try { + if (resultSet.next()) { byte[] hashBytes = resultSet.getBytes("md5"); StringBuilder sb = new StringBuilder(); for (byte b : hashBytes) { sb.append(String.format("%02x", b)); } - if(sb.toString().length() != 32){ + if (sb.toString().length() != 32) { throw new TskCoreException("Hash has incorrect length: " + sb.toString()); - } - + } + totalHashesRead++; return sb.toString(); } else { throw new TskCoreException("Could not read expected number of hashes from database " + filename); } - } catch (SQLException ex){ + } catch (SQLException ex) { throw new TskCoreException("Error reading hash from result set for database " + filename, ex); } } - + /** * Check if there are more hashes to read + * * @return true if we've read all expected hash values, false otherwise */ @Override public boolean doneReading() { - return(totalHashesRead >= totalHashes); + return (totalHashesRead >= totalHashes); } - + /** * Get the expected number of hashes in the file. - * This number can be an estimate. + * * @return The expected hash count */ @Override - public long getExpectedHashCount() { + public long getExpectedHashCount() { return totalHashes; } - + /** * Closes the import file */ @Override public final void close() { - if(statement != null){ + if (statement != null) { try { statement.close(); } catch (SQLException ex) { Logger.getLogger(KdbHashSetParser.class.getName()).log(Level.SEVERE, "Error closing prepared statement.", ex); } } - - if(resultSet != null){ + + if (resultSet != null) { try { resultSet.close(); } catch (SQLException ex) { Logger.getLogger(KdbHashSetParser.class.getName()).log(Level.SEVERE, "Error closing result set.", ex); } } - - if(conn != null){ + + if (conn != null) { try { conn.close(); } catch (SQLException ex) { Logger.getLogger(KdbHashSetParser.class.getName()).log(Level.SEVERE, "Error closing connection.", ex); } - } + } } } From 0e21b699930052940d0a6f28b54882c94536091d Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 22 Nov 2017 12:02:46 -0500 Subject: [PATCH 51/90] 3203-add (Notable) to tag context menus --- .../autopsy/actions/AddTagAction.java | 17 ++-- .../autopsy/actions/Bundle.properties | 6 +- .../autopsy/actions/Bundle_ja.properties | 4 +- ...DeleteFileBlackboardArtifactTagAction.java | 58 +++++------ .../actions/DeleteFileContentTagAction.java | 4 +- .../actions/GetTagNameAndCommentDialog.form | 11 +-- .../actions/GetTagNameAndCommentDialog.java | 95 +++++++++---------- .../autopsy/actions/GetTagNameDialog.form | 64 +++++++++++-- .../autopsy/actions/GetTagNameDialog.java | 80 ++++++++++++---- .../casemodule/services/TagNameDialog.form | 2 +- .../casemodule/services/TagNameDialog.java | 2 +- .../casemodule/services/TagsManager.java | 5 + .../imagegallery/actions/AddTagAction.java | 30 +++--- .../imagegallery/actions/DeleteTagAction.java | 58 ++++++----- 14 files changed, 270 insertions(+), 166 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/actions/AddTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/AddTagAction.java index f665aeb7d5..95b68b87d6 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/AddTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/AddTagAction.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2016 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,12 +26,14 @@ import javax.swing.AbstractAction; import javax.swing.JMenu; import javax.swing.JMenuItem; import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; import org.openide.util.actions.Presenter; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; /** * An abstract base class for Actions that allow users to tag SleuthKit data @@ -107,7 +109,8 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup { if (null != tagNamesMap && !tagNamesMap.isEmpty()) { for (Map.Entry entry : tagNamesMap.entrySet()) { String tagDisplayName = entry.getKey(); - JMenuItem tagNameItem = new JMenuItem(tagDisplayName); + String notableString = entry.getValue().getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; + JMenuItem tagNameItem = new JMenuItem(tagDisplayName + notableString); // for the bookmark tag name only, added shortcut label if (tagDisplayName.equals(NbBundle.getMessage(AddTagAction.class, "AddBookmarkTagAction.bookmark.text"))) { tagNameItem.setAccelerator(AddBookmarkTagAction.BOOKMARK_SHORTCUT); @@ -122,7 +125,7 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup { JMenuItem empty = new JMenuItem(NbBundle.getMessage(this.getClass(), "AddTagAction.noTags")); empty.setEnabled(false); quickTagMenu.add(empty); - } + } quickTagMenu.addSeparator(); @@ -155,10 +158,10 @@ abstract class AddTagAction extends AbstractAction implements Presenter.Popup { /** * Method to add to the action listener for each menu item. Allows a tag * display name to be added to the menu with an action listener without - * having to instantiate a TagName object for it. - * When the method is called, the TagName object is created here if it - * doesn't already exist. - * + * having to instantiate a TagName object for it. When the method is + * called, the TagName object is created here if it doesn't already + * exist. + * * @param tagDisplayName display name for the tag name * @param tagName TagName object associated with the tag name, * may be null diff --git a/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties b/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties index 28d4e4006a..01d0d21b47 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties @@ -4,7 +4,7 @@ GetTagNameDialog.okButton.text=OK GetTagNameDialog.preexistingLabel.text=Pre-existing Tag Names: GetTagNameDialog.newTagPanel.border.title=New Tag GetTagNameDialog.tagNameLabel.text=Tag Name: -GetTagNameAndCommentDialog.newTagButton.text=New Tag Name +GetTagNameAndCommentDialog.newTagButton.text=New Tag GetTagNameAndCommentDialog.okButton.text=OK GetTagNameAndCommentDialog.commentText.toolTipText=Enter an optional tag comment or leave blank GetTagNameAndCommentDialog.commentText.text= @@ -12,7 +12,6 @@ GetTagNameAndCommentDialog.commentLabel.text=Comment: # To change this template, choose Tools | Templates # and open the template in the editor. GetTagNameAndCommentDialog.cancelButton.text=Cancel -GetTagNameAndCommentDialog.tagCombo.toolTipText=Select tag to use GetTagNameAndCommentDialog.tagLabel.text=Tag: AddTagAction.bookmarkFile=Bookmark file AddTagAction.quickTag=Quick Tag @@ -45,3 +44,6 @@ ShowIngestProgressSnapshotAction.actionName.text=Get Ingest Progress Snapshot OpenPythonModulesFolderAction.actionName.text=Python Plugins OpenPythonModulesFolderAction.errorMsg.folderNotFound=Python plugins folder not found: {0} CTL_OpenPythonModulesFolderAction=Python Plugins +GetTagNameDialog.descriptionLabel.text=Description: +GetTagNameDialog.notableCheckbox.text=Tag indicates item is notable. +GetTagNameAndCommentDialog.tagCombo.toolTipText=Select tag to use diff --git a/Core/src/org/sleuthkit/autopsy/actions/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/actions/Bundle_ja.properties index 195d12c695..d6f865ecf0 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/actions/Bundle_ja.properties @@ -8,7 +8,6 @@ GetTagNameAndCommentDialog.okButton.text=OK GetTagNameAndCommentDialog.commentText.toolTipText=\u30bf\u30b0\u306e\u30aa\u30d7\u30b7\u30e7\u30ca\u30eb\u306e\u30b3\u30e1\u30f3\u30c8\u3092\u5165\u529b\u307e\u305f\u306f\u7a7a\u6b04\u306b\u3057\u3066\u304f\u3060\u3055\u3044 GetTagNameAndCommentDialog.commentLabel.text=\u30b3\u30e1\u30f3\u30c8\uff1a GetTagNameAndCommentDialog.cancelButton.text=\u30ad\u30e3\u30f3\u30bb\u30eb -GetTagNameAndCommentDialog.tagCombo.toolTipText=\u4f7f\u7528\u3059\u308b\u30bf\u30b0\u3092\u9078\u629e GetTagNameAndCommentDialog.tagLabel.text=\u30bf\u30b0\uff1a AddBlackboardArtifactTagAction.singularTagResult=\u7d50\u679c\u306b\u30bf\u30b0\u3092\u8ffd\u52a0 AddBlackboardArtifactTagAction.pluralTagResult=\u7d50\u679c\u306b\u30bf\u30b0\u3092\u8ffd\u52a0 @@ -48,4 +47,5 @@ CTL_OpenOutputFolder=\u30a2\u30a6\u30c8\u30d7\u30c3\u30c8\u30d5\u30a9\u30eb\u30c OpenOutputFolder.error1=\u6b21\u306e\u30a2\u30a6\u30c8\u30d7\u30c3\u30c8\u30d5\u30a9\u30eb\u30c0\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\uff1a{0} OpenOutputFolder.noCaseOpen=\u30aa\u30fc\u30d7\u30f3\u30b1\u30fc\u30b9\u304c\u306a\u3044\u306e\u3067\u3001\u4f5c\u696d\u4e2d\u306e\u30a2\u30a6\u30c8\u30d7\u30c3\u30c8\u30d5\u30a9\u30eb\u30c0\u304c\u3042\u308a\u307e\u305b\u3093\u3002 GetTagNameDialog.illegalChars.msg=\u4f7f\u7528\u3067\u304d\u306a\u3044\u6587\u5b57\u304c\u542b\u307e\u308c\u3066\u3044\u307e\u3059\u3002\n\u6b21\u306e\u6587\u5b57\u306f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\uff1a\\ \: * ? " < > | -OpenOutputFolder.CouldNotOpenOutputFolder=\u30a2\u30a6\u30c8\u30d7\u30c3\u30c8\u30d5\u30a9\u30eb\u30c0\u304c\u304c\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f \ No newline at end of file +OpenOutputFolder.CouldNotOpenOutputFolder=\u30a2\u30a6\u30c8\u30d7\u30c3\u30c8\u30d5\u30a9\u30eb\u30c0\u304c\u304c\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f +GetTagNameAndCommentDialog.tagCombo.toolTipText=\u4f7f\u7528\u3059\u308b\u30bf\u30b0\u3092\u9078\u629e diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java index d9fd5d364f..86696b0c63 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileBlackboardArtifactTagAction.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2017 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. @@ -43,6 +43,7 @@ import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; /** * Instances of this Action allow users to delete tags applied to blackboard @@ -52,7 +53,7 @@ import org.sleuthkit.datamodel.TskCoreException; "DeleteFileBlackboardArtifactTagAction.deleteTag=Remove Result Tag" }) public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implements Presenter.Popup { - + private static final Logger LOGGER = Logger.getLogger(DeleteFileBlackboardArtifactTagAction.class.getName()); private static final long serialVersionUID = 1L; @@ -89,27 +90,27 @@ public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implem } @NbBundle.Messages({"# {0} - artifactID", - "DeleteFileBlackboardArtifactTagAction.deleteTag.alert=Unable to untag artifact {0}."}) + "DeleteFileBlackboardArtifactTagAction.deleteTag.alert=Unable to untag artifact {0}."}) protected void deleteTag(TagName tagName, BlackboardArtifactTag artifactTag, long artifactId) { new SwingWorker() { @Override protected Void doInBackground() throws Exception { TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); - + // Pull the from the global context to avoid unnecessary calls // to the database. - final Collection selectedFilesList = - new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + final Collection selectedFilesList + = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); AbstractFile file = selectedFilesList.iterator().next(); - + try { LOGGER.log(Level.INFO, "Removing tag {0} from {1}", new Object[]{tagName.getDisplayName(), file.getName()}); //NON-NLS tagsManager.deleteBlackboardArtifactTag(artifactTag); } catch (TskCoreException tskCoreException) { LOGGER.log(Level.SEVERE, "Error untagging artifact", tskCoreException); //NON-NLS - Platform.runLater(() -> - new Alert(Alert.AlertType.ERROR, Bundle.DeleteFileBlackboardArtifactTagAction_deleteTag_alert(artifactId)).show() + Platform.runLater(() + -> new Alert(Alert.AlertType.ERROR, Bundle.DeleteFileBlackboardArtifactTagAction_deleteTag_alert(artifactId)).show() ); } return null; @@ -133,21 +134,21 @@ public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implem * comment. */ @NbBundle.Messages({"# {0} - artifactID", - "DeleteFileBlackboardArtifactTagAction.deleteTags.alert=Unable to untag artifact {0}."}) + "DeleteFileBlackboardArtifactTagAction.deleteTags.alert=Unable to untag artifact {0}."}) private class TagMenu extends JMenu { private static final long serialVersionUID = 1L; TagMenu() { super(getActionDisplayName()); - - final Collection selectedBlackboardArtifactsList = - new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class)); - - if(!selectedBlackboardArtifactsList.isEmpty()) { - BlackboardArtifact artifact = - selectedBlackboardArtifactsList.iterator().next(); - + + final Collection selectedBlackboardArtifactsList + = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class)); + + if (!selectedBlackboardArtifactsList.isEmpty()) { + BlackboardArtifact artifact + = selectedBlackboardArtifactsList.iterator().next(); + // Get the current set of tag names. TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); @@ -163,17 +164,18 @@ public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implem // a tag with the associated tag name. if (null != tagNamesMap && !tagNamesMap.isEmpty()) { try { - List existingTagsList = - Case.getCurrentCase().getServices().getTagsManager() - .getBlackboardArtifactTagsByArtifact(artifact); + List existingTagsList + = Case.getCurrentCase().getServices().getTagsManager() + .getBlackboardArtifactTagsByArtifact(artifact); for (Map.Entry entry : tagNamesMap.entrySet()) { String tagDisplayName = entry.getKey(); TagName tagName = entry.getValue(); - for(BlackboardArtifactTag artifactTag : existingTagsList) { - if(tagDisplayName.equals(artifactTag.getName().getDisplayName())) { - JMenuItem tagNameItem = new JMenuItem(tagDisplayName); + for (BlackboardArtifactTag artifactTag : existingTagsList) { + if (tagDisplayName.equals(artifactTag.getName().getDisplayName())) { + String notableString = tagName.getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; + JMenuItem tagNameItem = new JMenuItem(tagDisplayName + notableString); tagNameItem.addActionListener((ActionEvent e) -> { deleteTag(tagName, artifactTag, artifact.getArtifactID()); }); @@ -187,7 +189,7 @@ public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implem } } - if(getItemCount() == 0) { + if (getItemCount() == 0) { setEnabled(false); } } diff --git a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java index e49e0f9170..5c8d4abb74 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/DeleteFileContentTagAction.java @@ -42,6 +42,7 @@ import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; /** * Instances of this Action allow users to delete tags applied to content. @@ -169,7 +170,8 @@ public class DeleteFileContentTagAction extends AbstractAction implements Presen TagName tagName = entry.getValue(); for(ContentTag contentTag : existingTagsList) { if(tagDisplayName.equals(contentTag.getName().getDisplayName())) { - JMenuItem tagNameItem = new JMenuItem(tagDisplayName); + String notableString = tagName.getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; + JMenuItem tagNameItem = new JMenuItem(tagDisplayName + notableString); tagNameItem.addActionListener((ActionEvent e) -> { deleteTag(tagName, contentTag, file.getId()); }); diff --git a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.form b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.form index 17a9738dbd..57c43e964b 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.form +++ b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.form @@ -28,7 +28,7 @@ - + @@ -39,11 +39,10 @@ - + - + - @@ -108,8 +107,8 @@ - - + + diff --git a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java index 647d851341..e01a887949 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java +++ b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameAndCommentDialog.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * - * Copyright 2011-2016 Basis Technology Corp. + * + * Copyright 2011-2017 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. @@ -18,17 +18,20 @@ */ package org.sleuthkit.autopsy.actions; +import java.awt.Component; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; -import java.util.Map; -import java.util.TreeMap; import java.util.logging.Level; +import java.util.HashSet; +import java.util.Set; import javax.swing.AbstractAction; import javax.swing.ActionMap; +import javax.swing.DefaultListCellRenderer; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JDialog; +import javax.swing.JList; import javax.swing.KeyStroke; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; @@ -37,15 +40,14 @@ import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; public class GetTagNameAndCommentDialog extends JDialog { private static final long serialVersionUID = 1L; - private static final String NO_TAG_NAMES_MESSAGE = NbBundle.getMessage(GetTagNameAndCommentDialog.class, - "GetTagNameAndCommentDialog.noTags"); - private final Map tagNamesMap = new TreeMap<>(); + private final Set tagNamesSet = new HashSet<>(); private TagNameAndComment tagNameAndComment = null; - + public static class TagNameAndComment { private final TagName tagName; @@ -68,7 +70,7 @@ public class GetTagNameAndCommentDialog extends JDialog { /** * Show the Tag Name and Comment Dialog and return the TagNameAndContent * chosen by the user. The dialog will be centered with the main autopsy - * window as its owner. + * window as its owner. * * @return a TagNameAndComment instance containing the TagName selected by * the user and the entered comment, or null if the user canceled @@ -102,21 +104,34 @@ public class GetTagNameAndCommentDialog extends JDialog { ModalityType.APPLICATION_MODAL); } + private void display() { initComponents(); - + tagCombo.setRenderer(new DefaultListCellRenderer() { + private static final long serialVersionUID = 1L; + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + String status = ((TagName) value).getKnownStatus() == TskData.FileKnown.BAD ?TagsManager.getNotableTagLabel() : ""; + String newValue = ((TagName) value).getDisplayName() + status; + return super.getListCellRendererComponent(list, newValue, index, isSelected, cellHasFocus); + } + }); // Set up the dialog to close when Esc is pressed. String cancelName = NbBundle.getMessage(this.getClass(), "GetTagNameAndCommentDialog.cancelName"); InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), cancelName); ActionMap actionMap = getRootPane().getActionMap(); + actionMap.put(cancelName, new AbstractAction() { private static final long serialVersionUID = 1L; + @Override public void actionPerformed(ActionEvent e) { dispose(); } - }); + } + ); // Populate the combo box with the available tag names and save the // tag name DTOs to be enable to return the one the user selects. @@ -124,23 +139,22 @@ public class GetTagNameAndCommentDialog extends JDialog { // not exist in the database). TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); try { - tagNamesMap.putAll(tagsManager.getDisplayNamesToTagNamesMap()); + tagNamesSet.addAll(tagsManager.getAllTagNames()); + } catch (TskCoreException ex) { - Logger.getLogger(GetTagNameAndCommentDialog.class.getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS + Logger.getLogger(GetTagNameAndCommentDialog.class + .getName()).log(Level.SEVERE, "Failed to get tag names", ex); //NON-NLS } - if (null != tagNamesMap && tagNamesMap.isEmpty()) { - tagCombo.addItem(NO_TAG_NAMES_MESSAGE); - } else { - for (String tagDisplayName : tagNamesMap.keySet()) { - tagCombo.addItem(tagDisplayName); - } + for (TagName tag : tagNamesSet) { + + tagCombo.addItem(tag); } // Center and show the dialog box. this.setLocationRelativeTo(this.getOwner()); - setVisible(true); + setVisible(true); } - + /** * 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 @@ -152,7 +166,7 @@ public class GetTagNameAndCommentDialog extends JDialog { okButton = new javax.swing.JButton(); cancelButton = new javax.swing.JButton(); - tagCombo = new javax.swing.JComboBox(); + tagCombo = new javax.swing.JComboBox(); tagLabel = new javax.swing.JLabel(); commentLabel = new javax.swing.JLabel(); commentText = new javax.swing.JTextField(); @@ -203,7 +217,7 @@ public class GetTagNameAndCommentDialog extends JDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addComponent(newTagButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 48, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 165, Short.MAX_VALUE) .addComponent(okButton, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(cancelButton)) @@ -212,10 +226,9 @@ public class GetTagNameAndCommentDialog extends JDialog { .addComponent(commentLabel) .addComponent(tagLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(commentText) - .addComponent(tagCombo, 0, 214, Short.MAX_VALUE)) - .addGap(0, 0, Short.MAX_VALUE))) + .addComponent(tagCombo, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) .addContainerGap()) ); @@ -246,21 +259,7 @@ public class GetTagNameAndCommentDialog extends JDialog { }// //GEN-END:initComponents private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed - String tagDisplayName = (String) tagCombo.getSelectedItem(); - TagName tagNameFromCombo = tagNamesMap.get(tagDisplayName); - if (tagNameFromCombo == null) { - try { - tagNameFromCombo = Case.getCurrentCase().getServices().getTagsManager().addTagName(tagDisplayName); - } catch (TagsManager.TagNameAlreadyExistsException ex) { - try { - tagNameFromCombo = Case.getCurrentCase().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(tagDisplayName); - } catch (TskCoreException ex1) { - Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, tagDisplayName + " already exists in database but an error occurred in retrieving it.", ex1); //NON-NLS - } - } catch (TskCoreException ex) { - Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, "Error adding " + tagDisplayName + " tag name", ex); //NON-NLS - } - } + TagName tagNameFromCombo = (TagName) tagCombo.getSelectedItem(); tagNameAndComment = new TagNameAndComment(tagNameFromCombo, commentText.getText()); dispose(); }//GEN-LAST:event_okButtonActionPerformed @@ -278,9 +277,9 @@ public class GetTagNameAndCommentDialog extends JDialog { private void newTagButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newTagButtonActionPerformed TagName newTagName = GetTagNameDialog.doDialog(this); if (newTagName != null) { - tagNamesMap.put(newTagName.getDisplayName(), newTagName); - tagCombo.addItem(newTagName.getDisplayName()); - tagCombo.setSelectedItem(newTagName.getDisplayName()); + tagNamesSet.add(newTagName); + tagCombo.addItem(newTagName); + tagCombo.setSelectedItem(newTagName); } }//GEN-LAST:event_newTagButtonActionPerformed @@ -290,7 +289,7 @@ public class GetTagNameAndCommentDialog extends JDialog { private javax.swing.JTextField commentText; private javax.swing.JButton newTagButton; private javax.swing.JButton okButton; - private javax.swing.JComboBox tagCombo; + private javax.swing.JComboBox tagCombo; private javax.swing.JLabel tagLabel; // End of variables declaration//GEN-END:variables } diff --git a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.form b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.form index a281ea606e..bf17a398a7 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.form +++ b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.form @@ -142,11 +142,20 @@ - + - - - + + + + + + + + + + + + @@ -154,12 +163,17 @@ + + - - - - - + + + + + + + + @@ -182,6 +196,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java index 4e5720a0fc..1619c95fed 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2011-2016 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. @@ -42,6 +42,7 @@ import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; public class GetTagNameDialog extends JDialog { @@ -79,7 +80,7 @@ public class GetTagNameDialog extends JDialog { } private GetTagNameDialog(Window owner) { - super(owner, + super(owner, NbBundle.getMessage(GetTagNameDialog.class, "GetTagNameDialog.createTag"), ModalityType.APPLICATION_MODAL); } @@ -95,7 +96,7 @@ public class GetTagNameDialog extends JDialog { ActionMap actionMap = getRootPane().getActionMap(); actionMap.put(cancelName, new AbstractAction() { private static final long serialVersionUID = 1L; - + @Override public void actionPerformed(ActionEvent e) { cancelButtonActionPerformed(e); @@ -120,9 +121,9 @@ public class GetTagNameDialog extends JDialog { // Center and show the dialog box. this.setLocationRelativeTo(this.getOwner()); - setVisible(true); + setVisible(true); } - + private class TagsTableModel extends AbstractTableModel { private static final long serialVersionUID = 1L; @@ -172,6 +173,10 @@ public class GetTagNameDialog extends JDialog { newTagPanel = new javax.swing.JPanel(); tagNameLabel = new javax.swing.JLabel(); tagNameField = new javax.swing.JTextField(); + descriptionLabel = new javax.swing.JLabel(); + descriptionScrollPane = new javax.swing.JScrollPane(); + descriptionTextArea = new javax.swing.JTextArea(); + notableCheckbox = new javax.swing.JCheckBox(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); addKeyListener(new java.awt.event.KeyAdapter() { @@ -223,25 +228,46 @@ public class GetTagNameDialog extends JDialog { } }); + org.openide.awt.Mnemonics.setLocalizedText(descriptionLabel, org.openide.util.NbBundle.getMessage(GetTagNameDialog.class, "GetTagNameDialog.descriptionLabel.text")); // NOI18N + + descriptionTextArea.setColumns(20); + descriptionTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N + descriptionTextArea.setRows(3); + descriptionScrollPane.setViewportView(descriptionTextArea); + + org.openide.awt.Mnemonics.setLocalizedText(notableCheckbox, org.openide.util.NbBundle.getMessage(GetTagNameDialog.class, "GetTagNameDialog.notableCheckbox.text")); // NOI18N + javax.swing.GroupLayout newTagPanelLayout = new javax.swing.GroupLayout(newTagPanel); newTagPanel.setLayout(newTagPanelLayout); newTagPanelLayout.setHorizontalGroup( newTagPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(newTagPanelLayout.createSequentialGroup() .addContainerGap() - .addComponent(tagNameLabel) - .addGap(36, 36, 36) - .addComponent(tagNameField, javax.swing.GroupLayout.DEFAULT_SIZE, 235, Short.MAX_VALUE) + .addGroup(newTagPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(descriptionScrollPane, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(tagNameField, javax.swing.GroupLayout.DEFAULT_SIZE, 323, Short.MAX_VALUE) + .addGroup(newTagPanelLayout.createSequentialGroup() + .addGroup(newTagPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(notableCheckbox) + .addComponent(descriptionLabel) + .addComponent(tagNameLabel)) + .addGap(0, 0, Short.MAX_VALUE))) .addContainerGap()) ); newTagPanelLayout.setVerticalGroup( newTagPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(newTagPanelLayout.createSequentialGroup() - .addContainerGap() - .addGroup(newTagPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(tagNameLabel) - .addComponent(tagNameField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addContainerGap(164, Short.MAX_VALUE)) + .addGap(6, 6, 6) + .addComponent(tagNameLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(tagNameField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(descriptionLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(descriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 57, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(notableCheckbox) + .addContainerGap(31, Short.MAX_VALUE)) ); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); @@ -288,8 +314,12 @@ public class GetTagNameDialog extends JDialog { dispose(); }//GEN-LAST:event_cancelButtonActionPerformed + @NbBundle.Messages({"GetTagNameDialog.tagNameAlreadyExists.message=Tag name must be unique. A tag with this name already exists.", + "GetTagNameDialog.tagNameAlreadyExists.title=Duplicate Tag Name"}) private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed String tagDisplayName = tagNameField.getText(); + String userTagDescription = descriptionTextArea.getText(); + TskData.FileKnown status = notableCheckbox.isSelected() ? TskData.FileKnown.BAD : TskData.FileKnown.UNKNOWN; if (tagDisplayName.isEmpty()) { JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), @@ -301,11 +331,18 @@ public class GetTagNameDialog extends JDialog { NbBundle.getMessage(this.getClass(), "GetTagNameDialog.illegalChars.msg"), NbBundle.getMessage(this.getClass(), "GetTagNameDialog.illegalCharsErr"), JOptionPane.ERROR_MESSAGE); + } else if (userTagDescription.contains(",") + || userTagDescription.contains(";")) { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), "GetTagNameDialog.illegalChars.msg"), + NbBundle.getMessage(this.getClass(), "GetTagNameDialog.illegalCharsErr"), + JOptionPane.ERROR_MESSAGE); } else { tagName = tagNamesMap.get(tagDisplayName); + if (tagName == null) { try { - tagName = Case.getCurrentCase().getServices().getTagsManager().addTagName(tagDisplayName); + tagName = Case.getCurrentCase().getServices().getTagsManager().addTagName(tagDisplayName, userTagDescription, TagName.HTML_COLOR.NONE, status); dispose(); } catch (TskCoreException ex) { Logger.getLogger(AddTagAction.class.getName()).log(Level.SEVERE, "Error adding " + tagDisplayName + " tag name", ex); //NON-NLS @@ -331,7 +368,10 @@ public class GetTagNameDialog extends JDialog { } } } else { - dispose(); + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), "GetTagNameDialog.tagNameAlreadyExists.message"), + NbBundle.getMessage(this.getClass(), "GetTagNameDialog.tagNameAlreadyExists.title"), + JOptionPane.INFORMATION_MESSAGE); } } }//GEN-LAST:event_okButtonActionPerformed @@ -350,8 +390,12 @@ public class GetTagNameDialog extends JDialog { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton cancelButton; + private javax.swing.JLabel descriptionLabel; + private javax.swing.JScrollPane descriptionScrollPane; + private javax.swing.JTextArea descriptionTextArea; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JPanel newTagPanel; + private javax.swing.JCheckBox notableCheckbox; private javax.swing.JButton okButton; private javax.swing.JLabel preexistingLabel; private javax.swing.JTextField tagNameField; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.form b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.form index e8162e6b3b..a88e25eb55 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.form @@ -117,7 +117,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java index 9b8584d293..0d0f07aa89 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java @@ -231,7 +231,7 @@ final class TagNameDialog extends javax.swing.JDialog { descriptionTextArea.setColumns(20); descriptionTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N - descriptionTextArea.setRows(5); + descriptionTextArea.setRows(3); descriptionScrollPane.setViewportView(descriptionTextArea); org.openide.awt.Mnemonics.setLocalizedText(descriptionLabel, org.openide.util.NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.descriptionLabel.text")); // NOI18N diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index e67f8a3484..b28769a50a 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -27,6 +27,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; +import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -69,6 +70,10 @@ public class TagsManager implements Closeable { || tagDisplayName.contains(";")); } + @NbBundle.Messages({"TagsManager.notableTagEnding.text= (Notable)"}) + public static String getNotableTagLabel(){ + return Bundle.TagsManager_notableTagEnding_text(); + } /** * Gets the set of display names of the currently available tag types. This diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddTagAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddTagAction.java index e116ff171c..cd40efdb55 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddTagAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/AddTagAction.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * - * Copyright 2013-16 Basis Technology Corp. + * + * Copyright 2013-2017 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. @@ -36,10 +36,12 @@ import javax.swing.SwingWorker; import org.controlsfx.control.action.Action; import org.controlsfx.control.action.ActionUtils; import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.actions.GetTagNameAndCommentDialog; import org.sleuthkit.autopsy.actions.GetTagNameDialog; +import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.ImageGalleryTopComponent; @@ -48,6 +50,7 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableTagsManager; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TagName; +import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskCoreException; /** @@ -67,7 +70,8 @@ public class AddTagAction extends Action { this.selectedFileIDs = selectedFileIDs; this.tagName = tagName; setGraphic(controller.getTagsManager().getGraphic(tagName)); - setText(tagName.getDisplayName()); + String notableString = tagName.getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; + setText(tagName.getDisplayName() + notableString); setEventHandler(actionEvent -> addTagWithComment("")); } @@ -78,7 +82,7 @@ public class AddTagAction extends Action { private void addTagWithComment(String comment) { addTagsToFiles(tagName, comment, selectedFileIDs); } - + @NbBundle.Messages({"# {0} - fileID", "AddDrawableTagAction.addTagsToFiles.alert=Unable to tag file {0}."}) private void addTagsToFiles(TagName tagName, String comment, Set selectedFiles) { @@ -108,8 +112,8 @@ public class AddTagAction extends Action { } catch (TskCoreException tskCoreException) { LOGGER.log(Level.SEVERE, "Error tagging file", tskCoreException); //NON-NLS - Platform.runLater(() -> - new Alert(Alert.AlertType.ERROR, Bundle.AddDrawableTagAction_addTagsToFiles_alert(fileID)).show() + Platform.runLater(() + -> new Alert(Alert.AlertType.ERROR, Bundle.AddDrawableTagAction_addTagsToFiles_alert(fileID)).show() ); break; } @@ -172,8 +176,8 @@ public class AddTagAction extends Action { * or select a tag name and adds a tag with the resulting name. */ MenuItem newTagMenuItem = new MenuItem(Bundle.AddTagAction_menuItem_newTag()); - newTagMenuItem.setOnAction(actionEvent -> - SwingUtilities.invokeLater(() -> { + newTagMenuItem.setOnAction(actionEvent + -> SwingUtilities.invokeLater(() -> { TagName tagName = GetTagNameDialog.doDialog(getIGWindow()); if (tagName != null) { new AddTagAction(controller, tagName, selectedFileIDs).handle(actionEvent); @@ -188,8 +192,8 @@ public class AddTagAction extends Action { * name. */ MenuItem tagAndCommentItem = new MenuItem(Bundle.AddTagAction_menuItem_tagAndComment()); - tagAndCommentItem.setOnAction(actionEvent -> - SwingUtilities.invokeLater(() -> { + tagAndCommentItem.setOnAction(actionEvent + -> SwingUtilities.invokeLater(() -> { GetTagNameAndCommentDialog.TagNameAndComment tagNameAndComment = GetTagNameAndCommentDialog.doDialog(getIGWindow()); if (null != tagNameAndComment) { new AddTagAction(controller, tagNameAndComment.getTagName(), selectedFileIDs).addTagWithComment(tagNameAndComment.getComment()); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteTagAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteTagAction.java index 53a033a2c9..a21d163fdc 100755 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteTagAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/DeleteTagAction.java @@ -1,15 +1,15 @@ /* * Autopsy Forensic Browser - * + * * Copyright 2017 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. @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.imagegallery.actions; -import java.awt.Window; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; @@ -30,24 +29,22 @@ import javafx.scene.control.Alert; import javafx.scene.control.Menu; import javafx.scene.control.MenuItem; import javafx.scene.image.ImageView; -import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import org.controlsfx.control.action.Action; import org.controlsfx.control.action.ActionUtils; import org.openide.util.NbBundle; import org.openide.util.Utilities; -import org.openide.windows.TopComponent; -import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.imagegallery.ImageGalleryTopComponent; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableTagsManager; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; /** * Instances of this Action allow users to remove tags from content. @@ -68,7 +65,8 @@ public class DeleteTagAction extends Action { this.tagName = tagName; this.contentTag = contentTag; setGraphic(controller.getTagsManager().getGraphic(tagName)); - setText(tagName.getDisplayName()); + String notableString = tagName.getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; + setText(tagName.getDisplayName() + notableString); setEventHandler(actionEvent -> deleteTag()); } @@ -84,20 +82,20 @@ public class DeleteTagAction extends Action { @Override protected Void doInBackground() throws Exception { DrawableTagsManager tagsManager = controller.getTagsManager(); - + // Pull the from the global context to avoid unnecessary calls // to the database. - final Collection selectedFilesList = - new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + final Collection selectedFilesList + = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); AbstractFile file = selectedFilesList.iterator().next(); - + try { LOGGER.log(Level.INFO, "Removing tag {0} from {1}", new Object[]{tagName.getDisplayName(), file.getName()}); //NON-NLS tagsManager.deleteContentTag(contentTag); } catch (TskCoreException tskCoreException) { LOGGER.log(Level.SEVERE, "Error untagging file", tskCoreException); //NON-NLS - Platform.runLater(() -> - new Alert(Alert.AlertType.ERROR, Bundle.DeleteDrawableTagAction_deleteTag_alert(fileId)).show() + Platform.runLater(() + -> new Alert(Alert.AlertType.ERROR, Bundle.DeleteDrawableTagAction_deleteTag_alert(fileId)).show() ); } return null; @@ -121,25 +119,25 @@ public class DeleteTagAction extends Action { TagMenu(ImageGalleryController controller) { setGraphic(new ImageView(DrawableAttribute.TAGS.getIcon())); setText(Bundle.DeleteDrawableTagAction_displayName()); - + // For this menu, we shouldn't have more than one file selected. // Therefore, we will simply grab the first file and work with that. - final Collection selectedFilesList = - new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); + final Collection selectedFilesList + = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); AbstractFile file = selectedFilesList.iterator().next(); - - try { - List existingTagsList = - Case.getCurrentCase().getServices().getTagsManager() - .getContentTagsByContent(file); - Collection tagNamesList = - controller.getTagsManager().getNonCategoryTagNames(); + try { + List existingTagsList + = Case.getCurrentCase().getServices().getTagsManager() + .getContentTagsByContent(file); + + Collection tagNamesList + = controller.getTagsManager().getNonCategoryTagNames(); Iterator tagNameIterator = tagNamesList.iterator(); - for(int i=0; tagNameIterator.hasNext(); i++) { + for (int i = 0; tagNameIterator.hasNext(); i++) { TagName tagName = tagNameIterator.next(); - for(ContentTag contentTag : existingTagsList) { - if(contentTag.getName().getId() == tagName.getId()) { + for (ContentTag contentTag : existingTagsList) { + if (contentTag.getName().getId() == tagName.getId()) { DeleteTagAction deleteDrawableTagAction = new DeleteTagAction(controller, tagName, contentTag, file.getId()); MenuItem tagNameItem = ActionUtils.createMenuItem(deleteDrawableTagAction); getItems().add(tagNameItem); @@ -151,7 +149,7 @@ public class DeleteTagAction extends Action { .log(Level.SEVERE, "Error retrieving tags for TagMenu", ex); //NON-NLS } - if(getItems().isEmpty()) { + if (getItems().isEmpty()) { setDisable(true); } } From 9d31a784baf11aa781ab9b7bb464f6170c9f8205 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 22 Nov 2017 12:13:23 -0500 Subject: [PATCH 52/90] 3203 add check for comma or semicolon in tag description --- .../autopsy/actions/GetTagNameDialog.java | 8 ++-- .../casemodule/services/TagNameDialog.java | 47 ++++++++++++------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java index 1619c95fed..ec282dfa1f 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java @@ -315,7 +315,9 @@ public class GetTagNameDialog extends JDialog { }//GEN-LAST:event_cancelButtonActionPerformed @NbBundle.Messages({"GetTagNameDialog.tagNameAlreadyExists.message=Tag name must be unique. A tag with this name already exists.", - "GetTagNameDialog.tagNameAlreadyExists.title=Duplicate Tag Name"}) + "GetTagNameDialog.tagNameAlreadyExists.title=Duplicate Tag Name", + "GetTagNameDialog.tagDescriptionIllegalCharacters.message=Tag descriptions may not contain commas (,) or semicolons (;)", + "GetTagNameDialog.tagDescriptionIllegalCharacters.title=Invalid character in tag description"}) private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed String tagDisplayName = tagNameField.getText(); String userTagDescription = descriptionTextArea.getText(); @@ -334,8 +336,8 @@ public class GetTagNameDialog extends JDialog { } else if (userTagDescription.contains(",") || userTagDescription.contains(";")) { JOptionPane.showMessageDialog(null, - NbBundle.getMessage(this.getClass(), "GetTagNameDialog.illegalChars.msg"), - NbBundle.getMessage(this.getClass(), "GetTagNameDialog.illegalCharsErr"), + NbBundle.getMessage(this.getClass(), "GetTagNameDialog.tagDescriptionIllegalCharacters.message"), + NbBundle.getMessage(this.getClass(), "GetTagNameDialog.tagDescriptionIllegalCharacters.title"), JOptionPane.ERROR_MESSAGE); } else { tagName = tagNamesMap.get(tagDisplayName); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java index 0d0f07aa89..5829495be1 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java @@ -1,20 +1,20 @@ /* -* Autopsy Forensic Browser -* -* Copyright 2011-2017 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. + * Autopsy Forensic Browser + * + * Copyright 2011-2017 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.services; @@ -60,7 +60,7 @@ final class TagNameDialog extends javax.swing.JDialog { initComponents(); tagNameTextField.setText(tagNameToEdit.getDisplayName()); descriptionTextArea.setText(tagNameToEdit.getDescription()); - notableCheckbox.setSelected(tagNameToEdit.getKnownStatus()== TskData.FileKnown.BAD); + notableCheckbox.setSelected(tagNameToEdit.getKnownStatus() == TskData.FileKnown.BAD); tagNameTextField.setEnabled(false); this.display(); } @@ -127,24 +127,35 @@ final class TagNameDialog extends javax.swing.JDialog { * * @param okPressed whether the OK button was pressed. */ + @Messages({"TagNameDialog.JOptionPane.tagDescriptionIllegalCharacters.message=Tag descriptions may not contain commas (,) or semicolons (;)", + "TagNameDialog.JOptionPane.tagDescriptionIllegalCharacters.title=Invalid character in tag description"}) private void doButtonAction(boolean okPressed) { if (okPressed) { String newTagDisplayName = tagNameTextField.getText().trim(); + String descriptionText = descriptionTextArea.getText(); if (newTagDisplayName.isEmpty()) { JOptionPane.showMessageDialog(null, NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameEmpty.message"), NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameEmpty.title"), JOptionPane.ERROR_MESSAGE); return; - } + } //if a tag name contains illegal characters and is not the name of one of the standard tags if (TagsManager.containsIllegalCharacters(newTagDisplayName) && !TagNameDefinition.getStandardTagNames().contains(newTagDisplayName)) { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagDescriptionIllegalCharacters.message"), + NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagDescriptionIllegalCharacters.title"), + JOptionPane.ERROR_MESSAGE); + return; + } else if (descriptionText.contains(",") + || descriptionText.contains(";")) { JOptionPane.showMessageDialog(null, NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameIllegalCharacters.message"), NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameIllegalCharacters.title"), JOptionPane.ERROR_MESSAGE); return; } + userTagDescription = descriptionTextArea.getText(); userTagDisplayName = newTagDisplayName; userTagIsNotable = notableCheckbox.isSelected(); From 4ec52d8a8476cce7ba5ab85106e856f2d7eadb81 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 22 Nov 2017 12:19:00 -0500 Subject: [PATCH 53/90] 3203 fix error message for invalid description --- .../sleuthkit/autopsy/casemodule/services/TagNameDialog.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java index 5829495be1..e8f2275db4 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java @@ -150,8 +150,8 @@ final class TagNameDialog extends javax.swing.JDialog { } else if (descriptionText.contains(",") || descriptionText.contains(";")) { JOptionPane.showMessageDialog(null, - NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameIllegalCharacters.message"), - NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagNameIllegalCharacters.title"), + NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagDescriptionIllegalCharacters.message"), + NbBundle.getMessage(TagNameDialog.class, "TagNameDialog.JOptionPane.tagDescriptionIllegalCharacters.title"), JOptionPane.ERROR_MESSAGE); return; } From 3b030a76d873c27ac2a62c53e58771a88c201507 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Wed, 22 Nov 2017 12:32:39 -0500 Subject: [PATCH 54/90] Add new parser file --- .../hashdatabase/HashkeeperHashSetParser.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashkeeperHashSetParser.java diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashkeeperHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashkeeperHashSetParser.java new file mode 100644 index 0000000000..ea9ff75771 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashkeeperHashSetParser.java @@ -0,0 +1,14 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.modules.hashdatabase; + +/** + * + * @author apriestman + */ +public class HashkeeperHashSetParser { + +} From 0f315a5bf2836e49432b1ac3a9e76413f64b6960 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 22 Nov 2017 13:16:35 -0500 Subject: [PATCH 55/90] Cleanup. --- Core/nbproject/project.xml | 2 +- .../EncryptionDetectionFileIngestModule.java} | 235 +++++++++--------- .../EncryptionDetectionModuleFactory.java} | 14 +- 3 files changed, 126 insertions(+), 125 deletions(-) rename Core/src/org/sleuthkit/autopsy/modules/{crypto/CryptoDetectionFileIngestModule.java => encryptiondetection/EncryptionDetectionFileIngestModule.java} (59%) rename Core/src/org/sleuthkit/autopsy/modules/{crypto/CryptoDetectionModuleFactory.java => encryptiondetection/EncryptionDetectionModuleFactory.java} (74%) diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index e5778c0955..0e6b98892f 100755 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -313,7 +313,7 @@ org.sleuthkit.autopsy.ingest org.sleuthkit.autopsy.keywordsearchservice org.sleuthkit.autopsy.menuactions - org.sleuthkit.autopsy.modules.crypto + org.sleuthkit.autopsy.modules.encryptiondetection org.sleuthkit.autopsy.modules.filetypeid org.sleuthkit.autopsy.modules.hashdatabase org.sleuthkit.autopsy.modules.vmextractor diff --git a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java similarity index 59% rename from Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java rename to Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java index f3f821d2e1..f18911c016 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionFileIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.modules.crypto; +package org.sleuthkit.autopsy.modules.encryptiondetection; import java.io.BufferedInputStream; import java.io.IOException; @@ -27,12 +27,10 @@ import java.util.logging.Level; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.ingest.FileIngestModule; +import org.sleuthkit.autopsy.ingest.FileIngestModuleAdapter; import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestModule; -import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; @@ -45,28 +43,30 @@ import org.sleuthkit.datamodel.TskData; /** * File ingest module to detect encryption. */ -final class CryptoDetectionFileIngestModule implements FileIngestModule { +final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter { + private static final double ENTROPY_THRESHOLD = 7.5; + private static final int FILE_SIZE_THRESHOLD = 5242880; // 5MB + private static final int FILE_SIZE_MODULUS = 512; private static final double ONE_OVER_LOG2 = 1.4426950408889634073599246810019; // (1 / log(2)) + private static final int BYTE_OCCURENCES_BUFFER_SIZE = 256; private final IngestServices SERVICES = IngestServices.getInstance(); - private final Logger LOGGER = SERVICES.getLogger(CryptoDetectionModuleFactory.getModuleName()); - private long jobId; - private static final IngestModuleReferenceCounter REF_COUNTER = new IngestModuleReferenceCounter(); + private final Logger LOGGER = SERVICES.getLogger(EncryptionDetectionModuleFactory.getModuleName()); private FileTypeDetector fileTypeDetector; private Blackboard blackboard; + private double entropy; /** - * Create a CryptoDetectionFileIngestModule object that will detect files + * Create a EncryptionDetectionFileIngestModule object that will detect files * that are encrypted and create blackboard artifacts as appropriate. */ - CryptoDetectionFileIngestModule() { + EncryptionDetectionFileIngestModule() { } @Override public void startUp(IngestJobContext context) throws IngestModule.IngestModuleException { - jobId = context.getJobId(); - REF_COUNTER.incrementAndGet(jobId); + blackboard = Case.getCurrentCase().getServices().getBlackboard(); try { fileTypeDetector = new FileTypeDetector(); } catch (FileTypeDetector.FileTypeDetectorInitException ex) { @@ -75,70 +75,129 @@ final class CryptoDetectionFileIngestModule implements FileIngestModule { } @Override - public IngestModule.ProcessResult process(AbstractFile content) { - blackboard = Case.getCurrentCase().getServices().getBlackboard(); + public IngestModule.ProcessResult process(AbstractFile file) { - if (isFileSupported(content)) { - return processFile(content); + try { + if (isFileEncrypted(file)) { + return flagFile(file); + } + } catch (IOException | TskCoreException ex) { + LOGGER.log(Level.SEVERE, String.format("Unable to process file '%s'", Paths.get(file.getParentPath(), file.getName())), ex); + return IngestModule.ProcessResult.ERROR; } return IngestModule.ProcessResult.OK; } /** - * Process the file. If the file has an entropy value greater than seven, - * create a blackboard artifact. + * Create a blackboard artifact. * * @param The file to be processed. * * @return 'OK' if the file was processed successfully, or 'ERROR' if there * was a problem. */ - private IngestModule.ProcessResult processFile(AbstractFile f) { + private IngestModule.ProcessResult flagFile(AbstractFile file) { try { - double entropy = calculateEntropy(f); - if (entropy > 7.5) { - BlackboardArtifact artifact = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED); - - try { - /* - * Index the artifact for keyword search. - */ - blackboard.indexArtifact(artifact); - } catch (Blackboard.BlackboardException ex) { - LOGGER.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex); //NON-NLS - MessageNotifyUtil.Notify.show("Failed to index encryption detected artifact for keyword search.", artifact.getDisplayName(), MessageNotifyUtil.MessageType.ERROR); - } + BlackboardArtifact artifact = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED); + try { /* - * Send an event to update the view with the new result. + * Index the artifact for keyword search. */ - SERVICES.fireModuleDataEvent(new ModuleDataEvent(CryptoDetectionModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED, Collections.singletonList(artifact))); - - /* - * Make an ingest inbox message. - */ - StringBuilder detailsSb = new StringBuilder(); - detailsSb.append("File: " + f.getParentPath() + f.getName() + "
\n"); - detailsSb.append("Entropy: " + entropy); - - SERVICES.postMessage(IngestMessage.createDataMessage(CryptoDetectionModuleFactory.getModuleName(), - "Encryption Detected Match: " + f.getName(), - detailsSb.toString(), - f.getName(), - artifact)); + blackboard.indexArtifact(artifact); + } catch (Blackboard.BlackboardException ex) { + LOGGER.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex); //NON-NLS } + /* + * Send an event to update the view with the new result. + */ + SERVICES.fireModuleDataEvent(new ModuleDataEvent(EncryptionDetectionModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED, Collections.singletonList(artifact))); + + /* + * Make an ingest inbox message. + */ + StringBuilder detailsSb = new StringBuilder(); + detailsSb.append("File: ").append(file.getParentPath()).append(file.getName()).append("
\n"); + detailsSb.append("Entropy: ").append(entropy); + + SERVICES.postMessage(IngestMessage.createDataMessage(EncryptionDetectionModuleFactory.getModuleName(), + "Encryption Detected Match: " + file.getName(), + detailsSb.toString(), + file.getName(), + artifact)); + return IngestModule.ProcessResult.OK; } catch (TskCoreException ex) { - LOGGER.log(Level.WARNING, "Failed to create blackboard artifact ({0}).", ex.getLocalizedMessage()); //NON-NLS - return IngestModule.ProcessResult.ERROR; - } catch (IOException ex) { - LOGGER.log(Level.WARNING, String.format("Failed to calculate the entropy for '%s'.", Paths.get(f.getParentPath(), f.getName())), ex); //NON-NLS + LOGGER.log(Level.SEVERE, String.format("Failed to create blackboard artifact for '%s'.", Paths.get(file.getParentPath(), file.getName())), ex); //NON-NLS return IngestModule.ProcessResult.ERROR; } } + /** + * This method checks if the AbstractFile input is encrypted. Initial + * qualifications require that it be an actual file that is not known, meets + * file size requirements, and has a MIME type of + * 'application/octet-stream'. + * + * @param file AbstractFile to be checked. + * + * @return True if the AbstractFile is encrypted. + */ + private boolean isFileEncrypted(AbstractFile file) throws IOException, TskCoreException { + /* + * Criteria for the checks in this method are partially based on + * http://www.forensicswiki.org/wiki/TrueCrypt#Detection + */ + + boolean possiblyEncrypted = false; + + /* + * Qualify the file type. + */ + if (!file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) + && !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) + && !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR) + && !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR)) { + /* + * Qualify the file against hash databases. + */ + if (!file.getKnown().equals(TskData.FileKnown.KNOWN)) { + /* + * Qualify the size. + */ + long contentSize = file.getSize(); + if (contentSize >= FILE_SIZE_THRESHOLD && (contentSize % FILE_SIZE_MODULUS) == 0) { + /* + * Qualify the MIME type. + */ + try { + String mimeType = fileTypeDetector.getFileType(file); + if (mimeType != null && mimeType.equals("application/octet-stream")) { + possiblyEncrypted = true; + } + } catch (TskCoreException ex) { + throw new TskCoreException("Failed to detect the file type.", ex); + } + } + } + } + + if (possiblyEncrypted) { + try { + entropy = calculateEntropy(file); + if (entropy > ENTROPY_THRESHOLD) { + return true; + } + } catch (IOException ex) { + throw new IOException("Unable to calculate the entropy.", ex); + } + } + + return false; + } + /** * Calculate the entropy of the file. The result is used to qualify the file * as an encrypted file. @@ -155,6 +214,7 @@ final class CryptoDetectionFileIngestModule implements FileIngestModule { * Logic in this method is based on * https://github.com/willjasen/entropy/blob/master/entropy.java */ + InputStream in = null; BufferedInputStream bin = null; @@ -165,7 +225,7 @@ final class CryptoDetectionFileIngestModule implements FileIngestModule { /* * Determine the number of times each byte value appears. */ - int[] byteOccurences = new int[256]; + int[] byteOccurences = new int[BYTE_OCCURENCES_BUFFER_SIZE]; int readByte; while ((readByte = bin.read()) != -1) { byteOccurences[readByte]++; @@ -175,19 +235,18 @@ final class CryptoDetectionFileIngestModule implements FileIngestModule { * Calculate the entropy based on the byte occurence counts. */ long dataLength = file.getSize() - 1; - double entropy = 0; - for (int i = 0; i < 256; i++) { + double entropyAccumulator = 0; + for (int i = 0; i < BYTE_OCCURENCES_BUFFER_SIZE; i++) { if (byteOccurences[i] > 0) { double byteProbability = (double) byteOccurences[i] / (double) dataLength; - entropy += (byteProbability * Math.log(byteProbability) * ONE_OVER_LOG2); + entropyAccumulator += (byteProbability * Math.log(byteProbability) * ONE_OVER_LOG2); } } - return -entropy; + return -entropyAccumulator; } catch (IOException ex) { - LOGGER.log(Level.WARNING, "IOException occurred while trying to read data from InputStream.", ex); //NON-NLS - throw ex; + throw new IOException("IOException occurred while trying to read data from InputStream.", ex); } finally { try { if (in != null) { @@ -197,66 +256,8 @@ final class CryptoDetectionFileIngestModule implements FileIngestModule { bin.close(); } } catch (IOException ex) { - LOGGER.log(Level.WARNING, "Failed to close InputStream.", ex); //NON-NLS - throw ex; + throw new IOException("Failed to close InputStream.", ex); } } } - - /** - * This method checks if the AbstractFile input is supported. To qualify, it - * must be an actual file that is not known, has a size that's evenly - * divisible by 512 and a minimum size of 5MB, and has a MIME type of - * 'application/octet-stream'. - * - * @param file AbstractFile to be checked. - * - * @return True if the AbstractFile qualifies. - */ - private boolean isFileSupported(AbstractFile file) { - /* - * Criteria for the checks in this method are partially based on - * http://www.forensicswiki.org/wiki/TrueCrypt#Detection - */ - - boolean supported = false; - - /* - * Qualify the file type. - */ - if (!file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) - && !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) - && !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR) - && !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR)) { - /* - * Qualify the file against hash databases. - */ - if (!file.getKnown().equals(TskData.FileKnown.KNOWN)) { - /* - * Qualify the size. - */ - long contentSize = file.getSize(); - if (contentSize >= 5242880 && (contentSize % 512) == 0) { - /* - * Qualify the MIME type. - */ - try { - String mimeType = fileTypeDetector.getFileType(file); - if (mimeType != null && mimeType.equals("application/octet-stream")) { - supported = true; - } - } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, "Failed to detect file type", ex); //NON-NLS - } - } - } - } - - return supported; - } - - @Override - public void shutDown() { - REF_COUNTER.decrementAndGet(jobId); - } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionModuleFactory.java similarity index 74% rename from Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java rename to Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionModuleFactory.java index f40b2a3490..53eca1aec6 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/crypto/CryptoDetectionModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionModuleFactory.java @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.sleuthkit.autopsy.modules.crypto; +package org.sleuthkit.autopsy.modules.encryptiondetection; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; @@ -32,10 +32,10 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; */ @ServiceProvider(service = IngestModuleFactory.class) @Messages({ - "CryptoDetectionFileIngestModule.moduleName.text=Crypto Detection", - "CryptoDetectionFileIngestModule.getDesc.text=Looks for large files with high entropy." + "EncryptionDetectionFileIngestModule.moduleName.text=Encryption Detection", + "EncryptionDetectionFileIngestModule.getDesc.text=Looks for large files with high entropy." }) -public class CryptoDetectionModuleFactory extends IngestModuleFactoryAdapter { +public class EncryptionDetectionModuleFactory extends IngestModuleFactoryAdapter { @Override public String getModuleDisplayName() { @@ -48,12 +48,12 @@ public class CryptoDetectionModuleFactory extends IngestModuleFactoryAdapter { * @return The module name. */ static String getModuleName() { - return NbBundle.getMessage(CryptoDetectionFileIngestModule.class, "CryptoDetectionFileIngestModule.moduleName.text"); + return NbBundle.getMessage(EncryptionDetectionFileIngestModule.class, "EncryptionDetectionFileIngestModule.moduleName.text"); } @Override public String getModuleDescription() { - return NbBundle.getMessage(CryptoDetectionFileIngestModule.class, "CryptoDetectionFileIngestModule.getDesc.text"); + return NbBundle.getMessage(EncryptionDetectionFileIngestModule.class, "EncryptionDetectionFileIngestModule.getDesc.text"); } @Override @@ -68,6 +68,6 @@ public class CryptoDetectionModuleFactory extends IngestModuleFactoryAdapter { @Override public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings ingestOptions) { - return new CryptoDetectionFileIngestModule(); + return new EncryptionDetectionFileIngestModule(); } } \ No newline at end of file From a5dca8681fac15b9ca4d9c71836ef073aad7d810 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 22 Nov 2017 16:57:18 -0500 Subject: [PATCH 56/90] 3202 rename event for tag definition changes and comment code better in caseeventlistener --- .../sleuthkit/autopsy/casemodule/Case.java | 20 +++- .../casemodule/services/TagOptionsPanel.java | 5 +- .../eventlisteners/CaseEventListener.java | 104 +++++++++++------- 3 files changed, 81 insertions(+), 48 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 2dcc532a37..52a2b7fa97 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -364,10 +364,11 @@ public class Case { */ CASE_DETAILS, /** - * The status which a Tag indicates has been changed and the new value - * of the TagNameDefinition is included. + * A tag definition has changed (e.g., description, known status). The + * old value of the PropertyChangeEvent is the display name of the tag + * definition that has changed. */ - TAG_STATUS_CHANGED; + TAG_DEFINITION_CHANGED; }; @@ -1478,9 +1479,18 @@ public class Case { eventPublisher.publish(new ContentTagDeletedEvent(deletedTag)); } - public void notifyTagStatusChanged(String changedTagName) { - eventPublisher.publish(new AutopsyEvent(Events.TAG_STATUS_CHANGED.toString(), changedTagName, changedTagName)); + /** + * Notifies case event subscribers that a tag definition has changed. + * + * This should not be called from the event dispatch thread (EDT) + * + * @param changedTagName the name of the tag definition which was changed + */ + public void notifyTagDefinitionChanged(String changedTagName) { + //leaving new value of changedTagName as null, because we do not currently support changing the display name of a tag. + eventPublisher.publish(new AutopsyEvent(Events.TAG_DEFINITION_CHANGED.toString(), changedTagName, null)); } + /** * Notifies case event subscribers that an artifact tag has been added. * diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java index 712fa6480d..c5458d2f76 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagOptionsPanel.java @@ -423,7 +423,10 @@ final class TagOptionsPanel extends javax.swing.JPanel implements OptionsPanel { private void sendStatusChangedEvents() { for (String modifiedTagDisplayName : updatedStatusTags) { - Case.getCurrentCase().notifyTagStatusChanged(modifiedTagDisplayName); + //if user closes their case after options have been changed but before application of them is complete don't notify + if (Case.isCaseOpen()) { + Case.getCurrentCase().notifyTagDefinitionChanged(modifiedTagDisplayName); + } } updatedStatusTags.clear(); } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index cc6dbaf142..7252ca53cc 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -98,8 +98,8 @@ final class CaseEventListener implements PropertyChangeListener { jobProcessingExecutor.submit(new DataSourceAddedTask(dbManager, evt)); } break; - case TAG_STATUS_CHANGED: { - jobProcessingExecutor.submit(new TagStatusChangeTask(evt)); + case TAG_DEFINITION_CHANGED: { + jobProcessingExecutor.submit(new TagDefinitionChangeTask(evt)); } break; case CURRENT_CASE: { @@ -298,11 +298,11 @@ final class CaseEventListener implements PropertyChangeListener { } - private final class TagStatusChangeTask implements Runnable { + private final class TagDefinitionChangeTask implements Runnable { private final PropertyChangeEvent event; - private TagStatusChangeTask(PropertyChangeEvent evt) { + private TagDefinitionChangeTask(PropertyChangeEvent evt) { event = evt; } @@ -311,73 +311,93 @@ final class CaseEventListener implements PropertyChangeListener { if (!EamDb.isEnabled()) { return; } - String modifiedTagName = (String) event.getNewValue(); - List notableTags = TagsManager.getNotableTagDisplayNames(); - TskData.FileKnown status = notableTags.contains(modifiedTagName) ? TskData.FileKnown.BAD : TskData.FileKnown.UNKNOWN; - /** + //get the display name of the tag that has had it's definition modified + String modifiedTagName = (String) event.getOldValue(); + + /* * Set knownBad status for all files/artifacts in the given case * that are tagged with the given tag name. */ try { TagName tagName = Case.getCurrentCase().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(modifiedTagName); - // First find any matching artifacts + //First update the artifacts + //Get all BlackboardArtifactTags with this tag name List artifactTags = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifactTagsByTagName(tagName); for (BlackboardArtifactTag bbTag : artifactTags) { - List convertedArtifacts = EamArtifactUtil.getCorrelationAttributeFromBlackboardArtifact(bbTag.getArtifact(), true, true); - for (CorrelationAttribute eamArtifact : convertedArtifacts) { - boolean hasOtherBadTags = false; - //if the new status of the tag is unknown UNKNOWN ensure we are not changing the status of BlackboardArtifact which still have other tags with a non-unknown status - if (status == TskData.FileKnown.UNKNOWN) { - Content content = bbTag.getContent(); - if ((content instanceof AbstractFile) && (((AbstractFile) content).getKnown() == TskData.FileKnown.KNOWN)) { + //start with assumption that none of the other tags applied to this Correlation Attribute will prevent it's status from being changed + boolean hasTagWithConflictingKnownStatus = false; + // if the status of the tag has been changed to TskData.FileKnown.UNKNOWN + // we need to check the status of all other tags on this correlation attribute before changing + // the status of the correlation attribute in the central repository + if (tagName.getKnownStatus() == TskData.FileKnown.UNKNOWN) { + Content content = bbTag.getContent(); + // If the content which this Blackboard Artifact Tag is linked to is an AbstractFile with KNOWN status then + // it's status in the central reporsitory should not be changed to UNKNOWN + if ((content instanceof AbstractFile) && (((AbstractFile) content).getKnown() == TskData.FileKnown.KNOWN)) { + continue; + } + //Get the BlackboardArtifact which this BlackboardArtifactTag has been applied to. + BlackboardArtifact bbArtifact = bbTag.getArtifact(); + TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); + List tags = tagsManager.getBlackboardArtifactTagsByArtifact(bbArtifact); + //get all tags which are on this blackboard artifact + for (BlackboardArtifactTag t : tags) { + //All instances of the modified tag name will be changed, they can not conflict with each other + if (t.getName().equals(tagName)) { + continue; + } + //if any other tags on this artifact are Notable in status then this artifact can not have its status changed + if (TskData.FileKnown.BAD == t.getName().getKnownStatus()) { + //a tag with a conflicting status has been found, the status of this correlation attribute can not be modified + hasTagWithConflictingKnownStatus = true; break; } - BlackboardArtifact bbArtifact = bbTag.getArtifact(); - TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); - List tags = tagsManager.getBlackboardArtifactTagsByArtifact(bbArtifact); - for (BlackboardArtifactTag t : tags) { - //avoid the possibility for threading issues if the tag whose status is currently changing is ever still in the tags manager with the old status - if (t.getName().equals(tagName)) { - continue; - } - //if any other tags on this artifact are Notable in status then this artifact can not have its status changed - if (notableTags.contains(t.getName().getDisplayName())) { - hasOtherBadTags = true; - break; - } - } } - if (!hasOtherBadTags) { - EamDb.getInstance().setArtifactInstanceKnownStatus(eamArtifact, status); + } + //if the Correlation Attribute will have no tags with a status which would prevent the current status from being changed + if (!hasTagWithConflictingKnownStatus) { + //Get the correlation atttributes that correspond to the current BlackboardArtifactTag if their status should be changed + //with the initial set of correlation attributes this should be a single correlation attribute + List convertedArtifacts = EamArtifactUtil.getCorrelationAttributeFromBlackboardArtifact(bbTag.getArtifact(), true, true); + for (CorrelationAttribute eamArtifact : convertedArtifacts) { + EamDb.getInstance().setArtifactInstanceKnownStatus(eamArtifact, tagName.getKnownStatus()); } } } - // Now search for files + // Next update the files + List fileTags = Case.getCurrentCase().getSleuthkitCase().getContentTagsByTagName(tagName); + //Get all ContentTags with this tag name for (ContentTag contentTag : fileTags) { - boolean hasOtherBadTags = false; - //if the new status of the tag is unknown UNKNOWN ensure we are not changing the status of files which still have other tags with a Notable status - if (status == TskData.FileKnown.UNKNOWN) { + //start with assumption that none of the other tags applied to this ContentTag will prevent it's status from being changed + boolean hasTagWithConflictingKnownStatus = false; + // if the status of the tag has been changed to TskData.FileKnown.UNKNOWN + // we need to check the status of all other tags on this file before changing + // the status of the file in the central repository + if (tagName.getKnownStatus() == TskData.FileKnown.UNKNOWN) { Content content = contentTag.getContent(); TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager(); List tags = tagsManager.getContentTagsByContent(content); + //get all tags which are on this file for (ContentTag t : tags) { - //avoid the possibility for threading issues if the tag whose status is currently changing is ever still in the tags manager with the old status + //All instances of the modified tag name will be changed, they can not conflict with each other if (t.getName().equals(tagName)) { continue; } //if any other tags on this file are Notable in status then this file can not have its status changed - if (notableTags.contains(t.getName().getDisplayName())) { - hasOtherBadTags = true; + if (TskData.FileKnown.BAD == t.getName().getKnownStatus()) { + //a tag with a conflicting status has been found, the status of this file can not be modified + hasTagWithConflictingKnownStatus = true; break; } } } - if (!hasOtherBadTags) { + //if the file will have no tags with a status which would prevent the current status from being changed + if (!hasTagWithConflictingKnownStatus) { final CorrelationAttribute eamArtifact = EamArtifactUtil.getEamArtifactFromContent(contentTag.getContent(), - status, ""); + tagName.getKnownStatus(), ""); if (eamArtifact != null) { - EamDb.getInstance().setArtifactInstanceKnownStatus(eamArtifact, status); + EamDb.getInstance().setArtifactInstanceKnownStatus(eamArtifact, tagName.getKnownStatus()); } } } From 29e953ab4fcc8e700b06eb0316f1453b068792fa Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 22 Nov 2017 17:43:59 -0500 Subject: [PATCH 57/90] Completed feature. --- .../autoingest/AutoIngestJob.java | 38 ++++++++++++++++++- .../autoingest/AutoIngestJobNodeData.java | 21 ++++++---- .../autoingest/AutoIngestManager.java | 24 ++++++++---- 3 files changed, 65 insertions(+), 18 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java index dd4cb60377..40537d3b83 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java @@ -38,10 +38,10 @@ import org.sleuthkit.autopsy.ingest.IngestJob; * ingest service. */ @ThreadSafe -public final class AutoIngestJob implements Comparable, Serializable { +final class AutoIngestJob implements Comparable, Serializable { private static final long serialVersionUID = 1L; - private static final int CURRENT_VERSION = 1; + private static final int CURRENT_VERSION = 2; private static final int DEFAULT_PRIORITY = 0; private static final String LOCAL_HOST_NAME = NetworkUtils.getLocalHostName(); @@ -82,6 +82,12 @@ public final class AutoIngestJob implements Comparable, Serializa private int numberOfCrashes; @GuardedBy("this") private StageDetails stageDetails; + + /* + * Version 2 fields. + */ + @GuardedBy("this") + private long dataSourceSize; /** * Constructs a new automated ingest job. All job state not specified in the @@ -114,6 +120,11 @@ public final class AutoIngestJob implements Comparable, Serializa this.processingStatus = ProcessingStatus.PENDING; this.numberOfCrashes = 0; this.stageDetails = this.getProcessingStageDetails(); + + /* + * Version 2 fields. + */ + this.dataSourceSize = 0; } catch (Exception ex) { throw new AutoIngestJobException(String.format("Error creating automated ingest job"), ex); } @@ -151,6 +162,11 @@ public final class AutoIngestJob implements Comparable, Serializa this.processingStatus = nodeData.getProcessingStatus(); this.numberOfCrashes = nodeData.getNumberOfCrashes(); this.stageDetails = this.getProcessingStageDetails(); + + /* + * Version 2 fields. + */ + this.dataSourceSize = nodeData.getDataSourceSize(); } catch (Exception ex) { throw new AutoIngestJobException(String.format("Error creating automated ingest job"), ex); } @@ -462,6 +478,24 @@ public final class AutoIngestJob implements Comparable, Serializa this.numberOfCrashes = numberOfCrashes; } + /** + * Gets the total size of the data source. + * + * @return The data source size. + */ + synchronized long getDataSourceSize() { + return dataSourceSize; + } + + /** + * Sets the total size of the data source. + * + * @param dataSourceSize The data source size. + */ + synchronized void setDataSourceSize(long dataSourceSize) { + this.dataSourceSize = dataSourceSize; + } + /** * Indicates whether some other job is "equal to" this job. Two jobs are * equal if they have the same manifest file path. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java index e3ecf177e1..f367fdf553 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java @@ -114,7 +114,7 @@ final class AutoIngestJobNodeData { setProcessingStage(job.getProcessingStage()); setProcessingStageStartDate(job.getProcessingStageStartDate()); setProcessingStageDetails(job.getProcessingStageDetails()); - //DLG: + setDataSourceSize(job.getDataSourceSize()); } /** @@ -184,10 +184,13 @@ final class AutoIngestJobNodeData { this.processingStageDetailsDescription = getStringFromBuffer(buffer, TypeKind.BYTE); this.processingStageDetailsStartDate = buffer.getLong(); this.processingHostName = getStringFromBuffer(buffer, TypeKind.SHORT); - - if (this.version >= 2) { - this.dataSourceSize = buffer.getLong(); - } + } + + if (buffer.hasRemaining()) { + /* + * Get version 2 fields. + */ + this.dataSourceSize = buffer.getLong(); } } catch (BufferUnderflowException ex) { @@ -511,16 +514,18 @@ final class AutoIngestJobNodeData { } /** - * DLG: + * Gets the total size of the data source. + * + * @return The data source size. */ long getDataSourceSize() { return this.dataSourceSize; } /** - * DLG: + * Sets the total size of the data source. * - * @param DLG: + * @param dataSourceSize The data source size. */ void setDataSourceSize(long dataSourceSize) { this.dataSourceSize = dataSourceSize; diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 199cb8a8db..2a0c8cd60b 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -56,7 +56,6 @@ import java.util.concurrent.Future; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; -import java.util.stream.Collectors; import javax.annotation.concurrent.GuardedBy; import org.openide.util.Lookup; import org.sleuthkit.autopsy.casemodule.Case; @@ -2547,20 +2546,29 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen currentJob.setIngestJob(null); } } - - /* - * DLG: + + /** + * Gather metrics to store in auto ingest job nodes. A SleuthkitCase + * instance is used to get the content size. + * + * @param caseDb The SleuthkitCase instance. + * @param dataSource The auto ingest data source. + * + * @throws CoordinationServiceException If there's a problem retrieving + * data from the coordination + * service. + * @throws InterruptedException If the thread calling the + * coordination service is + * interrupted. */ private void collectMetrics(SleuthkitCase caseDb, AutoIngestDataSource dataSource) throws CoordinationServiceException, InterruptedException { List contentList = dataSource.getContent(); long dataSourceSize = 0; for (Content content : contentList) { - // DLG: Why multiply Content objects? - // DLG: What to do if more than one? - dataSourceSize = ((DataSource)content).getContentSize(caseDb); + dataSourceSize += ((DataSource) content).getContentSize(caseDb); } + currentJob.setDataSourceSize(dataSourceSize); AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(currentJob); - nodeData.setDataSourceSize(dataSourceSize); String manifestNodePath = currentJob.getManifest().getFilePath().toString(); coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, nodeData.toArray()); } From 8dfd028c3111694f1fd378a605615c0edbaff93c Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 22 Nov 2017 17:45:01 -0500 Subject: [PATCH 58/90] 3203 add (Notable) to end of tags in generated reports --- .../casemodule/services/TagsManager.java | 5 +++++ .../sleuthkit/autopsy/report/ReportHTML.java | 4 +++- .../autopsy/report/ReportVisualPanel2.java | 5 ++++- .../autopsy/report/TableReportGenerator.java | 17 +++++++++++------ 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java index b28769a50a..f96fe08f23 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagsManager.java @@ -71,6 +71,11 @@ public class TagsManager implements Closeable { } @NbBundle.Messages({"TagsManager.notableTagEnding.text= (Notable)"}) + /** + * Get String of text which is used to label tags as notable to the user. + * + * @return Bundle message TagsManager.notableTagEnding.text + */ public static String getNotableTagLabel(){ return Bundle.TagsManager_notableTagEnding_text(); } diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java index c03c37a09b..aab7eaae97 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportHTML.java @@ -63,6 +63,7 @@ import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM; class ReportHTML implements TableReportModule { @@ -688,7 +689,8 @@ class ReportHTML implements TableReportModule { } for (int i = 0; i < tags.size(); i++) { ContentTag tag = tags.get(i); - linkToThumbnail.append(tag.getName().getDisplayName()); + String notableString = tag.getName().getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; + linkToThumbnail.append(tag.getName().getDisplayName() + notableString); if (i != tags.size() - 1) { linkToThumbnail.append(", "); } diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel2.java b/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel2.java index 08ec3d0151..53422c8f0d 100755 --- a/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel2.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportVisualPanel2.java @@ -41,10 +41,12 @@ import javax.swing.event.ListDataListener; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; final class ReportVisualPanel2 extends JPanel { @@ -102,7 +104,8 @@ final class ReportVisualPanel2 extends JPanel { } for (TagName tagName : tagNamesInUse) { - tagStates.put(tagName.getDisplayName(), Boolean.FALSE); + String notableString = tagName.getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; + tagStates.put(tagName.getDisplayName() + notableString, Boolean.FALSE); } tags.addAll(tagStates.keySet()); diff --git a/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java index 3df94c1d1c..8d5ad932ca 100755 --- a/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java @@ -39,6 +39,7 @@ import java.util.TreeSet; import java.util.logging.Level; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.casemodule.services.TagsManager; import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.Logger; @@ -299,7 +300,8 @@ class TableReportGenerator { // Give the modules the rows for the content tags. for (ContentTag tag : tags) { // skip tags that we are not reporting on - if (passesTagNamesFilter(tag.getName().getDisplayName()) == false) { + String notableString = tag.getName().getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; + if (passesTagNamesFilter(tag.getName().getDisplayName() + notableString) == false) { continue; } @@ -310,7 +312,7 @@ class TableReportGenerator { fileName = tag.getContent().getName(); } - ArrayList rowData = new ArrayList<>(Arrays.asList(tag.getName().getDisplayName(), fileName, tag.getComment())); + ArrayList rowData = new ArrayList<>(Arrays.asList(tag.getName().getDisplayName() + notableString, fileName, tag.getComment())); Content content = tag.getContent(); if (content instanceof AbstractFile) { AbstractFile file = (AbstractFile) content; @@ -376,12 +378,13 @@ class TableReportGenerator { // Give the modules the rows for the content tags. for (BlackboardArtifactTag tag : tags) { - if (passesTagNamesFilter(tag.getName().getDisplayName()) == false) { + String notableString = tag.getName().getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; + if (passesTagNamesFilter(tag.getName().getDisplayName() + notableString) == false) { continue; } List row; - row = new ArrayList<>(Arrays.asList(tag.getArtifact().getArtifactTypeName(), tag.getName().getDisplayName(), tag.getComment(), tag.getContent().getName())); + row = new ArrayList<>(Arrays.asList(tag.getArtifact().getArtifactTypeName(), tag.getName().getDisplayName() + notableString, tag.getComment(), tag.getContent().getName())); tableReport.addRow(row); // check if the tag is an image that we should later make a thumbnail for @@ -963,7 +966,8 @@ class TableReportGenerator { try { List contentTags = Case.getCurrentCase().getServices().getTagsManager().getContentTagsByContent(content); for (ContentTag ct : contentTags) { - allTags.add(ct.getName().getDisplayName()); + String notableString = ct.getName().getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; + allTags.add(ct.getName().getDisplayName() + notableString); } } catch (TskCoreException ex) { errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedGetContentTags")); @@ -1000,7 +1004,8 @@ class TableReportGenerator { List tags = Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact); HashSet uniqueTagNames = new HashSet<>(); for (BlackboardArtifactTag tag : tags) { - uniqueTagNames.add(tag.getName().getDisplayName()); + String notableString = tag.getName().getKnownStatus() == TskData.FileKnown.BAD ? TagsManager.getNotableTagLabel() : ""; + uniqueTagNames.add(tag.getName().getDisplayName() + notableString); } if (failsTagFilter(uniqueTagNames, tagNamesFilter)) { continue; From 27b9edbd29f44a34d38ecb5b4d0d3dd8055d1e4d Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 22 Nov 2017 17:51:34 -0500 Subject: [PATCH 59/90] Additional comments added. --- .../autopsy/experimental/autoingest/AutoIngestManager.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 2a0c8cd60b..83337c551b 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -2562,12 +2562,19 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen * interrupted. */ private void collectMetrics(SleuthkitCase caseDb, AutoIngestDataSource dataSource) throws CoordinationServiceException, InterruptedException { + /* + * Get the data source size and store it in the current job. + */ List contentList = dataSource.getContent(); long dataSourceSize = 0; for (Content content : contentList) { dataSourceSize += ((DataSource) content).getContentSize(caseDb); } currentJob.setDataSourceSize(dataSourceSize); + + /* + * Create node data from the current job and store it. + */ AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(currentJob); String manifestNodePath = currentJob.getManifest().getFilePath().toString(); coordinationService.setNodeData(CoordinationService.CategoryNode.MANIFESTS, manifestNodePath, nodeData.toArray()); From 0e0ee5cd6c2cd148c5bc927af756c86f4294b30c Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 22 Nov 2017 17:55:05 -0500 Subject: [PATCH 60/90] 3203 change new bundle properties to @messages syntax --- Core/src/org/sleuthkit/autopsy/actions/Bundle.properties | 2 -- Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java | 5 ++++- .../sleuthkit/autopsy/casemodule/services/Bundle.properties | 2 -- .../sleuthkit/autopsy/casemodule/services/TagNameDialog.java | 2 ++ 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties b/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties index 01d0d21b47..1cbc4b70b6 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/actions/Bundle.properties @@ -44,6 +44,4 @@ ShowIngestProgressSnapshotAction.actionName.text=Get Ingest Progress Snapshot OpenPythonModulesFolderAction.actionName.text=Python Plugins OpenPythonModulesFolderAction.errorMsg.folderNotFound=Python plugins folder not found: {0} CTL_OpenPythonModulesFolderAction=Python Plugins -GetTagNameDialog.descriptionLabel.text=Description: -GetTagNameDialog.notableCheckbox.text=Tag indicates item is notable. GetTagNameAndCommentDialog.tagCombo.toolTipText=Select tag to use diff --git a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java index ec282dfa1f..515db21dab 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/actions/GetTagNameDialog.java @@ -36,6 +36,7 @@ import javax.swing.KeyStroke; import javax.swing.table.AbstractTableModel; import org.openide.util.ImageUtilities; import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.TagsManager; @@ -44,6 +45,8 @@ import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; +@Messages({"GetTagNameDialog.descriptionLabel.text=Description:", + "GetTagNameDialog.notableCheckbox.text=Tag indicates item is notable."}) public class GetTagNameDialog extends JDialog { private static final long serialVersionUID = 1L; @@ -335,7 +338,7 @@ public class GetTagNameDialog extends JDialog { JOptionPane.ERROR_MESSAGE); } else if (userTagDescription.contains(",") || userTagDescription.contains(";")) { - JOptionPane.showMessageDialog(null, + JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "GetTagNameDialog.tagDescriptionIllegalCharacters.message"), NbBundle.getMessage(this.getClass(), "GetTagNameDialog.tagDescriptionIllegalCharacters.title"), JOptionPane.ERROR_MESSAGE); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties index 95fd09a57b..e9c1b5307c 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/Bundle.properties @@ -9,9 +9,7 @@ TagNameDialog.JOptionPane.tagNameEmpty.title=Empty tag name TagOptionsPanel.tagTypesListLabel.text=Tag Names: TagOptionsPanel.deleteTagNameButton.text=Delete Tag TagOptionsPanel.newTagNameButton.text=New Tag -TagNameDialog.descriptionLabel.text=Description: TagNameDialog.okButton.text=OK TagNameDialog.cancelButton.text=Cancel TagNameDialog.tagNameTextField.text= TagNameDialog.newTagNameLabel.text=Name: -TagNameDialog.notableCheckbox.text=Tag indicates item is notable. \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java index e8f2275db4..4949be2507 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDialog.java @@ -31,6 +31,8 @@ import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.datamodel.TskData; +@Messages({"TagNameDialog.descriptionLabel.text=Description:", + "TagNameDialog.notableCheckbox.text=Tag indicates item is notable."}) final class TagNameDialog extends javax.swing.JDialog { private static final long serialVersionUID = 1L; From 605994d64174e64520e45938fbf95f36a4bc415a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 22 Nov 2017 18:17:09 -0500 Subject: [PATCH 61/90] 3224 add Databases node to File Types by Extension tree --- .../org/sleuthkit/autopsy/datamodel/FileTypeExtensions.java | 5 +++++ .../sleuthkit/autopsy/datamodel/FileTypesByExtension.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeExtensions.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeExtensions.java index 4195b33008..eafa8377b2 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeExtensions.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypeExtensions.java @@ -38,6 +38,7 @@ public class FileTypeExtensions { private final static List WEB_EXTENSIONS = Arrays.asList(".html", ".htm", ".css", ".js", ".php", ".aspx"); //NON-NLS private final static List PDF_EXTENSIONS = Arrays.asList(".pdf"); //NON-NLS private final static List ARCHIVE_EXTENSIONS = Arrays.asList(".zip", ".rar", ".7zip", ".7z", ".arj", ".tar", ".gzip", ".bzip", ".bzip2", ".cab", ".jar", ".cpio", ".ar", ".gz", ".tgz", ".bz2"); //NON-NLS + private final static List DATABASE_EXTENSIONS = Arrays.asList(".db", ".db3", ".sqlite", ".sqlite3"); //NON-NLS public static List getImageExtensions() { return IMAGE_EXTENSIONS; @@ -75,6 +76,10 @@ public class FileTypeExtensions { return ARCHIVE_EXTENSIONS; } + public static List getDatabaseExtensions() { + return DATABASE_EXTENSIONS; + } + private FileTypeExtensions() { } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java index 305da8e953..3c79626e81 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java @@ -34,6 +34,7 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.Lookups; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.core.UserPreferences; @@ -423,6 +424,7 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { } // root node filters + @Messages({"FileTypeExtensionFilters.tskDatabaseFilter.text=Databases"}) public static enum RootFilter implements AutopsyVisitableItem, SearchFilterInterface { TSK_IMAGE_FILTER(0, "TSK_IMAGE_FILTER", //NON-NLS @@ -437,6 +439,9 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { TSK_ARCHIVE_FILTER(3, "TSK_ARCHIVE_FILTER", //NON-NLS NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskArchiveFilter.text"), FileTypeExtensions.getArchiveExtensions()), + TSK_DATABASE_FILTER(3, "TSK_DATABASE_FILTER", //NON-NLS + NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskDatabaseFilter.text"), + FileTypeExtensions.getDatabaseExtensions()), TSK_DOCUMENT_FILTER(3, "TSK_DOCUMENT_FILTER", //NON-NLS NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskDocumentFilter.text"), Arrays.asList(".htm", ".html", ".doc", ".docx", ".odt", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".rtf")), //NON-NLS From d7c59a0356ce7c329bf388a7fa93b0bc5061abb1 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 22 Nov 2017 18:19:34 -0500 Subject: [PATCH 62/90] 3224 fix IDs for FileTypesByExtension filter enum --- .../sleuthkit/autopsy/datamodel/FileTypesByExtension.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java index 3c79626e81..2341fff12c 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileTypesByExtension.java @@ -439,13 +439,13 @@ public final class FileTypesByExtension implements AutopsyVisitableItem { TSK_ARCHIVE_FILTER(3, "TSK_ARCHIVE_FILTER", //NON-NLS NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskArchiveFilter.text"), FileTypeExtensions.getArchiveExtensions()), - TSK_DATABASE_FILTER(3, "TSK_DATABASE_FILTER", //NON-NLS + TSK_DATABASE_FILTER(4, "TSK_DATABASE_FILTER", //NON-NLS NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskDatabaseFilter.text"), FileTypeExtensions.getDatabaseExtensions()), - TSK_DOCUMENT_FILTER(3, "TSK_DOCUMENT_FILTER", //NON-NLS + TSK_DOCUMENT_FILTER(5, "TSK_DOCUMENT_FILTER", //NON-NLS NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskDocumentFilter.text"), Arrays.asList(".htm", ".html", ".doc", ".docx", ".odt", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".rtf")), //NON-NLS - TSK_EXECUTABLE_FILTER(3, "TSK_EXECUTABLE_FILTER", //NON-NLS + TSK_EXECUTABLE_FILTER(6, "TSK_EXECUTABLE_FILTER", //NON-NLS NbBundle.getMessage(FileTypesByExtension.class, "FileTypeExtensionFilters.tskExecFilter.text"), FileTypeExtensions.getExecutableExtensions()); //NON-NLS From 81d35de2c49b4792484d161944f2b862255330f5 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 27 Nov 2017 10:06:55 -0500 Subject: [PATCH 63/90] Add support for importing hashkeeper hash sets and md5sum output text files --- .../HashDbImportDatabaseDialog.java | 22 +-- .../hashdatabase/HashkeeperHashSetParser.java | 132 +++++++++++++++++- .../hashdatabase/IdxHashSetParser.java | 13 +- .../ImportCentralRepoDbProgressDialog.java | 4 +- 4 files changed, 141 insertions(+), 30 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index db70d1114d..d2af9533be 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -84,25 +84,12 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { private void initFileChooser() { fileChooser.setDragEnabled(false); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - updateFileChooserFilter(); + String[] EXTENSION = new String[]{"txt", "kdb", "idx", "hash", "Hash", "hsh"}; //NON-NLS + FileNameExtensionFilter filter = new FileNameExtensionFilter( + NbBundle.getMessage(this.getClass(), "HashDbImportDatabaseDialog.fileNameExtFilter.text"), EXTENSION); + fileChooser.setFileFilter(filter); fileChooser.setMultiSelectionEnabled(false); } - - @NbBundle.Messages({"HashDbImportDatabaseDialog.centralRepoExtFilter.text=Hash Database File (.kdb, .idx or .hash)"}) - private void updateFileChooserFilter() { - fileChooser.resetChoosableFileFilters(); - if(centralRepoRadioButton.isSelected()){ - String[] EXTENSION = new String[]{"kdb", "idx", "hash", "Hash"}; //NON-NLS - FileNameExtensionFilter filter = new FileNameExtensionFilter( - NbBundle.getMessage(this.getClass(), "HashDbImportDatabaseDialog.centralRepoExtFilter.text"), EXTENSION); - fileChooser.setFileFilter(filter); - } else { - String[] EXTENSION = new String[]{"txt", "kdb", "idx", "hash", "Hash", "hsh"}; //NON-NLS - FileNameExtensionFilter filter = new FileNameExtensionFilter( - NbBundle.getMessage(this.getClass(), "HashDbImportDatabaseDialog.fileNameExtFilter.text"), EXTENSION); - fileChooser.setFileFilter(filter); - } - } private void display() { Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); @@ -409,7 +396,6 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { hashDbFolder.mkdir(); } fileChooser.setCurrentDirectory(hashDbFolder); - updateFileChooserFilter(); if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { File databaseFile = fileChooser.getSelectedFile(); try { diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashkeeperHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashkeeperHashSetParser.java index ea9ff75771..e325bc94da 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashkeeperHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashkeeperHashSetParser.java @@ -1,14 +1,134 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * Autopsy Forensic Browser + * + * Copyright 2011 - 2017 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.modules.hashdatabase; +import java.io.File; +import java.io.InputStreamReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.logging.Level; +import java.util.Iterator; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.TskCoreException; + /** - * - * @author apriestman + * Parser for Hashkeeper hash sets (*.hsh) */ -public class HashkeeperHashSetParser { +public class HashkeeperHashSetParser implements HashSetParser { + private String filename; + private InputStreamReader inputStreamReader; + private CSVParser csvParser; + private final long expectedHashCount; // Number of hashes we expect to read from the file + private final Iterator recordIterator; + private final int hashColumnIndex; // The index of the hash column + + HashkeeperHashSetParser(String filename) throws TskCoreException { + this.filename = filename; + + try{ + // Estimate the total number of hashes in the file + File importFile = new File(filename); + long fileSize = importFile.length(); + expectedHashCount = fileSize / 75 + 1; // As a rough estimate, assume 75 bytes per line. We add one to prevent this from being zero + + // Create the parser + inputStreamReader = new InputStreamReader(new FileInputStream(filename)); //NON-NLS + csvParser = CSVFormat.RFC4180.withFirstRecordAsHeader().parse(inputStreamReader); + if( ! csvParser.getHeaderMap().keySet().contains("hash")){ + close(); + throw new TskCoreException("Hashkeeper file format invalid - does not contain 'hash' column"); + } + + // For efficiency, store the index of the hash column + hashColumnIndex = csvParser.getHeaderMap().get("hash"); + + // Make an iterator to loop over the entries + recordIterator = csvParser.getRecords().listIterator(); + + // We're ready to use recordIterator to get each hash + + } catch (IOException ex){ + close(); + throw new TskCoreException("Error reading " + filename, ex); + } + } + + /** + * Get the next hash to import + * + * @return The hash as a string, or null if the end of file was reached + * without error + * @throws TskCoreException + */ + @Override + public String getNextHash() throws TskCoreException { + if(recordIterator.hasNext()){ + CSVRecord record = recordIterator.next(); + String hash = record.get(hashColumnIndex); + + if (hash.length() != 32) { + throw new TskCoreException("Hash has incorrect length: " + hash); + } + + return (hash); + } + return null; + } + + /** + * Check if there are more hashes to read + * + * @return true if we've read all expected hash values, false otherwise + */ + @Override + public boolean doneReading() { + return (! recordIterator.hasNext()); + } + + /** + * Get the expected number of hashes in the file. This number can be an + * estimate. + * + * @return The expected hash count + */ + @Override + public long getExpectedHashCount() { + return expectedHashCount; + } + + /** + * Closes the import file + */ + @Override + public final void close() { + if(inputStreamReader != null){ + try{ + inputStreamReader.close(); + } catch (IOException ex) { + Logger.getLogger(EncaseHashSetParser.class.getName()).log(Level.SEVERE, "Error closing Hashkeeper hash set " + filename, ex); + } finally { + inputStreamReader = null; + } + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java index 0c1b694e1b..815e98e324 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java @@ -28,7 +28,8 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.TskCoreException; /** - * Parser for idx files (*.idx) + * Parser for idx files and md5sum files (*.idx or *.txt) + * This parsers lines that start with md5 hashes and ignores any others */ class IdxHashSetParser implements HashSetParser { @@ -49,6 +50,7 @@ class IdxHashSetParser implements HashSetParser { File importFile = new File(filename); long fileSize = importFile.length(); totalHashes = fileSize / 0x33 + 1; // IDX file lines are generally 0x33 bytes long. We add one to prevent this from being zero + // MD5sum output lines should be close enough to that (0x20 byte hash + filename) } /** @@ -65,14 +67,15 @@ class IdxHashSetParser implements HashSetParser { try { while ((line = reader.readLine()) != null) { - String[] parts = line.split("\\|"); + // idx files have a pipe after the hash, md5sum files should have a space + String[] parts = line.split("\\|| "); - // Header lines start with a 41 character dummy hash, 1 character longer than a SHA-1 hash - if (parts.length != 2 || parts[0].length() == 41) { + String hashStr = parts[0].toLowerCase(); + if(! hashStr.matches("^[0-9a-f]{32}$")){ continue; } - return parts[0].toLowerCase(); + return hashStr; } } catch (IOException ex) { throw new TskCoreException("Error reading file " + filename, ex); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index a2e9522893..0ea2776328 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -213,12 +213,14 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P // Create the hash set parser HashSetParser hashSetParser; - if (importFileName.toLowerCase().endsWith(".idx")) { + if (importFileName.toLowerCase().endsWith(".idx") || importFileName.toLowerCase().endsWith(".txt")) { hashSetParser = new IdxHashSetParser(importFileName); } else if(importFileName.toLowerCase().endsWith(".hash")){ hashSetParser = new EncaseHashSetParser(importFileName); } else if(importFileName.toLowerCase().endsWith(".kdb")){ hashSetParser = new KdbHashSetParser(importFileName); + } else if(importFileName.toLowerCase().endsWith(".hsh")){ + hashSetParser = new HashkeeperHashSetParser(importFileName); } else { // We've gotten here with a format that can't be processed throw new TskCoreException("Hash set to import is an unknown format : " + importFileName); From 05244f6fa146c13c48ae3a2e1a725e9be8954d37 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Mon, 27 Nov 2017 10:09:19 -0500 Subject: [PATCH 64/90] Cleanup --- .../hashdatabase/HashkeeperHashSetParser.java | 37 +++++++++---------- .../hashdatabase/IdxHashSetParser.java | 6 +-- .../ImportCentralRepoDbProgressDialog.java | 8 ++-- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashkeeperHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashkeeperHashSetParser.java index e325bc94da..e66af62eb3 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashkeeperHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashkeeperHashSetParser.java @@ -34,45 +34,44 @@ import org.sleuthkit.datamodel.TskCoreException; * Parser for Hashkeeper hash sets (*.hsh) */ public class HashkeeperHashSetParser implements HashSetParser { - + private String filename; private InputStreamReader inputStreamReader; private CSVParser csvParser; private final long expectedHashCount; // Number of hashes we expect to read from the file private final Iterator recordIterator; private final int hashColumnIndex; // The index of the hash column - + HashkeeperHashSetParser(String filename) throws TskCoreException { this.filename = filename; - - try{ + + try { // Estimate the total number of hashes in the file File importFile = new File(filename); long fileSize = importFile.length(); expectedHashCount = fileSize / 75 + 1; // As a rough estimate, assume 75 bytes per line. We add one to prevent this from being zero - + // Create the parser inputStreamReader = new InputStreamReader(new FileInputStream(filename)); //NON-NLS csvParser = CSVFormat.RFC4180.withFirstRecordAsHeader().parse(inputStreamReader); - if( ! csvParser.getHeaderMap().keySet().contains("hash")){ + if (!csvParser.getHeaderMap().keySet().contains("hash")) { close(); throw new TskCoreException("Hashkeeper file format invalid - does not contain 'hash' column"); } - + // For efficiency, store the index of the hash column hashColumnIndex = csvParser.getHeaderMap().get("hash"); // Make an iterator to loop over the entries recordIterator = csvParser.getRecords().listIterator(); - + // We're ready to use recordIterator to get each hash - - } catch (IOException ex){ + } catch (IOException ex) { close(); throw new TskCoreException("Error reading " + filename, ex); } } - + /** * Get the next hash to import * @@ -82,7 +81,7 @@ public class HashkeeperHashSetParser implements HashSetParser { */ @Override public String getNextHash() throws TskCoreException { - if(recordIterator.hasNext()){ + if (recordIterator.hasNext()) { CSVRecord record = recordIterator.next(); String hash = record.get(hashColumnIndex); @@ -91,7 +90,7 @@ public class HashkeeperHashSetParser implements HashSetParser { } return (hash); - } + } return null; } @@ -102,7 +101,7 @@ public class HashkeeperHashSetParser implements HashSetParser { */ @Override public boolean doneReading() { - return (! recordIterator.hasNext()); + return (!recordIterator.hasNext()); } /** @@ -120,15 +119,15 @@ public class HashkeeperHashSetParser implements HashSetParser { * Closes the import file */ @Override - public final void close() { - if(inputStreamReader != null){ - try{ + public final void close() { + if (inputStreamReader != null) { + try { inputStreamReader.close(); } catch (IOException ex) { - Logger.getLogger(EncaseHashSetParser.class.getName()).log(Level.SEVERE, "Error closing Hashkeeper hash set " + filename, ex); + Logger.getLogger(HashkeeperHashSetParser.class.getName()).log(Level.SEVERE, "Error closing Hashkeeper hash set " + filename, ex); } finally { inputStreamReader = null; - } + } } } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java index 815e98e324..0db5442c0c 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/IdxHashSetParser.java @@ -28,8 +28,8 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.TskCoreException; /** - * Parser for idx files and md5sum files (*.idx or *.txt) - * This parsers lines that start with md5 hashes and ignores any others + * Parser for idx files and md5sum files (*.idx or *.txt) This parsers lines + * that start with md5 hashes and ignores any others */ class IdxHashSetParser implements HashSetParser { @@ -71,7 +71,7 @@ class IdxHashSetParser implements HashSetParser { String[] parts = line.split("\\|| "); String hashStr = parts[0].toLowerCase(); - if(! hashStr.matches("^[0-9a-f]{32}$")){ + if (!hashStr.matches("^[0-9a-f]{32}$")) { continue; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java index 0ea2776328..37d3a20009 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/ImportCentralRepoDbProgressDialog.java @@ -215,12 +215,12 @@ class ImportCentralRepoDbProgressDialog extends javax.swing.JDialog implements P HashSetParser hashSetParser; if (importFileName.toLowerCase().endsWith(".idx") || importFileName.toLowerCase().endsWith(".txt")) { hashSetParser = new IdxHashSetParser(importFileName); - } else if(importFileName.toLowerCase().endsWith(".hash")){ + } else if (importFileName.toLowerCase().endsWith(".hash")) { hashSetParser = new EncaseHashSetParser(importFileName); - } else if(importFileName.toLowerCase().endsWith(".kdb")){ + } else if (importFileName.toLowerCase().endsWith(".kdb")) { hashSetParser = new KdbHashSetParser(importFileName); - } else if(importFileName.toLowerCase().endsWith(".hsh")){ - hashSetParser = new HashkeeperHashSetParser(importFileName); + } else if (importFileName.toLowerCase().endsWith(".hsh")) { + hashSetParser = new HashkeeperHashSetParser(importFileName); } else { // We've gotten here with a format that can't be processed throw new TskCoreException("Hash set to import is an unknown format : " + importFileName); From 06b8b51e51b457c430279706615e26416d6b4149 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 27 Nov 2017 10:20:32 -0500 Subject: [PATCH 65/90] 3203 fix comment to reflect that tag status applies outside of CR --- .../autopsy/casemodule/services/TagNameDefinition.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java index 880354f77b..e1d81d2b65 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/TagNameDefinition.java @@ -107,8 +107,7 @@ final class TagNameDefinition implements Comparable { } /** - * The status which items which have this tag applied to them should have in - * the central repository. + * The status which will be applied to items with this tag. * * @return a value of TskData.FileKnown which is associated with this tag */ From 6487af2f57ea43cc4729b5bf0d068acc522f7b07 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 28 Nov 2017 11:04:47 -0500 Subject: [PATCH 66/90] Add a default organization when the central repo db is created --- .../datamodel/EamDbUtil.java | 45 ++++++++++++++++++- .../datamodel/PostgresEamDbSettings.java | 3 +- .../datamodel/SqliteEamDbSettings.java | 3 +- .../ManageOrganizationsDialog.java | 20 ++++++--- .../HashDbCreateDatabaseDialog.java | 7 ++- .../HashDbImportDatabaseDialog.java | 7 ++- 6 files changed, 72 insertions(+), 13 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDbUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDbUtil.java index 5d70d6fdac..49f49f9d38 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDbUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDbUtil.java @@ -37,6 +37,7 @@ public class EamDbUtil { private final static Logger LOGGER = Logger.getLogger(EamDbUtil.class.getName()); private static final String CENTRAL_REPO_NAME = "CentralRepository"; private static final String CENTRAL_REPO_USE_KEY = "db.useCentralRepo"; + private static final String DEFAULT_ORG_NAME = "Not Specified"; /** * Close the prepared statement. @@ -175,11 +176,51 @@ public class EamDbUtil { return true; } + /** + * Check whether the given org is the default organization. + * + * @param org + * @return true if it is the default org, false otherwise + */ + public static boolean isDefaultOrg(EamOrganization org) { + return DEFAULT_ORG_NAME.equals(org.getName()); + } + + /** + * Add the default organization to the database + * + * @param conn + * @return true if successful, false otherwise + */ + static boolean insertDefaultOrganization(Connection conn) { + if (null == conn) { + return false; + } + + PreparedStatement preparedStatement = null; + String sql = "INSERT INTO organizations(org_name, poc_name, poc_email, poc_phone) VALUES (?, ?, ?, ?)"; + try { + preparedStatement = conn.prepareStatement(sql); + preparedStatement.setString(1, DEFAULT_ORG_NAME); + preparedStatement.setString(2, ""); + preparedStatement.setString(3, ""); + preparedStatement.setString(4, ""); + preparedStatement.executeUpdate(); + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Error adding default organization", ex); + return false; + } finally { + EamDbUtil.closePreparedStatement(preparedStatement); + } + + return true; + } + /** * If the Central Repos use has been enabled. * * @return true if the Central Repo may be configured, false if it should - * not be able to be + * not be able to be */ public static boolean useCentralRepo() { return Boolean.parseBoolean(ModuleSettings.getConfigSetting(CENTRAL_REPO_NAME, CENTRAL_REPO_USE_KEY)); @@ -190,7 +231,7 @@ public class EamDbUtil { * configured. * * @param centralRepoCheckBoxIsSelected - true if the central repo can be - * used + * used */ public static void setUseCentralRepo(boolean centralRepoCheckBoxIsSelected) { ModuleSettings.setConfigSetting(CENTRAL_REPO_NAME, CENTRAL_REPO_USE_KEY, Boolean.toString(centralRepoCheckBoxIsSelected)); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java index bfb3f04b32..324cc2ac7d 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresEamDbSettings.java @@ -485,7 +485,8 @@ public final class PostgresEamDbSettings { } boolean result = EamDbUtil.insertDefaultCorrelationTypes(conn) - && EamDbUtil.insertSchemaVersion(conn); + && EamDbUtil.insertSchemaVersion(conn) + && EamDbUtil.insertDefaultOrganization(conn); EamDbUtil.closeConnection(conn); return result; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java index b4ea1aa8a2..c7a3730e46 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDbSettings.java @@ -434,7 +434,8 @@ public final class SqliteEamDbSettings { } boolean result = EamDbUtil.insertDefaultCorrelationTypes(conn) - && EamDbUtil.insertSchemaVersion(conn); + && EamDbUtil.insertSchemaVersion(conn) + && EamDbUtil.insertDefaultOrganization(conn); EamDbUtil.closeConnection(conn); return result; } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageOrganizationsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageOrganizationsDialog.java index ad6c26e4d8..9055485e2f 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageOrganizationsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/ManageOrganizationsDialog.java @@ -35,6 +35,7 @@ import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil; import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization; import org.sleuthkit.autopsy.coreutils.Logger; @@ -72,7 +73,7 @@ public final class ManageOrganizationsDialog extends JDialog { organizationList.setModel(rulesListModel); organizationList.addListSelectionListener(new OrganizationListSelectionListener()); populateList(); - setButtonsEnabled(organizationList.getSelectedValue() != null); + setButtonsEnabled(organizationList.getSelectedValue()); newOrg = null; } catch (EamDbException ex) { Exceptions.printStackTrace(ex); @@ -421,9 +422,15 @@ public final class ManageOrganizationsDialog extends JDialog { return newOrg; } - private void setButtonsEnabled(boolean isSelected) { - editButton.setEnabled(isSelected); - deleteButton.setEnabled(isSelected); + private void setButtonsEnabled(EamOrganization selectedOrg) { + boolean isSelected = (selectedOrg != null); + boolean isDefaultOrg = false; + if(selectedOrg != null){ + isDefaultOrg = EamDbUtil.isDefaultOrg(selectedOrg); + } + + editButton.setEnabled(isSelected && (! isDefaultOrg)); + deleteButton.setEnabled(isSelected && (! isDefaultOrg)); } /** @@ -436,9 +443,8 @@ public final class ManageOrganizationsDialog extends JDialog { if (e.getValueIsAdjusting()) { return; } - EamOrganization selected = organizationList.getSelectedValue(); - boolean isSelected = (selected != null); - setButtonsEnabled(isSelected); + EamOrganization selected = organizationList.getSelectedValue(); + setButtonsEnabled(selected); if (selected != null) { orgNameTextField.setText(selected.getName()); pocNameTextField.setText(selected.getPocName()); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java index 17a69930a2..13dd9bcd63 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java @@ -33,6 +33,7 @@ import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil; import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization; import org.sleuthkit.autopsy.centralrepository.datamodel.EamGlobalSet; import org.sleuthkit.autopsy.centralrepository.optionspanel.ManageOrganizationsDialog; @@ -154,8 +155,12 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog { orgs = dbManager.getOrganizations(); orgs.forEach((org) -> { orgComboBox.addItem(org.getName()); + if(EamDbUtil.isDefaultOrg(org)){ + orgComboBox.setSelectedItem(org.getName()); + selectedOrg = org; + } }); - if (!orgs.isEmpty()) { + if ((selectedOrg == null) && (!orgs.isEmpty())) { selectedOrg = orgs.get(0); } } catch (EamDbException ex) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index db70d1114d..95f83229b1 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -34,6 +34,7 @@ import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException; +import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbUtil; import org.sleuthkit.autopsy.centralrepository.datamodel.EamOrganization; import org.sleuthkit.autopsy.centralrepository.optionspanel.ManageOrganizationsDialog; import org.sleuthkit.autopsy.coreutils.Logger; @@ -148,8 +149,12 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { orgs = dbManager.getOrganizations(); orgs.forEach((org) -> { orgComboBox.addItem(org.getName()); + if(EamDbUtil.isDefaultOrg(org)){ + orgComboBox.setSelectedItem(org.getName()); + selectedOrg = org; + } }); - if (!orgs.isEmpty()) { + if ((selectedOrg == null) && (!orgs.isEmpty())) { selectedOrg = orgs.get(0); } } catch (EamDbException ex) { From 917fd9048a187614c58ac1135c4d1886629d1cc2 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 28 Nov 2017 14:27:49 -0500 Subject: [PATCH 67/90] Cleanup of import hash dialog --- .../modules/hashdatabase/Bundle.properties | 8 +- .../HashDbImportDatabaseDialog.form | 172 +++++++++--------- .../HashDbImportDatabaseDialog.java | 142 ++++++++------- 3 files changed, 166 insertions(+), 156 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties index 3ec2961927..b3eb5608ae 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties @@ -17,7 +17,7 @@ HashDbSearchPanel.errorField.text=Error: Not all files have been hashed. HashDbSearchPanel.saveBox.text=Remember Hashes HashDbSearchPanel.cancelButton.text=Cancel OpenIDE-Module-Short-Description=Hash Database Ingest Module and hash db tools -HashDbImportDatabaseDialog.jLabel1.text=Hash Set Name: +HashDbImportDatabaseDialog.jLabel1.text=Name: HashDbImportDatabaseDialog.databasePathTextField.text= HashDbImportDatabaseDialog.knownBadRadioButton.text=Notable HashDbImportDatabaseDialog.jLabel2.text=Type of database\: @@ -230,9 +230,9 @@ HashDbImportDatabaseDialog.lbOrg.text=Source Organization: HashDbImportDatabaseDialog.readOnlyCheckbox.text=Make database read-only HashDbImportDatabaseDialog.orgButton.text=Manage Organizations HashDbImportDatabaseDialog.versionTextField.text= -HashDbImportDatabaseDialog.fileTypeRadioButton.text=File -HashDbImportDatabaseDialog.centralRepoRadioButton.text=Central Repository -HashDbImportDatabaseDialog.jLabel4.text=Location: +HashDbImportDatabaseDialog.fileTypeRadioButton.text=Local +HashDbImportDatabaseDialog.centralRepoRadioButton.text=Remote (Central Repository) +HashDbImportDatabaseDialog.jLabel4.text=Destination: HashDbCreateDatabaseDialog.jLabel4.text=Location: HashDbCreateDatabaseDialog.fileTypeRadioButton.text=File HashDbCreateDatabaseDialog.centralRepoRadioButton.text=Central Repository diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form index 682ec13c34..69601b784b 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form @@ -33,64 +33,63 @@ - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - + + - + + + + + + @@ -99,51 +98,58 @@ - - - - - - - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index db70d1114d..f84d17bd46 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -303,50 +303,50 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGap(0, 325, Short.MAX_VALUE) - .addComponent(okButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cancelButton)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel2) + .addGroup(layout.createSequentialGroup() + .addGap(19, 19, 19) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(knownRadioButton) + .addComponent(knownBadRadioButton))) + .addComponent(sendIngestMessagesCheckbox) + .addComponent(readOnlyCheckbox)) + .addGap(177, 177, 177)) .addGroup(layout.createSequentialGroup() .addComponent(lbOrg) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(orgComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(orgButton)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel1) - .addComponent(lbVersion)) - .addGap(2, 2, 2) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(versionTextField) - .addComponent(hashSetNameTextField))) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel3) - .addComponent(jLabel4)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(fileTypeRadioButton) - .addGap(26, 26, 26) - .addComponent(centralRepoRadioButton)) - .addComponent(databasePathTextField)))) + .addComponent(orgButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED))) + .addComponent(okButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(openButton)) + .addComponent(cancelButton)) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel2) + .addComponent(jLabel3) + .addComponent(jLabel4)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGap(19, 19, 19) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(knownRadioButton) - .addComponent(knownBadRadioButton))) - .addComponent(sendIngestMessagesCheckbox) - .addComponent(readOnlyCheckbox)) - .addGap(0, 0, Short.MAX_VALUE))) + .addComponent(fileTypeRadioButton) + .addGap(26, 26, 26) + .addComponent(centralRepoRadioButton)) + .addComponent(databasePathTextField)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(openButton)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1) + .addComponent(lbVersion)) + .addGap(40, 40, 40) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(versionTextField) + .addComponent(hashSetNameTextField)) + .addGap(142, 142, 142))) .addContainerGap()) ); @@ -354,45 +354,49 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createSequentialGroup() .addContainerGap() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(fileTypeRadioButton) - .addComponent(centralRepoRadioButton) - .addComponent(jLabel4)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(openButton) .addComponent(databasePathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jLabel3)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(jLabel1) - .addComponent(hashSetNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(versionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lbVersion)) - .addGap(9, 9, 9) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(orgButton) - .addComponent(orgComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lbOrg)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jLabel2) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(knownRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(knownBadRadioButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(readOnlyCheckbox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(sendIngestMessagesCheckbox) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(okButton) - .addComponent(cancelButton)) - .addContainerGap()) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(okButton) + .addComponent(cancelButton)) + .addContainerGap()) + .addGroup(layout.createSequentialGroup() + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(fileTypeRadioButton) + .addComponent(centralRepoRadioButton) + .addComponent(jLabel4)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1) + .addComponent(hashSetNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(lbVersion) + .addComponent(versionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(5, 5, 5) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(orgButton) + .addComponent(orgComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lbOrg)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(knownRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(knownBadRadioButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(readOnlyCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(sendIngestMessagesCheckbox) + .addContainerGap(32, Short.MAX_VALUE)))) ); pack(); From ce5f0fb4ffc0ee8f8db10d67511b7bfab9471831 Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Tue, 28 Nov 2017 14:49:33 -0500 Subject: [PATCH 68/90] Updated the new database panel and main options panel --- .../modules/hashdatabase/Bundle.properties | 12 +- .../HashDbImportDatabaseDialog.form | 111 +++++++++--------- .../HashDbImportDatabaseDialog.java | 95 +++++++-------- .../hashdatabase/HashLookupSettingsPanel.form | 41 +++---- .../hashdatabase/HashLookupSettingsPanel.java | 36 +++--- 5 files changed, 149 insertions(+), 146 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties index b3eb5608ae..7e4b10fc5d 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties @@ -39,7 +39,7 @@ HashDbCreateDatabaseDialog.sendIngestMessagesCheckbox.text=Send ingest inbox mes HashDbImportDatabaseDialog.sendIngestMessagesCheckbox.text=Send ingest inbox message for each hit HashDbImportDatabaseDialog.hashSetNameTextField.text= HashDbImportDatabaseDialog.openButton.text=Open... -HashDbCreateDatabaseDialog.jLabel3.text=Hash Set Name: +HashDbCreateDatabaseDialog.jLabel3.text=Name: HashDbCreateDatabaseDialog.okButton.text=OK HashDbCreateDatabaseDialog.databasePathTextField.text= AddContentToHashDbAction.ContentMenu.noHashDbsConfigd=No hash databases configured @@ -205,7 +205,7 @@ HashLookupSettingsPanel.typeLabel.text=Type: HashLookupSettingsPanel.locationLabel.text=Database Path: HashLookupSettingsPanel.hashDbLocationLabel.text=No database selected HashLookupSettingsPanel.hashDbNameLabel.text=No database selected -HashLookupSettingsPanel.nameLabel.text=Hash Set Name: +HashLookupSettingsPanel.nameLabel.text=Name: HashLookupSettingsPanel.hashDatabasesLabel.text=Hash Databases: HashLookupSettingsPanel.importDatabaseButton.toolTipText= HashLookupSettingsPanel.importDatabaseButton.text=Import database @@ -229,13 +229,13 @@ HashDbImportDatabaseDialog.lbVersion.text=Version: HashDbImportDatabaseDialog.lbOrg.text=Source Organization: HashDbImportDatabaseDialog.readOnlyCheckbox.text=Make database read-only HashDbImportDatabaseDialog.orgButton.text=Manage Organizations -HashDbImportDatabaseDialog.versionTextField.text= +HashDbImportDatabaseDialog.versionTextField.text=1.0 HashDbImportDatabaseDialog.fileTypeRadioButton.text=Local HashDbImportDatabaseDialog.centralRepoRadioButton.text=Remote (Central Repository) HashDbImportDatabaseDialog.jLabel4.text=Destination: -HashDbCreateDatabaseDialog.jLabel4.text=Location: -HashDbCreateDatabaseDialog.fileTypeRadioButton.text=File -HashDbCreateDatabaseDialog.centralRepoRadioButton.text=Central Repository +HashDbCreateDatabaseDialog.jLabel4.text=Destination: +HashDbCreateDatabaseDialog.fileTypeRadioButton.text=Local +HashDbCreateDatabaseDialog.centralRepoRadioButton.text=Remote (Central Repository) HashDbCreateDatabaseDialog.lbOrg.text=Source Organization: HashDbCreateDatabaseDialog.orgButton.text=Manage Organizations HashDbCreateDatabaseDialog.databasePathLabel.text=Database Path: diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form index 69601b784b..dbb9f7b4e3 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form @@ -32,36 +32,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -73,26 +43,61 @@ + + + + + + + - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + - + - @@ -101,21 +106,13 @@ - + + - - - - - - - - - @@ -147,9 +144,17 @@ - + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index f84d17bd46..2c43be75ee 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -302,29 +302,6 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel2) - .addGroup(layout.createSequentialGroup() - .addGap(19, 19, 19) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(knownRadioButton) - .addComponent(knownBadRadioButton))) - .addComponent(sendIngestMessagesCheckbox) - .addComponent(readOnlyCheckbox)) - .addGap(177, 177, 177)) - .addGroup(layout.createSequentialGroup() - .addComponent(lbOrg) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(orgComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(orgButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED))) - .addComponent(okButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(cancelButton)) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel3) @@ -334,20 +311,46 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { .addGroup(layout.createSequentialGroup() .addComponent(fileTypeRadioButton) .addGap(26, 26, 26) - .addComponent(centralRepoRadioButton)) - .addComponent(databasePathTextField)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(openButton)) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(centralRepoRadioButton) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(databasePathTextField) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(openButton) + .addContainerGap()))) + .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel1) - .addComponent(lbVersion)) - .addGap(40, 40, 40) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addComponent(versionTextField) - .addComponent(hashSetNameTextField)) - .addGap(142, 142, 142))) - .addContainerGap()) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(sendIngestMessagesCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(okButton)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addComponent(lbOrg) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(orgComboBox, 0, 121, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(orgButton)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1) + .addComponent(lbVersion)) + .addGap(40, 40, 40) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(versionTextField) + .addComponent(hashSetNameTextField)))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(cancelButton) + .addContainerGap()) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel2) + .addComponent(readOnlyCheckbox) + .addGroup(layout.createSequentialGroup() + .addGap(19, 19, 19) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(knownRadioButton) + .addComponent(knownBadRadioButton)))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) ); layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {cancelButton, okButton}); @@ -357,18 +360,12 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(openButton) .addComponent(databasePathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(jLabel3)) + .addComponent(jLabel3) + .addComponent(openButton)) + .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(okButton) - .addComponent(cancelButton)) - .addContainerGap()) - .addGroup(layout.createSequentialGroup() - .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(fileTypeRadioButton) .addComponent(centralRepoRadioButton) @@ -396,7 +393,13 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog { .addComponent(readOnlyCheckbox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(sendIngestMessagesCheckbox) - .addContainerGap(32, Short.MAX_VALUE)))) + .addGap(0, 21, Short.MAX_VALUE)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(cancelButton) + .addComponent(okButton)))) + .addContainerGap()) ); pack(); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.form index 5be552d274..d32cbf57d7 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.form @@ -105,28 +105,6 @@ - - - - - - - - - - - - - - - - - - - - - - @@ -143,6 +121,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java index b774ad83c8..1adb75594d 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java @@ -787,24 +787,6 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan .addGroup(jPanel1Layout.createSequentialGroup() .addGap(10, 10, 10) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(locationLabel) - .addComponent(typeLabel) - .addComponent(versionLabel) - .addComponent(orgLabel) - .addComponent(readOnlyLabel)) - .addGap(55, 55, 55) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(hashDbTypeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 225, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(hashDbLocationLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 225, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(hashDbVersionLabel) - .addComponent(hashDbOrgLabel) - .addComponent(hashDbReadOnlyLabel))) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(nameLabel) - .addGap(53, 53, 53) - .addComponent(hashDbNameLabel)) .addGroup(jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(indexLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 66, javax.swing.GroupLayout.PREFERRED_SIZE) @@ -816,7 +798,23 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(indexButton, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(10, 10, 10) - .addComponent(addHashesToDatabaseButton)))) + .addComponent(addHashesToDatabaseButton)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(locationLabel) + .addComponent(typeLabel) + .addComponent(versionLabel) + .addComponent(orgLabel) + .addComponent(readOnlyLabel) + .addComponent(nameLabel)) + .addGap(55, 55, 55) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(hashDbNameLabel) + .addComponent(hashDbTypeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 225, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(hashDbLocationLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 225, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(hashDbVersionLabel) + .addComponent(hashDbOrgLabel) + .addComponent(hashDbReadOnlyLabel))))) .addGroup(jPanel1Layout.createSequentialGroup() .addGap(70, 70, 70) .addComponent(informationSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 305, javax.swing.GroupLayout.PREFERRED_SIZE)) From a6d312663c4bc4cd598efe730aac6c8bd9b384ed Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 28 Nov 2017 15:44:31 -0500 Subject: [PATCH 69/90] 3158 Agency Logo preview now present in options panel --- .../corecomponents/AutopsyOptionsPanel.form | 543 ++++++++++-------- .../corecomponents/AutopsyOptionsPanel.java | 332 +++++++---- .../autopsy/corecomponents/Bundle.properties | 3 +- 3 files changed, 539 insertions(+), 339 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form index 06607d7d9b..2e618379e4 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form @@ -22,12 +22,18 @@ - + + + + - + + + + @@ -46,247 +52,336 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - + - - - - - - - - + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 4f95087f66..4862846b13 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -18,9 +18,18 @@ */ package org.sleuthkit.autopsy.corecomponents; +import java.awt.image.BufferedImage; import java.io.File; +import java.io.IOException; +import java.util.logging.Level; +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; import javax.swing.JFileChooser; +import javax.swing.JOptionPane; import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.GeneralFilter; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.ModuleSettings; @@ -29,16 +38,23 @@ import org.sleuthkit.autopsy.report.ReportBranding; /** * Options panel that allow users to set application preferences. */ +@Messages({"AutopsyOptionsPanel.agencyLogoPreview.text=
No logo
selected
", + "AutopsyOptionsPanel.logoPanel.border.title=Logo", + "AutopsyOptionsPanel.viewPanel.border.title=View", + "AutopsyOptionsPanel.invalidImageFile.msg=The selected file was not able to be used as an agency logo.", + "AutopsyOptionsPanel.invalidImageFile.title=Invalid Image File"}) final class AutopsyOptionsPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; private final JFileChooser fc; + private static final Logger logger = Logger.getLogger(AutopsyOptionsPanel.class.getName()); AutopsyOptionsPanel() { initComponents(); fc = new JFileChooser(); fc.setFileSelectionMode(JFileChooser.FILES_ONLY); fc.setMultiSelectionEnabled(false); + fc.setAcceptAllFileFilterUsed(false); fc.setFileFilter(new GeneralFilter(GeneralFilter.GRAPHIC_IMAGE_EXTS, GeneralFilter.GRAPHIC_IMG_DECR)); } @@ -53,7 +69,28 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { boolean useLocalTime = UserPreferences.displayTimesInLocalTime(); useLocalTimeRB.setSelected(useLocalTime); useGMTTimeRB.setSelected(!useLocalTime); - agencyLogoPathField.setText(ModuleSettings.getConfigSetting(ReportBranding.MODULE_NAME, ReportBranding.AGENCY_LOGO_PATH_PROP)); + String path = ModuleSettings.getConfigSetting(ReportBranding.MODULE_NAME, ReportBranding.AGENCY_LOGO_PATH_PROP); + try { + updateAgencyLogo(path); + } catch (IOException ex) { + logger.log(Level.WARNING, "Error loading image from previously saved agency logo path", ex); + } + } + + private void updateAgencyLogo(String path) throws IOException { + agencyLogoPathField.setText(path); + ImageIcon agencyLogoIcon = new ImageIcon(); + agencyLogoPreview.setText(Bundle.AutopsyOptionsPanel_agencyLogoPreview_text()); + if (!agencyLogoPathField.getText().isEmpty()) { + File file = new File(agencyLogoPathField.getText()); + if (file.exists()) { + BufferedImage image = ImageIO.read(file); //create it as an image first to support BMP files + agencyLogoIcon = new ImageIcon(image.getScaledInstance(64, 64, 4)); + agencyLogoPreview.setText(""); + } + } + agencyLogoPreview.setIcon(agencyLogoIcon); + agencyLogoPreview.repaint(); } void store() { @@ -64,8 +101,8 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { UserPreferences.setHideSlackFilesInViewsTree(viewsHideSlackCB.isSelected()); UserPreferences.setDisplayTimesInLocalTime(useLocalTimeRB.isSelected()); if (!agencyLogoPathField.getText().isEmpty()) { - File image = new File(agencyLogoPathField.getText()); - if (image.exists()) { + File file = new File(agencyLogoPathField.getText()); + if (file.exists()) { ModuleSettings.setConfigSetting(ReportBranding.MODULE_NAME, ReportBranding.AGENCY_LOGO_PATH_PROP, agencyLogoPathField.getText()); } } @@ -87,24 +124,87 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { buttonGroup3 = new javax.swing.ButtonGroup(); jScrollPane1 = new javax.swing.JScrollPane(); jPanel1 = new javax.swing.JPanel(); - useBestViewerRB = new javax.swing.JRadioButton(); - keepCurrentViewerRB = new javax.swing.JRadioButton(); - jLabelSelectFile = new javax.swing.JLabel(); - jLabelTimeDisplay = new javax.swing.JLabel(); - useLocalTimeRB = new javax.swing.JRadioButton(); - useGMTTimeRB = new javax.swing.JRadioButton(); - jLabelHideKnownFiles = new javax.swing.JLabel(); - dataSourcesHideKnownCB = new javax.swing.JCheckBox(); - viewsHideKnownCB = new javax.swing.JCheckBox(); - dataSourcesHideSlackCB = new javax.swing.JCheckBox(); - viewsHideSlackCB = new javax.swing.JCheckBox(); - jLabelHideSlackFiles = new javax.swing.JLabel(); + logoPanel = new javax.swing.JPanel(); agencyLogoImageLabel = new javax.swing.JLabel(); agencyLogoPathField = new javax.swing.JTextField(); browseLogosButton = new javax.swing.JButton(); + agencyLogoPreview = new javax.swing.JLabel(); + viewPanel = new javax.swing.JPanel(); + jLabelSelectFile = new javax.swing.JLabel(); + useBestViewerRB = new javax.swing.JRadioButton(); + keepCurrentViewerRB = new javax.swing.JRadioButton(); + jLabelHideKnownFiles = new javax.swing.JLabel(); + dataSourcesHideKnownCB = new javax.swing.JCheckBox(); + viewsHideKnownCB = new javax.swing.JCheckBox(); + jLabelHideSlackFiles = new javax.swing.JLabel(); + dataSourcesHideSlackCB = new javax.swing.JCheckBox(); + viewsHideSlackCB = new javax.swing.JCheckBox(); + jLabelTimeDisplay = new javax.swing.JLabel(); + useLocalTimeRB = new javax.swing.JRadioButton(); + useGMTTimeRB = new javax.swing.JRadioButton(); jScrollPane1.setBorder(null); + logoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.logoPanel.border.title"))); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(agencyLogoImageLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.agencyLogoImageLabel.text")); // NOI18N + + agencyLogoPathField.setEditable(false); + agencyLogoPathField.setBackground(new java.awt.Color(255, 255, 255)); + agencyLogoPathField.setText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.agencyLogoPathField.text")); // NOI18N + agencyLogoPathField.setFocusable(false); + agencyLogoPathField.setRequestFocusEnabled(false); + + org.openide.awt.Mnemonics.setLocalizedText(browseLogosButton, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.browseLogosButton.text")); // NOI18N + browseLogosButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + browseLogosButtonActionPerformed(evt); + } + }); + + agencyLogoPreview.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + org.openide.awt.Mnemonics.setLocalizedText(agencyLogoPreview, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.agencyLogoPreview.text")); // NOI18N + agencyLogoPreview.setBorder(javax.swing.BorderFactory.createEtchedBorder()); + agencyLogoPreview.setMaximumSize(new java.awt.Dimension(64, 64)); + agencyLogoPreview.setMinimumSize(new java.awt.Dimension(64, 64)); + agencyLogoPreview.setPreferredSize(new java.awt.Dimension(64, 64)); + + javax.swing.GroupLayout logoPanelLayout = new javax.swing.GroupLayout(logoPanel); + logoPanel.setLayout(logoPanelLayout); + logoPanelLayout.setHorizontalGroup( + logoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, logoPanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(logoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(agencyLogoImageLabel) + .addGroup(logoPanelLayout.createSequentialGroup() + .addGap(10, 10, 10) + .addComponent(agencyLogoPathField, javax.swing.GroupLayout.PREFERRED_SIZE, 259, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(browseLogosButton))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(agencyLogoPreview, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(149, Short.MAX_VALUE)) + ); + logoPanelLayout.setVerticalGroup( + logoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(logoPanelLayout.createSequentialGroup() + .addGroup(logoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(agencyLogoPreview, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(logoPanelLayout.createSequentialGroup() + .addContainerGap() + .addComponent(agencyLogoImageLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(logoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(agencyLogoPathField) + .addComponent(browseLogosButton)))) + .addGap(0, 0, 0)) + ); + + viewPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.viewPanel.border.title"))); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jLabelSelectFile, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelSelectFile.text")); // NOI18N + buttonGroup1.add(useBestViewerRB); org.openide.awt.Mnemonics.setLocalizedText(useBestViewerRB, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.useBestViewerRB.text")); // NOI18N useBestViewerRB.setToolTipText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.useBestViewerRB.toolTipText")); // NOI18N @@ -123,7 +223,37 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } }); - org.openide.awt.Mnemonics.setLocalizedText(jLabelSelectFile, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelSelectFile.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jLabelHideKnownFiles, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelHideKnownFiles.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(dataSourcesHideKnownCB, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.dataSourcesHideKnownCB.text")); // NOI18N + dataSourcesHideKnownCB.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + dataSourcesHideKnownCBActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(viewsHideKnownCB, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.viewsHideKnownCB.text")); // NOI18N + viewsHideKnownCB.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + viewsHideKnownCBActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(jLabelHideSlackFiles, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelHideSlackFiles.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(dataSourcesHideSlackCB, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.dataSourcesHideSlackCB.text")); // NOI18N + dataSourcesHideSlackCB.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + dataSourcesHideSlackCBActionPerformed(evt); + } + }); + + org.openide.awt.Mnemonics.setLocalizedText(viewsHideSlackCB, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.viewsHideSlackCB.text")); // NOI18N + viewsHideSlackCB.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + viewsHideSlackCBActionPerformed(evt); + } + }); org.openide.awt.Mnemonics.setLocalizedText(jLabelTimeDisplay, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelTimeDisplay.text")); // NOI18N @@ -143,93 +273,34 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } }); - org.openide.awt.Mnemonics.setLocalizedText(jLabelHideKnownFiles, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelHideKnownFiles.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(dataSourcesHideKnownCB, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.dataSourcesHideKnownCB.text")); // NOI18N - dataSourcesHideKnownCB.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - dataSourcesHideKnownCBActionPerformed(evt); - } - }); - - org.openide.awt.Mnemonics.setLocalizedText(viewsHideKnownCB, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.viewsHideKnownCB.text")); // NOI18N - viewsHideKnownCB.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - viewsHideKnownCBActionPerformed(evt); - } - }); - - org.openide.awt.Mnemonics.setLocalizedText(dataSourcesHideSlackCB, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.dataSourcesHideSlackCB.text")); // NOI18N - dataSourcesHideSlackCB.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - dataSourcesHideSlackCBActionPerformed(evt); - } - }); - - org.openide.awt.Mnemonics.setLocalizedText(viewsHideSlackCB, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.viewsHideSlackCB.text")); // NOI18N - viewsHideSlackCB.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - viewsHideSlackCBActionPerformed(evt); - } - }); - - org.openide.awt.Mnemonics.setLocalizedText(jLabelHideSlackFiles, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelHideSlackFiles.text")); // NOI18N - - org.openide.awt.Mnemonics.setLocalizedText(agencyLogoImageLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.agencyLogoImageLabel.text")); // NOI18N - - agencyLogoPathField.setEditable(false); - agencyLogoPathField.setBackground(new java.awt.Color(255, 255, 255)); - agencyLogoPathField.setText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.agencyLogoPathField.text")); // NOI18N - agencyLogoPathField.setFocusable(false); - agencyLogoPathField.setRequestFocusEnabled(false); - - org.openide.awt.Mnemonics.setLocalizedText(browseLogosButton, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.browseLogosButton.text")); // NOI18N - browseLogosButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - browseLogosButtonActionPerformed(evt); - } - }); - - javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); - jPanel1.setLayout(jPanel1Layout); - jPanel1Layout.setHorizontalGroup( - jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() + javax.swing.GroupLayout viewPanelLayout = new javax.swing.GroupLayout(viewPanel); + viewPanel.setLayout(viewPanelLayout); + viewPanelLayout.setHorizontalGroup( + viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, viewPanelLayout.createSequentialGroup() .addContainerGap() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabelTimeDisplay) - .addComponent(jLabelHideKnownFiles) - .addComponent(jLabelSelectFile) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(10, 10, 10) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(useLocalTimeRB) - .addComponent(useGMTTimeRB) - .addComponent(keepCurrentViewerRB) - .addComponent(useBestViewerRB) - .addComponent(dataSourcesHideKnownCB) - .addComponent(viewsHideKnownCB)))) - .addContainerGap(140, Short.MAX_VALUE)) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabelHideSlackFiles) - .addComponent(agencyLogoImageLabel) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(10, 10, 10) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addComponent(agencyLogoPathField, javax.swing.GroupLayout.PREFERRED_SIZE, 259, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(browseLogosButton)) - .addComponent(dataSourcesHideSlackCB) - .addComponent(viewsHideSlackCB)))) - .addGap(0, 0, Short.MAX_VALUE)))) + .addGroup(viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(viewPanelLayout.createSequentialGroup() + .addGap(10, 10, 10) + .addGroup(viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(useGMTTimeRB) + .addComponent(keepCurrentViewerRB) + .addComponent(useBestViewerRB) + .addGroup(viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(useLocalTimeRB) + .addComponent(dataSourcesHideSlackCB) + .addComponent(viewsHideSlackCB) + .addComponent(dataSourcesHideKnownCB) + .addComponent(viewsHideKnownCB)))) + .addComponent(jLabelHideSlackFiles) + .addComponent(jLabelTimeDisplay) + .addComponent(jLabelHideKnownFiles) + .addComponent(jLabelSelectFile)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); - jPanel1Layout.setVerticalGroup( - jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() + viewPanelLayout.setVerticalGroup( + viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, viewPanelLayout.createSequentialGroup() .addContainerGap() .addComponent(jLabelSelectFile) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -253,14 +324,28 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(useLocalTimeRB) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(useGMTTimeRB) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(agencyLogoImageLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(agencyLogoPathField) - .addComponent(browseLogosButton)) - .addGap(35, 35, 35)) + .addComponent(useGMTTimeRB)) + ); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(viewPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(logoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(viewPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(logoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0)) ); jScrollPane1.setViewportView(jPanel1); @@ -269,11 +354,15 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(layout.createSequentialGroup() + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 672, Short.MAX_VALUE) + .addGap(0, 0, 0)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane1) + .addGroup(layout.createSequentialGroup() + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 489, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -310,17 +399,32 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { }//GEN-LAST:event_viewsHideSlackCBActionPerformed private void browseLogosButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseLogosButtonActionPerformed + String oldLogoPath = agencyLogoPathField.getText(); int returnState = fc.showOpenDialog(this); if (returnState == JFileChooser.APPROVE_OPTION) { String path = fc.getSelectedFile().getPath(); - agencyLogoPathField.setText(path); - firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + try { + updateAgencyLogo(path); + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + } catch (IOException | IndexOutOfBoundsException ex) { + JOptionPane.showMessageDialog(null, + NbBundle.getMessage(this.getClass(), + "AutopsyOptionsPanel.invalidImageFile.msg"), + NbBundle.getMessage(this.getClass(), "AutopsyOptionsPanel.invalidImageFile.title"), + JOptionPane.ERROR_MESSAGE); + try { + updateAgencyLogo(oldLogoPath); //restore previous setting if new one is invalid + } catch (IOException ex1) { + logger.log(Level.WARNING, "Error loading image from previously saved agency logo path", ex1); + } + } } }//GEN-LAST:event_browseLogosButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel agencyLogoImageLabel; private javax.swing.JTextField agencyLogoPathField; + private javax.swing.JLabel agencyLogoPreview; private javax.swing.JButton browseLogosButton; private javax.swing.ButtonGroup buttonGroup1; private javax.swing.ButtonGroup buttonGroup3; @@ -333,9 +437,11 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private javax.swing.JPanel jPanel1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JRadioButton keepCurrentViewerRB; + private javax.swing.JPanel logoPanel; private javax.swing.JRadioButton useBestViewerRB; private javax.swing.JRadioButton useGMTTimeRB; private javax.swing.JRadioButton useLocalTimeRB; + private javax.swing.JPanel viewPanel; private javax.swing.JCheckBox viewsHideKnownCB; private javax.swing.JCheckBox viewsHideSlackCB; // End of variables declaration//GEN-END:variables diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties index 5ac6cbd626..26a2cc03e0 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties @@ -1,7 +1,7 @@ CTL_DataContentAction=DataContent CTL_DataContentTopComponent=Data Content CTL_CustomAboutAction=About -OptionsCategory_Name_General=View +OptionsCategory_Name_General=Application OptionsCategory_Keywords_General=Autopsy Options HINT_DataContentTopComponent=This is a DataContent window HINT_NodeTableTopComponent=This is a DataResult window @@ -198,7 +198,6 @@ AutopsyOptionsPanel.agencyLogoPathField.text= SortChooserDialog.label=remove SortChooser.addCriteriaButton.text=Add Sort Criteria DataResultViewerThumbnail.sortButton.text=Sort - CriterionChooser.ascendingRadio.text=\u25b2 Ascending\n CriterionChooser.removeButton.text=Remove CriterionChooser.descendingRadio.text=\u25bc Descending From 3d306b31baa5966db98acd6ecaacd572a7d0edc2 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 28 Nov 2017 16:30:32 -0500 Subject: [PATCH 70/90] 3158 fix NPE when some invalid image files are tried as agency logo --- .../sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 4862846b13..435bdc99b4 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -85,6 +85,9 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { File file = new File(agencyLogoPathField.getText()); if (file.exists()) { BufferedImage image = ImageIO.read(file); //create it as an image first to support BMP files + if (image == null) { + throw new IOException("Unable to read file as a BufferedImage for file " + file.toString()); + } agencyLogoIcon = new ImageIcon(image.getScaledInstance(64, 64, 4)); agencyLogoPreview.setText(""); } From 2d9c20b90c8753200db3139afab8d85b73db0535 Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 29 Nov 2017 12:39:36 -0500 Subject: [PATCH 71/90] Modified EmbeddedFileExtractor to use Tika for OOXML files. FileTypeDetector needed to be updated to use TikaInputStream because a new version of Apache Compress was pulled in with tika-parsers. --- Core/ivy.xml | 1 + Core/nbproject/project.properties | 8 +- Core/nbproject/project.xml | 149 +++--- .../EmbeddedFileExtractorIngestModule.java | 12 +- ... => MSOfficeEmbeddedContentExtractor.java} | 499 ++++++++---------- .../modules/filetypeid/FileTypeDetector.java | 22 +- 6 files changed, 315 insertions(+), 376 deletions(-) rename Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/{ImageExtractor.java => MSOfficeEmbeddedContentExtractor.java} (58%) diff --git a/Core/ivy.xml b/Core/ivy.xml index b6cfe4a568..eea67feb19 100755 --- a/Core/ivy.xml +++ b/Core/ivy.xml @@ -16,6 +16,7 @@ + diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties index 8868378570..7c36c61db7 100755 --- a/Core/nbproject/project.properties +++ b/Core/nbproject/project.properties @@ -1,10 +1,13 @@ file.reference.activemq-all-5.11.1.jar=release/modules/ext/activemq-all-5.11.1.jar file.reference.c3p0-0.9.5.jar=release/modules/ext/c3p0-0.9.5.jar +file.reference.commons-compress-1.12.jar=release/modules/ext/commons-compress-1.12.jar +file.reference.commons-dbcp2-2.1.1.jar=release\\modules\\ext\\commons-dbcp2-2.1.1.jar +file.reference.commons-pool2-2.4.2.jar=release\\modules\\ext\\commons-pool2-2.4.2.jar file.reference.jdom-2.0.5-contrib.jar=release/modules/ext/jdom-2.0.5-contrib.jar file.reference.jdom-2.0.5.jar=release/modules/ext/jdom-2.0.5.jar file.reference.jython-standalone-2.7.0.jar=release/modules/ext/jython-standalone-2.7.0.jar file.reference.mchange-commons-java-0.2.9.jar=release/modules/ext/mchange-commons-java-0.2.9.jar -file.reference.metadata-extractor-2.8.1.jar=release/modules/ext/metadata-extractor-2.8.1.jar +file.reference.metadata-extractor-2.9.1.jar=release/modules/ext/metadata-extractor-2.9.1.jar file.reference.postgresql-9.4.1211.jre7.jar=release/modules/ext/postgresql-9.4.1211.jre7.jar file.reference.opencv-248.jar=release/modules/ext/opencv-248.jar file.reference.Rejistry-1.0-SNAPSHOT.jar=release/modules/ext/Rejistry-1.0-SNAPSHOT.jar @@ -13,6 +16,7 @@ file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar file.reference.sqlite-jdbc-3.8.11.jar=release/modules/ext/sqlite-jdbc-3.8.11.jar file.reference.StixLib.jar=release/modules/ext/StixLib.jar file.reference.tika-core-1.14.jar=release/modules/ext/tika-core-1.14.jar +file.reference.tika-parsers-1.14.jar=release/modules/ext/tika-parsers-1.14.jar file.reference.Tsk_DataModel_PostgreSQL.jar=release/modules/ext/Tsk_DataModel_PostgreSQL.jar file.reference.xmpcore-5.1.2.jar=release/modules/ext/xmpcore-5.1.2.jar file.reference.curator-client-2.8.0.jar=release/modules/ext/curator-client-2.8.0.jar @@ -21,12 +25,10 @@ file.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8 file.reference.zookeeper-3.4.6.jar=release/modules/ext/zookeeper-3.4.6.jar javac.source=1.8 javac.compilerargs=-Xlint -Xlint:-serial -javadoc.reference.metadata-extractor-2.8.1.jar=release/modules/ext/metadata-extractor-2.8.1-src.zip license.file=../LICENSE-2.0.txt nbm.homepage=http://www.sleuthkit.org/ nbm.module.author=Brian Carrier nbm.needs.restart=true -source.reference.metadata-extractor-2.8.1.jar=release/modules/ext/metadata-extractor-2.8.1-src.zip!/Source/ source.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0-sources.jar spec.version.base=10.9 diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 0e6b98892f..525e6da6a7 100755 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -307,7 +307,6 @@ org.sleuthkit.autopsy.datasourceprocessors org.sleuthkit.autopsy.directorytree org.sleuthkit.autopsy.events - org.sleuthkit.autopsy.externalresults org.sleuthkit.autopsy.filesearch org.sleuthkit.autopsy.guiutils org.sleuthkit.autopsy.ingest @@ -321,93 +320,25 @@ org.sleuthkit.autopsy.report org.sleuthkit.datamodel + + ext/zookeeper-3.4.6.jar + release/modules/ext/zookeeper-3.4.6.jar + ext/jdom-2.0.5.jar release/modules/ext/jdom-2.0.5.jar - - ext/postgresql-9.4.1211.jre7.jar - release/modules/ext/postgresql-9.4.1211.jre7.jar - - - ext/mchange-commons-java-0.2.9.jar - release/modules/ext/mchange-commons-java-0.2.9.jar - - - ext/c3p0-0.9.5.jar - release/modules/ext/c3p0-0.9.5.jar - - - ext/xmpcore-5.1.2.jar - release/modules/ext/xmpcore-5.1.2.jar - - - ext/StixLib.jar - release/modules/ext/StixLib.jar - - - ext/sqlite-jdbc-3.8.11.jar - release/modules/ext/sqlite-jdbc-3.8.11.jar - - - ext/opencv-248.jar - release/modules/ext/opencv-248.jar - - - ext/Rejistry-1.0-SNAPSHOT.jar - release/modules/ext/Rejistry-1.0-SNAPSHOT.jar - - - ext/activemq-all-5.11.1.jar - release/modules/ext/activemq-all-5.11.1.jar - - - ext/Rejistry-1.0-SNAPSHOT.jar - release/modules/ext/Rejistry-1.0-SNAPSHOT.jar - - - ext/jython-standalone-2.7.0.jar - release/modules/ext/jython-standalone-2.7.0.jar - - - ext/sevenzipjbinding.jar - release/modules/ext/sevenzipjbinding.jar - - - ext/sevenzipjbinding-AllPlatforms.jar - release/modules/ext/sevenzipjbinding-AllPlatforms.jar - ext/tika-core-1.14.jar release/modules/ext/tika-core-1.14.jar - - ext/metadata-extractor-2.8.1.jar - release/modules/ext/metadata-extractor-2.8.1.jar - - - ext/metadata-extractor-2.8.1.jar - release/modules/ext/metadata-extractor-2.8.1.jar - - - ext/jdom-2.0.5-contrib.jar - release/modules/ext/jdom-2.0.5-contrib.jar - ext/Tsk_DataModel_PostgreSQL.jar release/modules/ext/Tsk_DataModel_PostgreSQL.jar - ext/zookeeper-3.4.6.jar - release/modules/ext/zookeeper-3.4.6.jar - - - ext/curator-client-2.8.0.jar - release/modules/ext/curator-client-2.8.0.jar - - - ext/curator-recipes-2.8.0.jar - release/modules/ext/curator-recipes-2.8.0.jar + ext/opencv-248.jar + release/modules/ext/opencv-248.jar ext/curator-framework-2.8.0.jar @@ -417,10 +348,78 @@ ext/commons-dbcp2-2.1.1.jar release\modules\ext\commons-dbcp2-2.1.1.jar + + ext/tika-parsers-1.14.jar + release/modules/ext/tika-parsers-1.14.jar + + + ext/jython-standalone-2.7.0.jar + release/modules/ext/jython-standalone-2.7.0.jar + + + ext/sevenzipjbinding.jar + release/modules/ext/sevenzipjbinding.jar + + + ext/mchange-commons-java-0.2.9.jar + release/modules/ext/mchange-commons-java-0.2.9.jar + + + ext/postgresql-9.4.1211.jre7.jar + release/modules/ext/postgresql-9.4.1211.jre7.jar + + + ext/curator-recipes-2.8.0.jar + release/modules/ext/curator-recipes-2.8.0.jar + + + ext/xmpcore-5.1.2.jar + release/modules/ext/xmpcore-5.1.2.jar + + + ext/StixLib.jar + release/modules/ext/StixLib.jar + + + ext/curator-client-2.8.0.jar + release/modules/ext/curator-client-2.8.0.jar + + + ext/sqlite-jdbc-3.8.11.jar + release/modules/ext/sqlite-jdbc-3.8.11.jar + + + ext/activemq-all-5.11.1.jar + release/modules/ext/activemq-all-5.11.1.jar + + + ext/Rejistry-1.0-SNAPSHOT.jar + release/modules/ext/Rejistry-1.0-SNAPSHOT.jar + + + ext/sevenzipjbinding-AllPlatforms.jar + release/modules/ext/sevenzipjbinding-AllPlatforms.jar + ext/commons-pool2-2.4.2.jar release\modules\ext\commons-pool2-2.4.2.jar + + ext/metadata-extractor-2.9.1.jar + release/modules/ext/metadata-extractor-2.9.1.jar + + + ext/commons-compress-1.12.jar + release/modules/ext/commons-compress-1.12.jar + + + ext/jdom-2.0.5-contrib.jar + release/modules/ext/jdom-2.0.5-contrib.jar + + + ext/c3p0-0.9.5.jar + release/modules/ext/c3p0-0.9.5.jar + diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java index 7d4328da59..7a9d9b04ef 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/EmbeddedFileExtractorIngestModule.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2013-2017 Basis Technology Corp. + * Copyright 2015 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -44,7 +44,7 @@ public final class EmbeddedFileExtractorIngestModule extends FileIngestModuleAda static final String[] SUPPORTED_EXTENSIONS = {"zip", "rar", "arj", "7z", "7zip", "gzip", "gz", "bzip2", "tar", "tgz",}; // "iso"}; NON-NLS private String moduleDirRelative; private String moduleDirAbsolute; - private ImageExtractor imageExtractor; + private MSOfficeEmbeddedContentExtractor officeExtractor; private SevenZipExtractor archiveExtractor; private FileTypeDetector fileTypeDetector; @@ -98,10 +98,10 @@ public final class EmbeddedFileExtractorIngestModule extends FileIngestModuleAda } /* - * Construct an embedded images extractor for processing Microsoft + * Construct an embedded content extractor for processing Microsoft * Office documents. */ - this.imageExtractor = new ImageExtractor(context, fileTypeDetector, moduleDirRelative, moduleDirAbsolute); + this.officeExtractor = new MSOfficeEmbeddedContentExtractor(context, fileTypeDetector, moduleDirRelative, moduleDirAbsolute); } @Override @@ -134,8 +134,8 @@ public final class EmbeddedFileExtractorIngestModule extends FileIngestModuleAda */ if (archiveExtractor.isSevenZipExtractionSupported(abstractFile)) { archiveExtractor.unpack(abstractFile); - } else if (imageExtractor.isImageExtractionSupported(abstractFile)) { - imageExtractor.extractImage(abstractFile); + } else if (officeExtractor.isContentExtractionSupported(abstractFile)) { + officeExtractor.extractEmbeddedContent(abstractFile); } return ProcessResult.OK; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/MSOfficeEmbeddedContentExtractor.java similarity index 58% rename from Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java rename to Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/MSOfficeEmbeddedContentExtractor.java index d58d935e97..668b8cfcdf 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/ImageExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/MSOfficeEmbeddedContentExtractor.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2015 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,14 +21,16 @@ package org.sleuthkit.autopsy.modules.embeddedfileextractor; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.lang.IllegalArgumentException; -import java.lang.IndexOutOfBoundsException; -import java.lang.NullPointerException; +import java.io.InputStream; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.logging.Level; -import org.apache.poi.POIXMLException; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; import org.apache.poi.hwpf.usermodel.Picture; import org.apache.poi.hslf.usermodel.HSLFPictureData; import org.apache.poi.hslf.usermodel.HSLFSlideShow; @@ -39,11 +41,18 @@ import org.apache.poi.hwpf.model.PicturesTable; import org.apache.poi.sl.usermodel.PictureData.PictureType; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.util.RecordFormatException; -import org.apache.poi.xslf.usermodel.XMLSlideShow; -import org.apache.poi.xslf.usermodel.XSLFPictureData; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.apache.poi.xwpf.usermodel.XWPFDocument; -import org.apache.poi.xwpf.usermodel.XWPFPictureData; +import org.apache.tika.config.TikaConfig; +import org.apache.tika.detect.Detector; +import org.apache.tika.exception.TikaException; +import org.apache.tika.extractor.EmbeddedDocumentExtractor; +import org.apache.tika.extractor.ParsingEmbeddedDocumentExtractor; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.mime.MediaType; +import org.apache.tika.mime.MimeTypeException; +import org.apache.tika.parser.AutoDetectParser; +import org.apache.tika.parser.ParseContext; +import org.apache.tika.parser.Parser; +import org.apache.tika.sax.BodyContentHandler; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.FileManager; @@ -57,24 +66,34 @@ import org.sleuthkit.datamodel.EncodedFileOutputStream; import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; -class ImageExtractor { +/** + * Extracts embedded content (e.g. images, audio, video) from Microsoft Office + * documents (both original and OOXML forms). + */ +class MSOfficeEmbeddedContentExtractor { private final FileManager fileManager; private final IngestServices services; - private static final Logger logger = Logger.getLogger(ImageExtractor.class.getName()); + private static final Logger LOGGER = Logger.getLogger(MSOfficeEmbeddedContentExtractor.class.getName()); private final IngestJobContext context; private String parentFileName; - private final String UNKNOWN_NAME_PREFIX = "image_"; //NON-NLS + private final String UNKNOWN_IMAGE_NAME_PREFIX = "image_"; //NON-NLS private final FileTypeDetector fileTypeDetector; private String moduleDirRelative; private String moduleDirAbsolute; + private AutoDetectParser parser = new AutoDetectParser(); + private Detector detector = parser.getDetector(); + private TikaConfig config = TikaConfig.getDefaultConfig(); + /** - * Enum of mimetypes which support image extraction + * Enum of mimetypes for which we can extract embedded content. */ - enum SupportedImageExtractionFormats { + enum SupportedExtractionFormats { DOC("application/msword"), //NON-NLS DOCX("application/vnd.openxmlformats-officedocument.wordprocessingml.document"), //NON-NLS @@ -85,7 +104,7 @@ class ImageExtractor { private final String mimeType; - SupportedImageExtractionFormats(final String mimeType) { + SupportedExtractionFormats(final String mimeType) { this.mimeType = mimeType; } @@ -93,11 +112,10 @@ class ImageExtractor { public String toString() { return this.mimeType; } - // TODO Expand to support more formats } - private SupportedImageExtractionFormats abstractFileExtractionFormat; + private SupportedExtractionFormats abstractFileExtractionFormat; - ImageExtractor(IngestJobContext context, FileTypeDetector fileTypeDetector, String moduleDirRelative, String moduleDirAbsolute) { + MSOfficeEmbeddedContentExtractor(IngestJobContext context, FileTypeDetector fileTypeDetector, String moduleDirRelative, String moduleDirAbsolute) { this.fileManager = Case.getCurrentCase().getServices().getFileManager(); this.services = IngestServices.getInstance(); @@ -111,15 +129,15 @@ class ImageExtractor { * This method returns true if the file format is currently supported. Else * it returns false. Performs only Apache Tika based detection. * - * @param abstractFile The AbstractFilw whose mimetype is to be determined. + * @param abstractFile The AbstractFile whose mimetype is to be determined. * * @return This method returns true if the file format is currently * supported. Else it returns false. */ - boolean isImageExtractionSupported(AbstractFile abstractFile) { + boolean isContentExtractionSupported(AbstractFile abstractFile) { try { String abstractFileMimeType = fileTypeDetector.getFileType(abstractFile); - for (SupportedImageExtractionFormats s : SupportedImageExtractionFormats.values()) { + for (SupportedExtractionFormats s : SupportedExtractionFormats.values()) { if (s.toString().equals(abstractFileMimeType)) { abstractFileExtractionFormat = s; return true; @@ -127,60 +145,55 @@ class ImageExtractor { } return false; } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error executing FileTypeDetector.getFileType()", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Error executing FileTypeDetector.getFileType()", ex); // NON-NLS return false; } } /** - * This method selects the appropriate process of extracting images from - * files using POI classes. Once the images have been extracted, the method - * adds them to the DB and fires a ModuleContentEvent. ModuleContent Event - * is not fired if the no images were extracted from the processed file. + * This method selects the appropriate process of extracting embedded + * content from files using either Tika or POI classes. Once the content has + * been extracted as files, the method adds them to the DB and fires a + * ModuleContentEvent. ModuleContent Event is not fired if no content + * was extracted from the processed file. * - * @param format * @param abstractFile The abstract file to be processed. */ - void extractImage(AbstractFile abstractFile) { - // - // switchcase for different supported formats - // process abstractFile according to the format by calling appropriate methods. - - List listOfExtractedImages = null; + void extractEmbeddedContent(AbstractFile abstractFile) { + List listOfExtractedImages = null; List listOfExtractedImageAbstractFiles = null; this.parentFileName = EmbeddedFileExtractorIngestModule.getUniqueName(abstractFile); - //check if already has derived files, skip + + // Skip files that already have been unpacked. try { if (abstractFile.hasChildren()) { //check if local unpacked dir exists if (new File(getOutputFolderPath(parentFileName)).exists()) { - logger.log(Level.INFO, "File already has been processed as it has children and local unpacked file, skipping: {0}", abstractFile.getName()); //NON-NLS + LOGGER.log(Level.INFO, "File already has been processed as it has children and local unpacked file, skipping: {0}", abstractFile.getName()); //NON-NLS return; } } } catch (TskCoreException e) { - logger.log(Level.SEVERE, String.format("Error checking if file already has been processed, skipping: %s", parentFileName), e); //NON-NLS + LOGGER.log(Level.SEVERE, String.format("Error checking if file already has been processed, skipping: %s", parentFileName), e); //NON-NLS return; } + + // Call the appropriate extraction method based on mime type switch (abstractFileExtractionFormat) { - case DOC: - listOfExtractedImages = extractImagesFromDoc(abstractFile); - break; case DOCX: - listOfExtractedImages = extractImagesFromDocx(abstractFile); + case PPTX: + case XLSX: + listOfExtractedImages = extractEmbeddedContentFromOOXML(abstractFile); + break; + case DOC: + listOfExtractedImages = extractEmbeddedImagesFromDoc(abstractFile); break; case PPT: - listOfExtractedImages = extractImagesFromPpt(abstractFile); - break; - case PPTX: - listOfExtractedImages = extractImagesFromPptx(abstractFile); + listOfExtractedImages = extractEmbeddedImagesFromPpt(abstractFile); break; case XLS: listOfExtractedImages = extractImagesFromXls(abstractFile); break; - case XLSX: - listOfExtractedImages = extractImagesFromXlsx(abstractFile); - break; default: break; } @@ -190,13 +203,13 @@ class ImageExtractor { } // the common task of adding abstractFile to derivedfiles is performed. listOfExtractedImageAbstractFiles = new ArrayList<>(); - for (ExtractedImage extractedImage : listOfExtractedImages) { + for (ExtractedFile extractedImage : listOfExtractedImages) { try { listOfExtractedImageAbstractFiles.add(fileManager.addDerivedFile(extractedImage.getFileName(), extractedImage.getLocalPath(), extractedImage.getSize(), extractedImage.getCtime(), extractedImage.getCrtime(), extractedImage.getAtime(), extractedImage.getAtime(), true, abstractFile, null, EmbeddedFileExtractorModuleFactory.getModuleName(), null, null, TskData.EncodingType.XOR1)); } catch (TskCoreException ex) { - logger.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.extractImage.addToDB.exception.msg"), ex); //NON-NLS + LOGGER.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.extractImage.addToDB.exception.msg"), ex); //NON-NLS } } if (!listOfExtractedImages.isEmpty()) { @@ -206,43 +219,79 @@ class ImageExtractor { } /** - * Extract images from doc format files. + * Extracts embedded content from OOXML documents (i.e. pptx, docx and xlsx) + * using Tika. This will extract images and other multimedia content + * embedded in the given file. + * + * @param abstractFile The file to extract content from. + * + * @return A list of extracted files. + */ + private List extractEmbeddedContentFromOOXML(AbstractFile abstractFile) { + Metadata metadata = new Metadata(); + + ParseContext parseContext = new ParseContext(); + parseContext.set(Parser.class, parser); + + // Passing -1 to the BodyContentHandler constructor disables the Tika + // write limit (which defaults to 100,000 characters. + ContentHandler contentHandler = new BodyContentHandler(-1); + + // TODO: this will be needed once we upgrade to Tika 1.16 or later. + // OfficeParserConfig officeParserConfig = new OfficeParserConfig(); + // officeParserConfig.setUseSAXPptxExtractor(true); + // officeParserConfig.setUseSAXDocxExtractor(true); + // parseContext.set(OfficeParserConfig.class, officeParserConfig); + EmbeddedDocumentExtractor extractor = new EmbeddedContentExtractor(parseContext); + parseContext.set(EmbeddedDocumentExtractor.class, extractor); + ReadContentInputStream stream = new ReadContentInputStream(abstractFile); + + try { + parser.parse(stream, contentHandler, metadata, parseContext); + } catch (IOException | SAXException | TikaException ex) { + LOGGER.log(Level.WARNING, "Error while parsing file, skipping: " + abstractFile.getName(), ex); //NON-NLS + return null; + } + + return ((EmbeddedContentExtractor) extractor).getExtractedImages(); + } + + /** + * Extract embedded images from doc format files. * * @param af the file from which images are to be extracted. * * @return list of extracted images. Returns null in case no images were * extracted. */ - private List extractImagesFromDoc(AbstractFile af) { + private List extractEmbeddedImagesFromDoc(AbstractFile af) { List listOfAllPictures; - + try { HWPFDocument doc = new HWPFDocument(new ReadContentInputStream(af)); PicturesTable pictureTable = doc.getPicturesTable(); listOfAllPictures = pictureTable.getAllPictures(); - } catch (IOException | IllegalArgumentException | - IndexOutOfBoundsException | NullPointerException ex) { + } catch (IOException | IllegalArgumentException + | IndexOutOfBoundsException | NullPointerException ex) { // IOException: // Thrown when the document has issues being read. - + // IllegalArgumentException: // This will catch OldFileFormatException, which is thrown when the // document's format is Word 95 or older. Alternatively, this is // thrown when attempting to load an RTF file as a DOC file. // However, our code verifies the file format before ever running it - // through the ImageExtractor. This exception gets thrown in the + // through the EmbeddedContentExtractor. This exception gets thrown in the // "IN10-0137.E01" image regardless. The reason is unknown. - // IndexOutOfBoundsException: // NullPointerException: // These get thrown in certain images. The reason is unknown. It is // likely due to problems with the file formats that POI is poorly // handling. - return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions - logger.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.docContainer.init.err", af.getName()), ex); //NON-NLS + LOGGER.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.docContainer.init.err", af.getName()), ex); //NON-NLS return null; } @@ -255,7 +304,7 @@ class ImageExtractor { if (outputFolderPath == null) { return null; } - List listOfExtractedImages = new ArrayList<>(); + List listOfExtractedImages = new ArrayList<>(); byte[] data = null; for (Picture picture : listOfAllPictures) { String fileName = picture.suggestFullFileName(); @@ -266,99 +315,43 @@ class ImageExtractor { } writeExtractedImage(Paths.get(outputFolderPath, fileName).toString(), data); // TODO Extract more info from the Picture viz ctime, crtime, atime, mtime - listOfExtractedImages.add(new ExtractedImage(fileName, getFileRelativePath(fileName), picture.getSize(), af)); + listOfExtractedImages.add(new ExtractedFile(fileName, getFileRelativePath(fileName), picture.getSize())); } return listOfExtractedImages; } /** - * Extract images from docx format files. + * Extract embedded images from ppt format files. * * @param af the file from which images are to be extracted. * * @return list of extracted images. Returns null in case no images were * extracted. */ - private List extractImagesFromDocx(AbstractFile af) { - List listOfAllPictures = null; - - try { - XWPFDocument docx = new XWPFDocument(new ReadContentInputStream(af)); - listOfAllPictures = docx.getAllPictures(); - } catch (POIXMLException | IOException ex) { - // POIXMLException: - // Thrown when document fails to load - - // IOException: - // Thrown when the document has issues being read. - - return null; - } catch (Throwable ex) { - // instantiating POI containers throw RuntimeExceptions - logger.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.docxContainer.init.err", af.getName()), ex); //NON-NLS - return null; - } - - // if no images are extracted from the PPT, return null, else initialize - // the output folder for image extraction. - String outputFolderPath; - if (listOfAllPictures.isEmpty()) { - return null; - } else { - outputFolderPath = getOutputFolderPath(this.parentFileName); - } - if (outputFolderPath == null) { - return null; - } - List listOfExtractedImages = new ArrayList<>(); - byte[] data = null; - for (XWPFPictureData xwpfPicture : listOfAllPictures) { - String fileName = xwpfPicture.getFileName(); - try { - data = xwpfPicture.getData(); - } catch (Exception ex) { - return null; - } - writeExtractedImage(Paths.get(outputFolderPath, fileName).toString(), data); - listOfExtractedImages.add(new ExtractedImage(fileName, getFileRelativePath(fileName), xwpfPicture.getData().length, af)); - } - return listOfExtractedImages; - } - - /** - * Extract images from ppt format files. - * - * @param af the file from which images are to be extracted. - * - * @return list of extracted images. Returns null in case no images were - * extracted. - */ - private List extractImagesFromPpt(AbstractFile af) { + private List extractEmbeddedImagesFromPpt(AbstractFile af) { List listOfAllPictures = null; - + try { HSLFSlideShow ppt = new HSLFSlideShow(new ReadContentInputStream(af)); listOfAllPictures = ppt.getPictureData(); - } catch (IOException | IllegalArgumentException | - IndexOutOfBoundsException ex) { + } catch (IOException | IllegalArgumentException + | IndexOutOfBoundsException ex) { // IllegalArgumentException: // This will catch OldFileFormatException, which is thrown when the // document version is unsupported. The IllegalArgumentException may // also get thrown for unknown reasons. - + // IOException: // Thrown when the document has issues being read. - // IndexOutOfBoundsException: // This gets thrown in certain images. The reason is unknown. It is // likely due to problems with the file formats that POI is poorly // handling. - return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions - logger.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.pptContainer.init.err", af.getName()), ex); //NON-NLS + LOGGER.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.pptContainer.init.err", af.getName()), ex); //NON-NLS return null; } @@ -374,10 +367,10 @@ class ImageExtractor { return null; } - // extract the images to the above initialized outputFolder. + // extract the content to the above initialized outputFolder. // extraction path - outputFolder/image_number.ext int i = 0; - List listOfExtractedImages = new ArrayList<>(); + List listOfExtractedImages = new ArrayList<>(); byte[] data = null; for (HSLFPictureData pictureData : listOfAllPictures) { @@ -404,80 +397,19 @@ class ImageExtractor { default: continue; } - String imageName = UNKNOWN_NAME_PREFIX + i + ext; //NON-NLS + String imageName = UNKNOWN_IMAGE_NAME_PREFIX + i + ext; //NON-NLS try { data = pictureData.getData(); } catch (Exception ex) { return null; } writeExtractedImage(Paths.get(outputFolderPath, imageName).toString(), data); - listOfExtractedImages.add(new ExtractedImage(imageName, getFileRelativePath(imageName), pictureData.getData().length, af)); + listOfExtractedImages.add(new ExtractedFile(imageName, getFileRelativePath(imageName), pictureData.getData().length)); i++; } return listOfExtractedImages; } - /** - * Extract images from pptx format files. - * - * @param af the file from which images are to be extracted. - * - * @return list of extracted images. Returns null in case no images were - * extracted. - */ - private List extractImagesFromPptx(AbstractFile af) { - List listOfAllPictures = null; - - try { - XMLSlideShow pptx = new XMLSlideShow(new ReadContentInputStream(af)); - listOfAllPictures = pptx.getPictureData(); - } catch (POIXMLException | IOException ex) { - // POIXMLException: - // Thrown when document fails to load. - - // IOException: - // Thrown when the document has issues being read - - return null; - } catch (Throwable ex) { - // instantiating POI containers throw RuntimeExceptions - logger.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.pptxContainer.init.err", af.getName()), ex); //NON-NLS - return null; - } - - // if no images are extracted from the PPT, return null, else initialize - // the output folder for image extraction. - String outputFolderPath; - if (listOfAllPictures.isEmpty()) { - return null; - } else { - outputFolderPath = getOutputFolderPath(this.parentFileName); - } - if (outputFolderPath == null) { - return null; - } - - List listOfExtractedImages = new ArrayList<>(); - byte[] data = null; - for (XSLFPictureData xslsPicture : listOfAllPictures) { - - // get image file name, write it to the module outputFolder, and add - // it to the listOfExtractedImageAbstractFiles. - String fileName = xslsPicture.getFileName(); - try { - data = xslsPicture.getData(); - } catch (Exception ex) { - return null; - } - writeExtractedImage(Paths.get(outputFolderPath, fileName).toString(), data); - listOfExtractedImages.add(new ExtractedImage(fileName, getFileRelativePath(fileName), xslsPicture.getData().length, af)); - - } - - return listOfExtractedImages; - - } - /** * Extract images from xls format files. * @@ -486,41 +418,37 @@ class ImageExtractor { * @return list of extracted images. Returns null in case no images were * extracted. */ - private List extractImagesFromXls(AbstractFile af) { + private List extractImagesFromXls(AbstractFile af) { List listOfAllPictures = null; - + try { Workbook xls = new HSSFWorkbook(new ReadContentInputStream(af)); listOfAllPictures = xls.getAllPictures(); - } catch (IOException | LeftoverDataException | - RecordFormatException | IllegalArgumentException | - IndexOutOfBoundsException ex) { + } catch (IOException | LeftoverDataException + | RecordFormatException | IllegalArgumentException + | IndexOutOfBoundsException ex) { // IllegalArgumentException: // This will catch OldFileFormatException, which is thrown when the // document version is unsupported. The IllegalArgumentException may // also get thrown for unknown reasons. - + // IOException: // Thrown when the document has issues being read. - // LeftoverDataException: // This is thrown for poorly formatted files that have more data // than expected. - // RecordFormatException: // This is thrown for poorly formatted files that have less data // that expected. - // IllegalArgumentException: // IndexOutOfBoundsException: // These get thrown in certain images. The reason is unknown. It is // likely due to problems with the file formats that POI is poorly // handling. - return null; } catch (Throwable ex) { // instantiating POI containers throw RuntimeExceptions - logger.log(Level.SEVERE, String.format("%s%s", NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.xlsContainer.init.err", af.getName()), af.getName()), ex); //NON-NLS + LOGGER.log(Level.SEVERE, String.format("%s%s", NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.xlsContainer.init.err", af.getName()), af.getName()), ex); //NON-NLS return null; } @@ -537,75 +465,17 @@ class ImageExtractor { } int i = 0; - List listOfExtractedImages = new ArrayList<>(); + List listOfExtractedImages = new ArrayList<>(); byte[] data = null; for (org.apache.poi.ss.usermodel.PictureData pictureData : listOfAllPictures) { - String imageName = UNKNOWN_NAME_PREFIX + i + "." + pictureData.suggestFileExtension(); //NON-NLS + String imageName = UNKNOWN_IMAGE_NAME_PREFIX + i + "." + pictureData.suggestFileExtension(); //NON-NLS try { data = pictureData.getData(); } catch (Exception ex) { return null; } writeExtractedImage(Paths.get(outputFolderPath, imageName).toString(), data); - listOfExtractedImages.add(new ExtractedImage(imageName, getFileRelativePath(imageName), pictureData.getData().length, af)); - i++; - } - return listOfExtractedImages; - - } - - /** - * Extract images from xlsx format files. - * - * @param af the file from which images are to be extracted. - * - * @return list of extracted images. Returns null in case no images were - * extracted. - */ - private List extractImagesFromXlsx(AbstractFile af) { - List listOfAllPictures = null; - - try { - Workbook xlsx = new XSSFWorkbook(new ReadContentInputStream(af)); - listOfAllPictures = xlsx.getAllPictures(); - } catch (POIXMLException | IOException ex) { - // POIXMLException: - // Thrown when document fails to load. - - // IOException: - // Thrown when the document has issues being read - - return null; - } catch (Throwable ex) { - // instantiating POI containers throw RuntimeExceptions - logger.log(Level.SEVERE, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.xlsxContainer.init.err", af.getName()), ex); //NON-NLS - return null; - } - - // if no images are extracted from the PPT, return null, else initialize - // the output folder for image extraction. - String outputFolderPath; - if (listOfAllPictures.isEmpty()) { - return null; - } else { - outputFolderPath = getOutputFolderPath(this.parentFileName); - } - if (outputFolderPath == null) { - return null; - } - - int i = 0; - List listOfExtractedImages = new ArrayList<>(); - byte[] data = null; - for (org.apache.poi.ss.usermodel.PictureData pictureData : listOfAllPictures) { - String imageName = UNKNOWN_NAME_PREFIX + i + "." + pictureData.suggestFileExtension(); - try { - data = pictureData.getData(); - } catch (Exception ex) { - return null; - } - writeExtractedImage(Paths.get(outputFolderPath, imageName).toString(), data); - listOfExtractedImages.add(new ExtractedImage(imageName, getFileRelativePath(imageName), pictureData.getData().length, af)); + listOfExtractedImages.add(new ExtractedFile(imageName, getFileRelativePath(imageName), pictureData.getData().length)); i++; } return listOfExtractedImages; @@ -623,18 +493,17 @@ class ImageExtractor { try (EncodedFileOutputStream fos = new EncodedFileOutputStream(new FileOutputStream(outputPath), TskData.EncodingType.XOR1)) { fos.write(data); } catch (IOException ex) { - logger.log(Level.WARNING, "Could not write to the provided location: " + outputPath, ex); //NON-NLS + LOGGER.log(Level.WARNING, "Could not write to the provided location: " + outputPath, ex); //NON-NLS } } /** - * Gets path to the output folder for image extraction. If the path does not + * Gets path to the output folder for file extraction. If the path does not * exist, it is created. * - * @param parentFileName name of the abstract file being processed for image - * extraction. + * @param parentFileName name of the abstract file being processed * - * @return path to the image extraction folder for a given abstract file. + * @return path to the file extraction folder for a given abstract file. */ private String getOutputFolderPath(String parentFileName) { String outputFolderPath = moduleDirAbsolute + File.separator + parentFileName; @@ -643,7 +512,7 @@ class ImageExtractor { try { outputFilePath.mkdirs(); } catch (SecurityException ex) { - logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.getOutputFolderPath.exception.msg", parentFileName), ex); + LOGGER.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "EmbeddedFileExtractorIngestModule.ImageExtractor.getOutputFolderPath.exception.msg", parentFileName), ex); return null; } } @@ -665,11 +534,11 @@ class ImageExtractor { } /** - * Represents the image extracted using POI methods. Currently, POI is not - * capable of extracting ctime, crtime, mtime, and atime; these values are - * set to 0. + * Represents a file extracted using either Tika or POI methods. Currently, + * POI is not capable of extracting ctime, crtime, mtime, and atime; these + * values are set to 0. */ - private static class ExtractedImage { + private static class ExtractedFile { //String fileName, String localPath, long size, long ctime, long crtime, //long atime, long mtime, boolean isFile, AbstractFile parentFile, String rederiveDetails, String toolName, String toolVersion, String otherDetails @@ -680,13 +549,12 @@ class ImageExtractor { private final long crtime; private final long atime; private final long mtime; - private final AbstractFile parentFile; - ExtractedImage(String fileName, String localPath, long size, AbstractFile parentFile) { - this(fileName, localPath, size, 0, 0, 0, 0, parentFile); + ExtractedFile(String fileName, String localPath, long size) { + this(fileName, localPath, size, 0, 0, 0, 0); } - ExtractedImage(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, AbstractFile parentFile) { + ExtractedFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime) { this.fileName = fileName; this.localPath = localPath; this.size = size; @@ -694,7 +562,6 @@ class ImageExtractor { this.crtime = crtime; this.atime = atime; this.mtime = mtime; - this.parentFile = parentFile; } public String getFileName() { @@ -724,9 +591,83 @@ class ImageExtractor { public long getMtime() { return mtime; } + } - public AbstractFile getParentFile() { - return parentFile; + /** + * Our custom embedded content extractor for OOXML files. We pass an + * instance of this class to Tika and Tika calls the parseEmbedded() method + * when it encounters an embedded file. + */ + private class EmbeddedContentExtractor extends ParsingEmbeddedDocumentExtractor { + + private int fileCount = 0; + // Map of file name to ExtractedFile instance. This can revert to a + // plain old list after we upgrade to Tika 1.16 or above. + private final Map nameToExtractedFileMap = new HashMap<>(); + + public EmbeddedContentExtractor(ParseContext context) { + super(context); + } + + @Override + public boolean shouldParseEmbedded(Metadata metadata) { + return true; + } + + @Override + public void parseEmbedded(InputStream stream, ContentHandler handler, + Metadata metadata, boolean outputHtml) throws SAXException, IOException { + + // Get the mime type for the embedded document + MediaType contentType = detector.detect(stream, metadata); + + if (!contentType.getType().equalsIgnoreCase("image") //NON-NLS + && !contentType.getType().equalsIgnoreCase("video") //NON-NLS + && !contentType.getType().equalsIgnoreCase("application") //NON-NLS + && !contentType.getType().equalsIgnoreCase("audio")) { //NON-NLS + return; + } + + // try to get the name of the embedded file from the metadata + String name = metadata.get(Metadata.RESOURCE_NAME_KEY); + + // TODO: This can be removed after we upgrade to Tika 1.16 or + // above. The 1.16 version of Tika keeps track of files that + // have been seen before. + if (nameToExtractedFileMap.containsKey(name)) { + return; + } + + if (name == null) { + name = UNKNOWN_IMAGE_NAME_PREFIX + fileCount++; + } else { + //make sure to select only the file name (not any directory paths + //that might be included in the name) and make sure + //to normalize the name + name = FilenameUtils.normalize(FilenameUtils.getName(name)); + } + + // Get the suggested extension based on mime type. + if (name.indexOf('.') == -1) { + try { + name += config.getMimeRepository().forName(contentType.toString()).getExtension(); + } catch (MimeTypeException ex) { + LOGGER.log(Level.WARNING, "Failed to get suggested extension for the following type: " + contentType.toString(), ex); //NON-NLS + } + } + + File extractedFile = new File(Paths.get(getOutputFolderPath(parentFileName), name).toString()); + writeExtractedImage(extractedFile.getAbsolutePath(), IOUtils.toByteArray(stream)); + nameToExtractedFileMap.put(name, new ExtractedFile(name, getFileRelativePath(name), FileUtils.sizeOf(extractedFile))); + } + + /** + * Get list of extracted files. + * + * @return List of extracted files. + */ + public List getExtractedImages() { + return new ArrayList<>(nameToExtractedFileMap.values()); } } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java index 4bfbb8b734..b1aff14a8f 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java +++ b/Core/src/org/sleuthkit/autopsy/modules/filetypeid/FileTypeDetector.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.modules.filetypeid; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -27,7 +28,9 @@ import java.util.TreeSet; import java.util.logging.Level; import java.util.stream.Collectors; import org.apache.tika.Tika; +import org.apache.tika.io.TikaInputStream; import org.apache.tika.mime.MimeTypes; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.Blackboard; @@ -36,6 +39,7 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; @@ -50,8 +54,6 @@ public class FileTypeDetector { private static final Logger logger = Logger.getLogger(FileTypeDetector.class.getName()); private static final Tika tika = new Tika(); - private static final int BUFFER_SIZE = 64 * 1024; - private final byte buffer[] = new byte[BUFFER_SIZE]; private final List userDefinedFileTypes; private final List autopsyDefinedFileTypes; private static SortedSet tikaDetectedTypes; @@ -270,17 +272,11 @@ public class FileTypeDetector { * bytes to Tika. */ if (null == mimeType) { - try { - byte buf[]; - int len = file.read(buffer, 0, BUFFER_SIZE); - if (len < BUFFER_SIZE) { - buf = new byte[len]; - System.arraycopy(buffer, 0, buf, 0, len); - } else { - buf = buffer; - } - String tikaType = tika.detect(buf, file.getName()); - + ReadContentInputStream stream = new ReadContentInputStream(file); + + try (TikaInputStream tikaInputStream = TikaInputStream.get(stream)) { + String tikaType = tika.detect(tikaInputStream, file.getName()); + /* * Remove the Tika suffix from the MIME type name. */ From f495a42db8862aa5dd023635f60f2cb248674cd4 Mon Sep 17 00:00:00 2001 From: esaunders Date: Wed, 29 Nov 2017 14:29:12 -0500 Subject: [PATCH 72/90] Fix for extracted file sizes. --- .../MSOfficeEmbeddedContentExtractor.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/MSOfficeEmbeddedContentExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/MSOfficeEmbeddedContentExtractor.java index 668b8cfcdf..61376d31f1 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/MSOfficeEmbeddedContentExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/MSOfficeEmbeddedContentExtractor.java @@ -657,8 +657,9 @@ class MSOfficeEmbeddedContentExtractor { } File extractedFile = new File(Paths.get(getOutputFolderPath(parentFileName), name).toString()); - writeExtractedImage(extractedFile.getAbsolutePath(), IOUtils.toByteArray(stream)); - nameToExtractedFileMap.put(name, new ExtractedFile(name, getFileRelativePath(name), FileUtils.sizeOf(extractedFile))); + byte[] fileData = IOUtils.toByteArray(stream); + writeExtractedImage(extractedFile.getAbsolutePath(), fileData); + nameToExtractedFileMap.put(name, new ExtractedFile(name, getFileRelativePath(name), fileData.length)); } /** From 77cf4a0ebb930b93af74e5e8777167c454835512 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 29 Nov 2017 16:34:18 -0500 Subject: [PATCH 73/90] Encryption Detection settings panel implemented. --- .../encryptiondetection/Bundle.properties | 7 + .../EncryptionDetectionFileIngestModule.java | 57 ++++-- .../EncryptionDetectionIngestJobSettings.java | 133 ++++++++++++ ...yptionDetectionIngestJobSettingsPanel.form | 119 +++++++++++ ...yptionDetectionIngestJobSettingsPanel.java | 193 ++++++++++++++++++ .../EncryptionDetectionModuleFactory.java | 57 +++++- 6 files changed, 539 insertions(+), 27 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/Bundle.properties create mode 100755 Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettings.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form create mode 100755 Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/Bundle.properties new file mode 100755 index 0000000000..3d8238e173 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/Bundle.properties @@ -0,0 +1,7 @@ +EncryptionDetectionIngestJobSettingsPanel.minimumEntropyLabel.text=Minimum Entropy: +EncryptionDetectionIngestJobSettingsPanel.minimumFileSizeLabel.text=Minimum File Size: +EncryptionDetectionIngestJobSettingsPanel.fileSizeMultiplesEnforcedCheckbox.text=Consider only files with sizes that are multiples of 512. +EncryptionDetectionIngestJobSettingsPanel.slackFilesAllowedCheckbox.text=Consider slack space files. +EncryptionDetectionIngestJobSettingsPanel.minimumEntropyTextbox.text= +EncryptionDetectionIngestJobSettingsPanel.minimumFileSizeTextbox.text= +EncryptionDetectionIngestJobSettingsPanel.mbLabel.text=MB diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java index f18911c016..15fccb6a74 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java @@ -45,8 +45,11 @@ import org.sleuthkit.datamodel.TskData; */ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter { - private static final double ENTROPY_THRESHOLD = 7.5; - private static final int FILE_SIZE_THRESHOLD = 5242880; // 5MB + static final double DEFAULT_CONFIG_MINIMUM_ENTROPY = 7.5; + static final int DEFAULT_CONFIG_MINIMUM_FILE_SIZE = 5242880; // 5MB; + static final boolean DEFAULT_CONFIG_FILE_SIZE_MULTIPLE_ENFORCED = true; + static final boolean DEFAULT_CONFIG_SLACK_FILES_ALLOWED = true; + private static final int FILE_SIZE_MODULUS = 512; private static final double ONE_OVER_LOG2 = 1.4426950408889634073599246810019; // (1 / log(2)) private static final int BYTE_OCCURENCES_BUFFER_SIZE = 256; @@ -55,13 +58,24 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter private final Logger LOGGER = SERVICES.getLogger(EncryptionDetectionModuleFactory.getModuleName()); private FileTypeDetector fileTypeDetector; private Blackboard blackboard; - private double entropy; + private double calculatedEntropy; + + private final double minimumEntropy; + private final int minimumFileSize; + private final boolean fileSizeMultipleEnforced; + private final boolean slackFilesAllowed; /** - * Create a EncryptionDetectionFileIngestModule object that will detect files - * that are encrypted and create blackboard artifacts as appropriate. + * Create a EncryptionDetectionFileIngestModule object that will detect + * files that are encrypted and create blackboard artifacts as appropriate. + * The supplied EncryptionDetectionIngestJobSettings object is used to + * configure the module. */ - EncryptionDetectionFileIngestModule() { + EncryptionDetectionFileIngestModule(EncryptionDetectionIngestJobSettings settings) { + minimumEntropy = settings.getMinimumEntropy(); + minimumFileSize = settings.getMinimumFileSize(); + fileSizeMultipleEnforced = settings.isFileSizeMultipleEnforced(); + slackFilesAllowed = settings.isSlackFilesAllowed(); } @Override @@ -120,7 +134,7 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter */ StringBuilder detailsSb = new StringBuilder(); detailsSb.append("File: ").append(file.getParentPath()).append(file.getName()).append("
\n"); - detailsSb.append("Entropy: ").append(entropy); + detailsSb.append("Entropy: ").append(calculatedEntropy); SERVICES.postMessage(IngestMessage.createDataMessage(EncryptionDetectionModuleFactory.getModuleName(), "Encryption Detected Match: " + file.getName(), @@ -159,7 +173,8 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter if (!file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) && !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS) && !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR) - && !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR)) { + && !file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR) + && (!file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK) || slackFilesAllowed)) { /* * Qualify the file against hash databases. */ @@ -168,17 +183,19 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter * Qualify the size. */ long contentSize = file.getSize(); - if (contentSize >= FILE_SIZE_THRESHOLD && (contentSize % FILE_SIZE_MODULUS) == 0) { - /* - * Qualify the MIME type. - */ - try { - String mimeType = fileTypeDetector.getFileType(file); - if (mimeType != null && mimeType.equals("application/octet-stream")) { - possiblyEncrypted = true; + if (contentSize >= minimumFileSize) { + if (!fileSizeMultipleEnforced || (contentSize % FILE_SIZE_MODULUS) == 0) { + /* + * Qualify the MIME type. + */ + try { + String mimeType = fileTypeDetector.getFileType(file); + if (mimeType != null && mimeType.equals("application/octet-stream")) { + possiblyEncrypted = true; + } + } catch (TskCoreException ex) { + throw new TskCoreException("Failed to detect the file type.", ex); } - } catch (TskCoreException ex) { - throw new TskCoreException("Failed to detect the file type.", ex); } } } @@ -186,8 +203,8 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter if (possiblyEncrypted) { try { - entropy = calculateEntropy(file); - if (entropy > ENTROPY_THRESHOLD) { + calculatedEntropy = calculateEntropy(file); + if (calculatedEntropy >= minimumEntropy) { return true; } } catch (IOException ex) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettings.java b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettings.java new file mode 100755 index 0000000000..2aa6ad860d --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettings.java @@ -0,0 +1,133 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2017 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.modules.encryptiondetection; + +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; + +/** + * Ingest job settings for the Encryption Detection module. + */ +final class EncryptionDetectionIngestJobSettings implements IngestModuleIngestJobSettings { + + private static final long serialVersionUID = 1L; + + private double minimumEntropy; + private int minimumFileSize; + private boolean fileSizeMultipleEnforced; + private boolean slackFilesAllowed; + + /** + * Instantiate the ingest job settings with default values. + */ + EncryptionDetectionIngestJobSettings() { + this.minimumEntropy = EncryptionDetectionFileIngestModule.DEFAULT_CONFIG_MINIMUM_ENTROPY; + this.minimumFileSize = EncryptionDetectionFileIngestModule.DEFAULT_CONFIG_MINIMUM_FILE_SIZE; + this.fileSizeMultipleEnforced = EncryptionDetectionFileIngestModule.DEFAULT_CONFIG_FILE_SIZE_MULTIPLE_ENFORCED; + this.slackFilesAllowed = EncryptionDetectionFileIngestModule.DEFAULT_CONFIG_SLACK_FILES_ALLOWED; + } + + /** + * Instantiate the ingest job settings. + * + * @param minimumEntropy The minimum entropy. + * @param minimumFileSize The minimum file size. + * @param fileSizeMultipleEnforced Files must be a multiple of 512 to be + * processed. + * @param slackFilesAllowed Slack files can be processed. + */ + EncryptionDetectionIngestJobSettings(double minimumEntropy, int minimumFileSize, boolean fileSizeMultipleEnforced, boolean slackFilesAllowed) { + this.minimumEntropy = minimumEntropy; + this.minimumFileSize = minimumFileSize; + this.fileSizeMultipleEnforced = fileSizeMultipleEnforced; + this.slackFilesAllowed = slackFilesAllowed; + } + + @Override + public long getVersionNumber() { + return serialVersionUID; + } + + /** + * Get the minimum entropy necessary for the creation of blackboard + * artifacts. + * + * @return The minimum entropy. + */ + double getMinimumEntropy() { + return minimumEntropy; + } + + /** + * Set the minimum entropy necessary for the creation of blackboard + * artifacts. + */ + void setMinimumEntropy(double minimumEntropy) { + this.minimumEntropy = minimumEntropy; + } + + /** + * Get the minimum file size necessary for the creation of blackboard + * artifacts. + * + * @return The minimum file size. + */ + int getMinimumFileSize() { + return minimumFileSize; + } + + /** + * Set the minimum file size necessary for the creation of blackboard + * artifacts. + */ + void setMinimumFileSize(int minimumFileSize) { + this.minimumFileSize = minimumFileSize; + } + + /** + * Is the file size multiple enforced? + * + * @return True if enforcement is enabled; otherwise false. + */ + boolean isFileSizeMultipleEnforced() { + return fileSizeMultipleEnforced; + } + + /** + * Enable or disable file size multiple enforcement. + */ + void setFileSizeMultipleEnforced(boolean fileSizeMultipleEnforced) { + this.fileSizeMultipleEnforced = fileSizeMultipleEnforced; + } + + /** + * Are slack files allowed for processing? + * + * @return True if slack files are allowed; otherwise false. + */ + boolean isSlackFilesAllowed() { + return slackFilesAllowed; + } + + /** + * Allow or disallow slack files for processing. + */ + void setSlackFilesAllowed(boolean slackFilesAllowed) { + this.slackFilesAllowed = slackFilesAllowed; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form new file mode 100755 index 0000000000..cb231c8abb --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form @@ -0,0 +1,119 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java new file mode 100755 index 0000000000..c1c72852d7 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java @@ -0,0 +1,193 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2017 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.modules.encryptiondetection; + +import org.openide.util.NbBundle; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; + +/** + * Ingest job settings panel for the Encryption Detection module. + */ +final class EncryptionDetectionIngestJobSettingsPanel extends IngestModuleIngestJobSettingsPanel { + + private static final int MEGABYTE_SIZE = 1048576; + private static final double MINIMUM_ENTROPY_INPUT_RANGE_MIN = 6.0; + private static final double MINIMUM_ENTROPY_INPUT_RANGE_MAX = 8.0; + private static final int MINIMUM_FILE_SIZE_INPUT_RANGE_MIN = 1; + + /** + * Instantiate the ingest job settings panel. + * + * @param settings The ingest job settings. + */ + public EncryptionDetectionIngestJobSettingsPanel(EncryptionDetectionIngestJobSettings settings) { + initComponents(); + customizeComponents(settings); + } + + /** + * Update components with values from the ingest job settings. + * + * @param settings The ingest job settings. + */ + private void customizeComponents(EncryptionDetectionIngestJobSettings settings) { + minimumEntropyTextbox.setText(String.valueOf(settings.getMinimumEntropy())); + minimumFileSizeTextbox.setText(String.valueOf(settings.getMinimumFileSize() / MEGABYTE_SIZE)); + fileSizeMultiplesEnforcedCheckbox.setSelected(settings.isFileSizeMultipleEnforced()); + slackFilesAllowedCheckbox.setSelected(settings.isSlackFilesAllowed()); + } + + @Override + public IngestModuleIngestJobSettings getSettings() { + validateMinimumEntropy(); + validateMinimumFileSize(); + + return new EncryptionDetectionIngestJobSettings( + Double.valueOf(minimumEntropyTextbox.getText()), + Integer.valueOf(minimumFileSizeTextbox.getText()) * MEGABYTE_SIZE, + fileSizeMultiplesEnforcedCheckbox.isSelected(), + slackFilesAllowedCheckbox.isSelected()); + } + + /** + * Validate the minimum entropy input. + * + * @throws IllegalArgumentException If the input is empty, invalid, or out + * of range. + */ + @Messages({ + "EncryptionDetectionIngestJobSettingsPanel.minimumEntropyInput.validationError.text=Minimum entropy input must be a number between 6.0 and 8.0." + }) + private void validateMinimumEntropy() throws IllegalArgumentException { + try { + double minimumEntropy = Double.valueOf(minimumEntropyTextbox.getText()); + if (minimumEntropy < MINIMUM_ENTROPY_INPUT_RANGE_MIN || minimumEntropy > MINIMUM_ENTROPY_INPUT_RANGE_MAX) { + throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), "EncryptionDetectionIngestJobSettingsPanel.minimumEntropyInput.validationError.text")); + } + } catch (NumberFormatException ex) { + throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), "EncryptionDetectionIngestJobSettingsPanel.minimumEntropyInput.validationError.text")); + } + } + + /** + * Validate the minimum file size input. + * + * @throws IllegalArgumentException If the input is empty, invalid, or out + * of range. + */ + @Messages({ + "EncryptionDetectionIngestJobSettingsPanel.minimumFileSizeInput.validationError.text=Minimum file size input must be an integer (in megabytes) of 1 or greater." + }) + private void validateMinimumFileSize() throws IllegalArgumentException { + try { + int minimumFileSize = Integer.valueOf(minimumFileSizeTextbox.getText()); + if (minimumFileSize < MINIMUM_FILE_SIZE_INPUT_RANGE_MIN) { + throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), "EncryptionDetectionIngestJobSettingsPanel.minimumFileSizeInput.validationError.text")); + } + } catch (NumberFormatException ex) { + throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), "EncryptionDetectionIngestJobSettingsPanel.minimumFileSizeInput.validationError.text")); + } + } + + /** + * 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 + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + minimumEntropyTextbox = new javax.swing.JTextField(); + minimumFileSizeTextbox = new javax.swing.JTextField(); + fileSizeMultiplesEnforcedCheckbox = new javax.swing.JCheckBox(); + slackFilesAllowedCheckbox = new javax.swing.JCheckBox(); + minimumEntropyLabel = new javax.swing.JLabel(); + minimumFileSizeLabel = new javax.swing.JLabel(); + mbLabel = new javax.swing.JLabel(); + + minimumEntropyTextbox.setText(org.openide.util.NbBundle.getMessage(EncryptionDetectionIngestJobSettingsPanel.class, "EncryptionDetectionIngestJobSettingsPanel.minimumEntropyTextbox.text")); // NOI18N + + minimumFileSizeTextbox.setText(org.openide.util.NbBundle.getMessage(EncryptionDetectionIngestJobSettingsPanel.class, "EncryptionDetectionIngestJobSettingsPanel.minimumFileSizeTextbox.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(fileSizeMultiplesEnforcedCheckbox, org.openide.util.NbBundle.getMessage(EncryptionDetectionIngestJobSettingsPanel.class, "EncryptionDetectionIngestJobSettingsPanel.fileSizeMultiplesEnforcedCheckbox.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(slackFilesAllowedCheckbox, org.openide.util.NbBundle.getMessage(EncryptionDetectionIngestJobSettingsPanel.class, "EncryptionDetectionIngestJobSettingsPanel.slackFilesAllowedCheckbox.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(minimumEntropyLabel, org.openide.util.NbBundle.getMessage(EncryptionDetectionIngestJobSettingsPanel.class, "EncryptionDetectionIngestJobSettingsPanel.minimumEntropyLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(minimumFileSizeLabel, org.openide.util.NbBundle.getMessage(EncryptionDetectionIngestJobSettingsPanel.class, "EncryptionDetectionIngestJobSettingsPanel.minimumFileSizeLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(mbLabel, org.openide.util.NbBundle.getMessage(EncryptionDetectionIngestJobSettingsPanel.class, "EncryptionDetectionIngestJobSettingsPanel.mbLabel.text")); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(minimumFileSizeLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(minimumFileSizeTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(minimumEntropyLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(minimumEntropyTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(mbLabel)) + .addComponent(fileSizeMultiplesEnforcedCheckbox) + .addComponent(slackFilesAllowedCheckbox)) + .addContainerGap(15, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(minimumEntropyLabel) + .addComponent(minimumEntropyTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(minimumFileSizeLabel) + .addComponent(minimumFileSizeTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(mbLabel)) + .addGap(15, 15, 15) + .addComponent(fileSizeMultiplesEnforcedCheckbox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(slackFilesAllowedCheckbox) + .addContainerGap(182, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox fileSizeMultiplesEnforcedCheckbox; + private javax.swing.JLabel mbLabel; + private javax.swing.JLabel minimumEntropyLabel; + private javax.swing.JTextField minimumEntropyTextbox; + private javax.swing.JLabel minimumFileSizeLabel; + private javax.swing.JTextField minimumFileSizeTextbox; + private javax.swing.JCheckBox slackFilesAllowedCheckbox; + // End of variables declaration//GEN-END:variables +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionModuleFactory.java index 53eca1aec6..27549f648f 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionModuleFactory.java @@ -22,10 +22,12 @@ import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.coreutils.Version; +import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; import org.sleuthkit.autopsy.ingest.FileIngestModule; import org.sleuthkit.autopsy.ingest.IngestModuleFactory; -import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; +import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; /** * A factory that creates file ingest modules that detect encryption. @@ -33,9 +35,9 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; @ServiceProvider(service = IngestModuleFactory.class) @Messages({ "EncryptionDetectionFileIngestModule.moduleName.text=Encryption Detection", - "EncryptionDetectionFileIngestModule.getDesc.text=Looks for large files with high entropy." + "EncryptionDetectionFileIngestModule.getDesc.text=Looks for files with the specified minimum entropy." }) -public class EncryptionDetectionModuleFactory extends IngestModuleFactoryAdapter { +public class EncryptionDetectionModuleFactory implements IngestModuleFactory { @Override public String getModuleDisplayName() { @@ -44,7 +46,7 @@ public class EncryptionDetectionModuleFactory extends IngestModuleFactoryAdapter /** * Get the name of the module. - * + * * @return The module name. */ static String getModuleName() { @@ -67,7 +69,48 @@ public class EncryptionDetectionModuleFactory extends IngestModuleFactoryAdapter } @Override - public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings ingestOptions) { - return new EncryptionDetectionFileIngestModule(); + public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings settings) { + if (!(settings instanceof EncryptionDetectionIngestJobSettings)) { + throw new IllegalArgumentException("Expected settings argument to be an instance of EncryptionDetectionIngestJobSettings."); + } + return new EncryptionDetectionFileIngestModule((EncryptionDetectionIngestJobSettings) settings); } -} \ No newline at end of file + + @Override + public boolean hasGlobalSettingsPanel() { + return false; + } + + @Override + public IngestModuleGlobalSettingsPanel getGlobalSettingsPanel() { + throw new UnsupportedOperationException(); + } + + @Override + public IngestModuleIngestJobSettings getDefaultIngestJobSettings() { + return new EncryptionDetectionIngestJobSettings(); + } + + @Override + public boolean hasIngestJobSettingsPanel() { + return true; + } + + @Override + public IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings settings) { + if (!(settings instanceof EncryptionDetectionIngestJobSettings)) { + throw new IllegalArgumentException("Expected settings argument to be an instance of EncryptionDetectionIngestJobSettings"); + } + return new EncryptionDetectionIngestJobSettingsPanel((EncryptionDetectionIngestJobSettings) settings); + } + + @Override + public boolean isDataSourceIngestModuleFactory() { + return false; + } + + @Override + public DataSourceIngestModule createDataSourceIngestModule(IngestModuleIngestJobSettings settings) { + throw new UnsupportedOperationException(); + } +} From 50223cc0c97c756eae4639819d00ce5773f33080 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Wed, 29 Nov 2017 17:30:09 -0500 Subject: [PATCH 74/90] Revised the settings panel. --- .../encryptiondetection/Bundle.properties | 1 + ...yptionDetectionIngestJobSettingsPanel.form | 56 ++++++++++++------- ...yptionDetectionIngestJobSettingsPanel.java | 51 ++++++++++------- 3 files changed, 69 insertions(+), 39 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/Bundle.properties index 3d8238e173..fdc7d9ed0d 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/Bundle.properties @@ -5,3 +5,4 @@ EncryptionDetectionIngestJobSettingsPanel.slackFilesAllowedCheckbox.text=Conside EncryptionDetectionIngestJobSettingsPanel.minimumEntropyTextbox.text= EncryptionDetectionIngestJobSettingsPanel.minimumFileSizeTextbox.text= EncryptionDetectionIngestJobSettingsPanel.mbLabel.text=MB +EncryptionDetectionIngestJobSettingsPanel.detectionSettingsLabel.text=Detection Settings diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form index cb231c8abb..99b6034502 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form @@ -19,26 +19,32 @@ + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - + @@ -46,21 +52,23 @@ + + - + - + - + - + @@ -115,5 +123,15 @@
+ + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java index c1c72852d7..8a8576c15b 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java @@ -123,6 +123,7 @@ final class EncryptionDetectionIngestJobSettingsPanel extends IngestModuleIngest minimumEntropyLabel = new javax.swing.JLabel(); minimumFileSizeLabel = new javax.swing.JLabel(); mbLabel = new javax.swing.JLabel(); + detectionSettingsLabel = new javax.swing.JLabel(); minimumEntropyTextbox.setText(org.openide.util.NbBundle.getMessage(EncryptionDetectionIngestJobSettingsPanel.class, "EncryptionDetectionIngestJobSettingsPanel.minimumEntropyTextbox.text")); // NOI18N @@ -138,6 +139,9 @@ final class EncryptionDetectionIngestJobSettingsPanel extends IngestModuleIngest org.openide.awt.Mnemonics.setLocalizedText(mbLabel, org.openide.util.NbBundle.getMessage(EncryptionDetectionIngestJobSettingsPanel.class, "EncryptionDetectionIngestJobSettingsPanel.mbLabel.text")); // NOI18N + detectionSettingsLabel.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(detectionSettingsLabel, org.openide.util.NbBundle.getMessage(EncryptionDetectionIngestJobSettingsPanel.class, "EncryptionDetectionIngestJobSettingsPanel.detectionSettingsLabel.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -145,43 +149,50 @@ final class EncryptionDetectionIngestJobSettingsPanel extends IngestModuleIngest .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(detectionSettingsLabel) .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addComponent(minimumFileSizeLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(minimumFileSizeTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() - .addComponent(minimumEntropyLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(minimumEntropyTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(mbLabel)) - .addComponent(fileSizeMultiplesEnforcedCheckbox) - .addComponent(slackFilesAllowedCheckbox)) - .addContainerGap(15, Short.MAX_VALUE)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(fileSizeMultiplesEnforcedCheckbox) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(layout.createSequentialGroup() + .addComponent(minimumFileSizeLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(minimumFileSizeTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(layout.createSequentialGroup() + .addComponent(minimumEntropyLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(minimumEntropyTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(mbLabel)) + .addComponent(slackFilesAllowedCheckbox)))) + .addContainerGap(17, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() + .addComponent(detectionSettingsLabel) + .addGap(16, 16, 16) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(minimumEntropyLabel) - .addComponent(minimumEntropyTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(minimumEntropyTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(minimumEntropyLabel)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(minimumFileSizeLabel) .addComponent(minimumFileSizeTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(mbLabel)) - .addGap(15, 15, 15) + .addComponent(mbLabel) + .addComponent(minimumFileSizeLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(fileSizeMultiplesEnforcedCheckbox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(slackFilesAllowedCheckbox) - .addContainerGap(182, Short.MAX_VALUE)) + .addContainerGap(160, Short.MAX_VALUE)) ); }// //GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel detectionSettingsLabel; private javax.swing.JCheckBox fileSizeMultiplesEnforcedCheckbox; private javax.swing.JLabel mbLabel; private javax.swing.JLabel minimumEntropyLabel; From 42111e272cf7a6f532aa58891ae8177f7807cbd1 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 30 Nov 2017 10:29:38 -0500 Subject: [PATCH 75/90] Minor tweak to settings panel. --- ...yptionDetectionIngestJobSettingsPanel.form | 39 ++++++++----------- ...yptionDetectionIngestJobSettingsPanel.java | 31 +++++++-------- 2 files changed, 31 insertions(+), 39 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form index 99b6034502..26c859fe4d 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form @@ -16,35 +16,30 @@ - + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - + + + - + diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java index 8a8576c15b..123a62ec85 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java @@ -149,25 +149,22 @@ final class EncryptionDetectionIngestJobSettingsPanel extends IngestModuleIngest .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(slackFilesAllowedCheckbox) .addComponent(detectionSettingsLabel) .addGroup(layout.createSequentialGroup() - .addGap(18, 18, 18) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(fileSizeMultiplesEnforcedCheckbox) - .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(layout.createSequentialGroup() - .addComponent(minimumFileSizeLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(minimumFileSizeTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(layout.createSequentialGroup() - .addComponent(minimumEntropyLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(minimumEntropyTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(mbLabel)) - .addComponent(slackFilesAllowedCheckbox)))) - .addContainerGap(17, Short.MAX_VALUE)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(minimumFileSizeLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(minimumFileSizeTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() + .addComponent(minimumEntropyLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(minimumEntropyTextbox, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(mbLabel)) + .addComponent(fileSizeMultiplesEnforcedCheckbox)) + .addContainerGap(15, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) From a6b115b35ea7e147fbc0c169c41cfdcd629e25f0 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 30 Nov 2017 16:57:39 -0500 Subject: [PATCH 76/90] Code added to display data source size metrics. --- .../AutoIngestMetricsCollector.java | 83 ++++++++++++++----- .../autoingest/AutoIngestMetricsDialog.form | 33 +++++--- .../autoingest/AutoIngestMetricsDialog.java | 53 ++++++++---- .../experimental/autoingest/Bundle.properties | 5 +- 4 files changed, 121 insertions(+), 53 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsCollector.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsCollector.java index 9567b70470..9a08951fe8 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsCollector.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsCollector.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -29,14 +29,15 @@ import org.sleuthkit.autopsy.coreutils.Logger; * Collects metrics for an auto ingest cluster. */ final class AutoIngestMetricsCollector { - + private static final Logger LOGGER = Logger.getLogger(AutoIngestMetricsCollector.class.getName()); + private static final int MINIMUM_SUPPORTED_JOB_NODE_VERSION = 1; private CoordinationService coordinationService; - + /** * Creates an instance of the AutoIngestMetricsCollector. - * - * @throws AutoIngestMetricsCollector.AutoIngestMetricsCollectorException + * + * @throws AutoIngestMetricsCollector.AutoIngestMetricsCollectorException */ AutoIngestMetricsCollector() throws AutoIngestMetricsCollectorException { try { @@ -45,7 +46,7 @@ final class AutoIngestMetricsCollector { throw new AutoIngestMetricsCollectorException("Failed to get coordination service", ex); //NON-NLS } } - + /** * Gets a new metrics snapshot from the coordination service for an auto * ingest cluster. @@ -59,7 +60,7 @@ final class AutoIngestMetricsCollector { for (String node : nodeList) { try { AutoIngestJobNodeData nodeData = new AutoIngestJobNodeData(coordinationService.getNodeData(CoordinationService.CategoryNode.MANIFESTS, node)); - if (nodeData.getVersion() < 1) { + if (nodeData.getVersion() < MINIMUM_SUPPORTED_JOB_NODE_VERSION) { /* * Ignore version '0' nodes that have not been * "upgraded" since they don't carry enough data. @@ -78,7 +79,7 @@ final class AutoIngestMetricsCollector { */ break; case COMPLETED: - newMetricsSnapshot.addCompletedJobDate(job.getCompletedDate()); + newMetricsSnapshot.addCompletedJobMetric(job.getCompletedDate(), job.getDataSourceSize()); break; default: LOGGER.log(Level.SEVERE, "Unknown AutoIngestJobData.ProcessingStatus"); @@ -92,41 +93,79 @@ final class AutoIngestMetricsCollector { LOGGER.log(Level.SEVERE, String.format("Failed to create a job for '%s'", node), ex); } } - + return newMetricsSnapshot; - + } catch (CoordinationService.CoordinationServiceException ex) { LOGGER.log(Level.SEVERE, "Failed to get node list from coordination service", ex); return new MetricsSnapshot(); } } - + /** * A snapshot of metrics for an auto ingest cluster. */ static final class MetricsSnapshot { - - private final List completedJobDates = new ArrayList<>(); + + private final List completedJobMetrics = new ArrayList<>(); /** - * Gets a list of completed job dates, formatted in milliseconds. + * Gets a list of completed job metrics. * - * @return The completed job dates, formatted in milliseconds. + * @return The completed job metrics. */ - List getCompletedJobDates() { - return new ArrayList<>(completedJobDates); + List getCompletedJobMetrics() { + return new ArrayList<>(completedJobMetrics); } /** - * Adds a new date to the list of completed job dates. + * Adds a new metric to the list of completed job metrics. * - * @param date The date to be added. + * @param completedDate The completed job date. + * @param dataSourceSize The data source size. */ - void addCompletedJobDate(java.util.Date date) { - completedJobDates.add(date.getTime()); + void addCompletedJobMetric(java.util.Date completedDate, long dataSourceSize) { + completedJobMetrics.add(new JobMetric(completedDate, dataSourceSize)); } } + /** + * A single job metric for an auto ingest cluster. + */ + static final class JobMetric { + private final long completedDate; + private final long dataSourceSize; + + /** + * Instantiates a job metric. + * + * @param completedDate The job completion date. + * @param dataSourceSize The data source size. + */ + JobMetric(java.util.Date completedDate, long dataSourceSize) { + this.completedDate = completedDate.getTime(); + this.dataSourceSize = dataSourceSize; + } + + /** + * Gets the job completion date, formatted in milliseconds. + * + * @return The job completion date. + */ + long getCompletedDate() { + return completedDate; + } + + /** + * Gets the data source size. + * + * @return The data source size. + */ + long getDataSourceSize() { + return dataSourceSize; + } + } + /** * Exception type thrown when there is an error completing an auto ingest * metrics collector operation. @@ -157,4 +196,4 @@ final class AutoIngestMetricsCollector { } } -} \ No newline at end of file +} diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.form b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.form index 49e700ca21..cbe7b53c2f 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.form +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.form @@ -30,10 +30,14 @@ - - + + - + + + + + @@ -43,17 +47,17 @@ - + + + + + + + - - - - - - - + @@ -109,5 +113,12 @@ + + + + + + + diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java index 80bcb6958b..69f3401180 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2017 Basis Technology Corp. + * Copyright 2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,14 +25,18 @@ import java.awt.Window; import java.sql.Date; import java.text.SimpleDateFormat; import java.time.ZoneOffset; +import java.util.List; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMetricsCollector.JobMetric; /** * Displays auto ingest metrics for a cluster. */ final class AutoIngestMetricsDialog extends javax.swing.JDialog { + private static final int GIGABYTE_SIZE = 1073741824; + private final AutoIngestMetricsCollector autoIngestMetricsCollector; /** @@ -42,7 +46,7 @@ final class AutoIngestMetricsDialog extends javax.swing.JDialog { */ @Messages({ "AutoIngestMetricsDialog.title.text=Auto Ingest Cluster Metrics", - "AutoIngestMetricsDialog.initReportText=Select a date below and click the 'Get Metrics Since...' button to generate\na metrics report." + "AutoIngestMetricsDialog.initReportText=Select a date above and click the 'Generate Metrics Report' button to generate\na metrics report." }) AutoIngestMetricsDialog(Container parent) throws AutoIngestMetricsDialogException { super((Window) parent, NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.title.text"), ModalityType.MODELESS); @@ -68,21 +72,26 @@ final class AutoIngestMetricsDialog extends javax.swing.JDialog { } AutoIngestMetricsCollector.MetricsSnapshot metricsSnapshot = autoIngestMetricsCollector.queryCoordinationServiceForMetrics(); - Object[] completedJobDates = metricsSnapshot.getCompletedJobDates().toArray(); - int count = 0; + List completedJobMetrics = metricsSnapshot.getCompletedJobMetrics(); + int jobsCompleted = 0; + long dataSourceSizeTotal = 0; long pickedDate = datePicker.getDate().atStartOfDay().toEpochSecond(ZoneOffset.UTC) * 1000; - for(int i = completedJobDates.length - 1; i >= 0; i--) { - if((Long)completedJobDates[i] >= pickedDate) { - count++; + + for(JobMetric jobMetric : completedJobMetrics) { + if(jobMetric.getCompletedDate() >= pickedDate) { + jobsCompleted++; + dataSourceSizeTotal += jobMetric.getDataSourceSize(); } } SimpleDateFormat dateFormatter = new SimpleDateFormat("MMM d, yyyy"); reportTextArea.setText(String.format( "Since %s:\n" + - "\tNumber of Jobs Completed: %d\n", + "Number of Jobs Completed: %d\n" + + "Total Size of Data Sources: %.1f GB\n", dateFormatter.format(Date.valueOf(datePicker.getDate())), - count + jobsCompleted, + (double)dataSourceSizeTotal / GIGABYTE_SIZE )); } @@ -131,6 +140,7 @@ final class AutoIngestMetricsDialog extends javax.swing.JDialog { reportTextArea = new javax.swing.JTextArea(); metricsButton = new javax.swing.JButton(); datePicker = new DatePicker(); + startingDataLabel = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setAlwaysOnTop(true); @@ -158,6 +168,8 @@ final class AutoIngestMetricsDialog extends javax.swing.JDialog { datePicker.setToolTipText(org.openide.util.NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.datePicker.toolTipText")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(startingDataLabel, org.openide.util.NbBundle.getMessage(AutoIngestMetricsDialog.class, "AutoIngestMetricsDialog.startingDataLabel.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( @@ -167,24 +179,28 @@ final class AutoIngestMetricsDialog extends javax.swing.JDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jScrollPane1) .addGroup(layout.createSequentialGroup() - .addComponent(metricsButton) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(startingDataLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(datePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 33, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 7, Short.MAX_VALUE) + .addComponent(metricsButton)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) .addComponent(closeButton, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE))) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGroup(layout.createSequentialGroup() .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(metricsButton) + .addComponent(datePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(startingDataLabel)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 128, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(closeButton) - .addComponent(metricsButton)) - .addComponent(datePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(closeButton) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); @@ -208,5 +224,6 @@ final class AutoIngestMetricsDialog extends javax.swing.JDialog { private javax.swing.JScrollPane jScrollPane1; private javax.swing.JButton metricsButton; private javax.swing.JTextArea reportTextArea; + private javax.swing.JLabel startingDataLabel; // End of variables declaration//GEN-END:variables } \ No newline at end of file diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties index 5f335b1ba4..d953b0ceb3 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties @@ -228,10 +228,11 @@ AutoIngestDashboard.prioritizeCaseButton.toolTipText=Move all images associated AutoIngestDashboard.prioritizeCaseButton.text=Prioritize &Case AutoIngestMetricsDialog.reportTextArea.text= AutoIngestDashboard.clusterMetricsButton.text=Cluster Metrics -AutoIngestMetricsDialog.metricsButton.text=Get Metrics Since... +AutoIngestMetricsDialog.metricsButton.text=Generate Metrics Report AutoIngestMetricsDialog.closeButton.text=Close AutoIngestMetricsDialog.datePicker.toolTipText=Choose a date ArchiveFilePanel.pathLabel.text=Browse for an archive file: ArchiveFilePanel.browseButton.text=Browse ArchiveFilePanel.pathTextField.text= -ArchiveFilePanel.errorLabel.text=Error Label \ No newline at end of file +ArchiveFilePanel.errorLabel.text=Error Label +AutoIngestMetricsDialog.startingDataLabel.text=Starting Date: From a5408e8a4a606a9db377b8fb392eeea29f275a10 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Thu, 30 Nov 2017 16:59:39 -0500 Subject: [PATCH 77/90] Formatting. --- .../AutoIngestMetricsCollector.java | 27 ++++++++-------- .../autoingest/AutoIngestMetricsDialog.java | 32 +++++++++---------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsCollector.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsCollector.java index 9a08951fe8..7b07a15aec 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsCollector.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsCollector.java @@ -108,57 +108,58 @@ final class AutoIngestMetricsCollector { static final class MetricsSnapshot { private final List completedJobMetrics = new ArrayList<>(); - + /** * Gets a list of completed job metrics. - * + * * @return The completed job metrics. */ List getCompletedJobMetrics() { return new ArrayList<>(completedJobMetrics); } - + /** * Adds a new metric to the list of completed job metrics. - * - * @param completedDate The completed job date. + * + * @param completedDate The completed job date. * @param dataSourceSize The data source size. */ void addCompletedJobMetric(java.util.Date completedDate, long dataSourceSize) { completedJobMetrics.add(new JobMetric(completedDate, dataSourceSize)); } } - + /** * A single job metric for an auto ingest cluster. */ static final class JobMetric { + private final long completedDate; private final long dataSourceSize; - + /** * Instantiates a job metric. - * - * @param completedDate The job completion date. + * + * @param completedDate The job completion date. * @param dataSourceSize The data source size. */ JobMetric(java.util.Date completedDate, long dataSourceSize) { this.completedDate = completedDate.getTime(); this.dataSourceSize = dataSourceSize; } - + /** * Gets the job completion date, formatted in milliseconds. - * + * * @return The job completion date. */ long getCompletedDate() { return completedDate; } - + /** * Gets the data source size. - * + * * @return The data source size. */ long getDataSourceSize() { diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java index 69f3401180..af0679be5f 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestMetricsDialog.java @@ -34,14 +34,14 @@ import org.sleuthkit.autopsy.experimental.autoingest.AutoIngestMetricsCollector. * Displays auto ingest metrics for a cluster. */ final class AutoIngestMetricsDialog extends javax.swing.JDialog { - + private static final int GIGABYTE_SIZE = 1073741824; - + private final AutoIngestMetricsCollector autoIngestMetricsCollector; /** * Creates an instance of AutoIngestMetricsDialog - * + * * @param parent The parent container. */ @Messages({ @@ -62,39 +62,39 @@ final class AutoIngestMetricsDialog extends javax.swing.JDialog { setLocationRelativeTo(parent); setVisible(true); } - + /** * Update the metrics shown in the report text area. */ private void updateMetrics() { - if(datePicker.getDate() == null) { + if (datePicker.getDate() == null) { return; } - + AutoIngestMetricsCollector.MetricsSnapshot metricsSnapshot = autoIngestMetricsCollector.queryCoordinationServiceForMetrics(); List completedJobMetrics = metricsSnapshot.getCompletedJobMetrics(); int jobsCompleted = 0; long dataSourceSizeTotal = 0; long pickedDate = datePicker.getDate().atStartOfDay().toEpochSecond(ZoneOffset.UTC) * 1000; - - for(JobMetric jobMetric : completedJobMetrics) { - if(jobMetric.getCompletedDate() >= pickedDate) { + + for (JobMetric jobMetric : completedJobMetrics) { + if (jobMetric.getCompletedDate() >= pickedDate) { jobsCompleted++; dataSourceSizeTotal += jobMetric.getDataSourceSize(); } } - + SimpleDateFormat dateFormatter = new SimpleDateFormat("MMM d, yyyy"); reportTextArea.setText(String.format( - "Since %s:\n" + - "Number of Jobs Completed: %d\n" + - "Total Size of Data Sources: %.1f GB\n", + "Since %s:\n" + + "Number of Jobs Completed: %d\n" + + "Total Size of Data Sources: %.1f GB\n", dateFormatter.format(Date.valueOf(datePicker.getDate())), jobsCompleted, - (double)dataSourceSizeTotal / GIGABYTE_SIZE + (double) dataSourceSizeTotal / GIGABYTE_SIZE )); } - + /** * Exception type thrown when there is an error completing an auto ingest * metrics dialog operation. @@ -226,4 +226,4 @@ final class AutoIngestMetricsDialog extends javax.swing.JDialog { private javax.swing.JTextArea reportTextArea; private javax.swing.JLabel startingDataLabel; // End of variables declaration//GEN-END:variables -} \ No newline at end of file +} From 87f69cc074ec7aba0053b6fbc2e7157198676851 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Fri, 1 Dec 2017 13:09:17 -0500 Subject: [PATCH 78/90] Remove use of deprecated method from AddLocalFilesTask, FileManager --- .../org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java | 2 +- .../sleuthkit/autopsy/casemodule/services/FileManager.java | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java index b2d14db118..c610ff78c3 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddLocalFilesTask.java @@ -89,7 +89,7 @@ class AddLocalFilesTask implements Runnable { progress.setIndeterminate(true); FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); LocalFilesDataSource newDataSource = fileManager.addLocalFilesDataSource(deviceId, rootVirtualDirectoryName, "", localFilePaths, new ProgressUpdater()); - newDataSources.add(newDataSource.getRootDirectory()); + newDataSources.add(newDataSource); } catch (TskDataException | TskCoreException ex) { errors.add(ex.getMessage()); LOGGER.log(Level.SEVERE, String.format("Failed to add datasource: %s", ex.getMessage()), ex); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java index f12c2f7e5d..817052619b 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java @@ -47,7 +47,6 @@ import org.sleuthkit.datamodel.LocalFilesDataSource; import org.sleuthkit.datamodel.TskDataException; import org.apache.commons.lang3.StringUtils; import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.datamodel.AbstractContent; import org.sleuthkit.datamodel.CarvingResult; import org.sleuthkit.datamodel.TskData; @@ -409,10 +408,9 @@ public class FileManager implements Closeable { */ trans = caseDb.beginTransaction(); LocalFilesDataSource dataSource = caseDb.addLocalFilesDataSource(deviceId, rootDirectoryName, timeZone, trans); - VirtualDirectory rootDirectory = dataSource.getRootDirectory(); List filesAdded = new ArrayList<>(); for (java.io.File localFile : localFiles) { - AbstractFile fileAdded = addLocalFile(trans, rootDirectory, localFile, TskData.EncodingType.NONE, progressUpdater); + AbstractFile fileAdded = addLocalFile(trans, dataSource, localFile, TskData.EncodingType.NONE, progressUpdater); if (null != fileAdded) { filesAdded.add(fileAdded); } else { From f3360d1ec679a1a0d7d8154d22db5b89e82cbced Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 1 Dec 2017 13:19:48 -0500 Subject: [PATCH 79/90] 3226 add memory setting to Application Options panel --- .../corecomponents/AutopsyOptionsPanel.form | 185 +++++++-- .../corecomponents/AutopsyOptionsPanel.java | 372 +++++++++++++++++- 2 files changed, 512 insertions(+), 45 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form index 2e618379e4..aebb685756 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form @@ -23,17 +23,14 @@ - + - - - - + @@ -53,12 +50,13 @@ - + + - + @@ -68,6 +66,8 @@ + +
@@ -79,7 +79,7 @@ - + @@ -102,7 +102,7 @@ - + @@ -185,7 +185,7 @@ - + @@ -201,24 +201,39 @@ - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + - @@ -382,6 +397,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 435bdc99b4..86750ba738 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -21,6 +21,14 @@ package org.sleuthkit.autopsy.corecomponents; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.StringJoiner; import java.util.logging.Level; import javax.imageio.ImageIO; import javax.swing.ImageIcon; @@ -33,6 +41,8 @@ import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.GeneralFilter; import org.sleuthkit.autopsy.core.UserPreferences; import org.sleuthkit.autopsy.coreutils.ModuleSettings; +import org.sleuthkit.autopsy.coreutils.PlatformUtil; +import org.sleuthkit.autopsy.coreutils.Version; import org.sleuthkit.autopsy.report.ReportBranding; /** @@ -42,12 +52,30 @@ import org.sleuthkit.autopsy.report.ReportBranding; "AutopsyOptionsPanel.logoPanel.border.title=Logo", "AutopsyOptionsPanel.viewPanel.border.title=View", "AutopsyOptionsPanel.invalidImageFile.msg=The selected file was not able to be used as an agency logo.", - "AutopsyOptionsPanel.invalidImageFile.title=Invalid Image File"}) + "AutopsyOptionsPanel.invalidImageFile.title=Invalid Image File", + "AutopsyOptionsPanel.restartNecessaryWarning.text=A restart is necessary for any changes to max memory to take effect.", + "AutopsyOptionsPanel.totalMemoryLabel.text=Total System Memory in Gigabytes:", + "AutopsyOptionsPanel.maxMemoryLabel.text=Maximum JVM Memory:", + "AutopsyOptionsPanel.maxMemoryUnitsLabel.text=GB", + "AutopsyOptionsPanel.runtimePanel.border.title=Runtime", + "AutopsyOptionsPanel.invalidReasonLabel.not64BitInstall.text=JVM memory settings only enabled for installed 64 bit version", + "AutopsyOptionsPanel.invalidReasonLabel.noValueEntered.text=No value entered", + "AutopsyOptionsPanel.invalidReasonLabel.invalidCharacters.text=Invalid characters, value must be a positive integer", + "# {0} - minimumMemory", + "AutopsyOptionsPanel.invalidReasonLabel.underMinMemory.text=Value must be at least {0}GB", + "# {0} - systemMemory", + "AutopsyOptionsPanel.invalidReasonLabel.overMaxMemory.text=Value must be less than the total system memory of {0}GB"}) + final class AutopsyOptionsPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; private final JFileChooser fc; + private static final long ONE_BILLION = 1000000000L; //used to roughly convert system memory from bytes to gigabytes + private static final long MEGA_IN_GIGA = 1024; //used to convert memory settings saved as megabytes to gigabytes + private static final int HARD_MIN_MEMORY_IN_GB = 2; //the enforced minimum memory in gigabytes + private static final int SOFT_MIN_MEMORY_IN_GB = 4; //the minimum memory we inform the user is required in gigabytes private static final Logger logger = Logger.getLogger(AutopsyOptionsPanel.class.getName()); + private String initialMemValue = Long.toString(Runtime.getRuntime().maxMemory() / ONE_BILLION); AutopsyOptionsPanel() { initComponents(); @@ -56,8 +84,137 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { fc.setMultiSelectionEnabled(false); fc.setAcceptAllFileFilterUsed(false); fc.setFileFilter(new GeneralFilter(GeneralFilter.GRAPHIC_IMAGE_EXTS, GeneralFilter.GRAPHIC_IMG_DECR)); + if (!PlatformUtil.is64BitJVM()) { + //32 bit JVM has a max heap size of 1.4 gb to 4 gb depending on OS + //So disabling the setting of heap size when the JVM is not 64 bit + //Is the safest course of action + memField.setEnabled(false); + invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_not64BitInstall_text()); + + } + systemMemoryTotal.setText(Long.toString(getSystemMemoryInGB())); } + private long getSystemMemoryInGB() { + long memorySize = ((com.sun.management.OperatingSystemMXBean) ManagementFactory + .getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); + return memorySize / ONE_BILLION; + } + + private long getCurrentJvmMaxMemoryInGB() throws IOException { + String currentXmx = getCurrentXmxValue(); + char units = '-'; + Long value = 0L; + if (currentXmx.length() > 1) { + units = currentXmx.charAt(currentXmx.length() - 1); + value = Long.parseLong(currentXmx.substring(0, currentXmx.length() - 1)); + } else { + throw new IOException("No memory setting found in String: " + currentXmx); + } + switch (units) { + case 'g': + case 'G': + return value; + case 'm': + case 'M': + return value / MEGA_IN_GIGA; + default: + throw new IOException("Units were not recognized as parsed: " + units); + } + } + + private String getCurrentXmxValue() throws IOException { + File userFolder = PlatformUtil.getUserDirectory(); + File userEtcFolder = new File(userFolder, "etc"); + String confFile = Version.getName() + ".conf"; + File userEtcConfigFile = new File(userEtcFolder, confFile); + String[] settings; + String currentSetting = ""; + if (!userEtcConfigFile.exists()) { + String installFolder = PlatformUtil.getInstallPath(); + File installFolderEtc = new File(installFolder, "etc"); + File installFolderConfigFile = new File(installFolderEtc, confFile); + if (installFolderConfigFile.exists()) { + settings = getDefaultsFromFileContents(readConfFile(installFolderConfigFile)); + //copy install folder config + } else { + throw new IOException("Conf file could not be found, software may not be properly installed. " + installFolderConfigFile.toString()); + } + } else { + settings = getDefaultsFromFileContents(readConfFile(userEtcConfigFile)); + } + for (String option : settings) { + System.out.println("Setting: " + option); + if (option.startsWith("-J-Xmx")) { + currentSetting = option.replace("-J-Xmx", "").trim(); + } + } + return currentSetting; + } + + private void writeEtcConfFile() throws IOException { + String confFileName = Version.getName() + ".conf"; + File userFolder = PlatformUtil.getUserDirectory(); + File userEtcFolder = new File(userFolder, "etc"); + File userEtcConfigFile = new File(userEtcFolder, confFileName); + String installFolder = PlatformUtil.getInstallPath(); + File installFolderEtc = new File(installFolder, "etc"); + File installFolderConfigFile = new File(installFolderEtc, confFileName); + StringBuilder content = new StringBuilder(); + if (installFolderConfigFile.exists()) { + List confFile = readConfFile(installFolderConfigFile); + for (String line : confFile) { + if (line.contains("-J-Xmx")) { + // content.append("default_options=\""); + String[] splitLine = line.split(" "); + //.replace("default_options=", "").replaceAll("\"", "") + StringJoiner modifiedLine = new StringJoiner(" "); + + for (String piece : splitLine) { + if (piece.contains("-J-Xmx")) { + piece = "-J-Xmx" + memField.getText() + "g"; + } + modifiedLine.add(piece); + } + content.append(modifiedLine.toString()); + // content.append("\""); + } else { + content.append(line); + } + content.append("\n"); + } + Files.write(userEtcConfigFile.toPath(), content.toString().getBytes()); + //copy install folder config + } else { + throw new IOException("Conf file could not be found, software may not be properly installed. " + installFolderConfigFile.toString()); + } + } + + private static List readConfFile(File ctConfigFile) { + List lines = new ArrayList<>(); + if (null != ctConfigFile) { + Path filePath = ctConfigFile.toPath(); + Charset charset = Charset.forName("UTF-8"); + try { + lines = Files.readAllLines(filePath, charset); + } catch (IOException e) { + logger.log(Level.SEVERE, "Error reading config file contents. {}", ctConfigFile.getAbsolutePath()); + } + } + return lines; + } + + private static String[] getDefaultsFromFileContents(List list) { + Optional defaultSettings = list.stream().filter(line -> line.startsWith("default_options=")).findFirst(); + + if (defaultSettings.isPresent()) { + return defaultSettings.get().replace("default_options=", "").replaceAll("\"", "").split(" "); + } + return new String[]{}; + } + + @Messages({"# {0} - installedFolder", + "AutopsyOptionsPanel.invalidReasonLabel.configFileMissing.text=Unable to find JVM memory settings in installed folder {0}"}) void load() { boolean keepPreferredViewer = UserPreferences.keepPreferredContentViewer(); keepCurrentViewerRB.setSelected(keepPreferredViewer); @@ -75,6 +232,16 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } catch (IOException ex) { logger.log(Level.WARNING, "Error loading image from previously saved agency logo path", ex); } + if (PlatformUtil.is64BitJVM()) { + try { + initialMemValue = Long.toString(getCurrentJvmMaxMemoryInGB()); + } catch (IOException ex) { + logger.log(Level.INFO, "Can't read current Jvm setting from file", ex); + memField.setEnabled(false); + invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_configFileMissing_text(PlatformUtil.getInstallPath())); + } + memField.setText(initialMemValue); + } } private void updateAgencyLogo(String path) throws IOException { @@ -87,7 +254,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { BufferedImage image = ImageIO.read(file); //create it as an image first to support BMP files if (image == null) { throw new IOException("Unable to read file as a BufferedImage for file " + file.toString()); - } + } agencyLogoIcon = new ImageIcon(image.getScaledInstance(64, 64, 4)); agencyLogoPreview.setText(""); } @@ -109,10 +276,17 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { ModuleSettings.setConfigSetting(ReportBranding.MODULE_NAME, ReportBranding.AGENCY_LOGO_PATH_PROP, agencyLogoPathField.getText()); } } + try { + if (memField.isEnabled()) { //if the field can't of been changed we don't need to save it + writeEtcConfFile(); + } + } catch (IOException ex) { + logger.log(Level.WARNING, "Unable to save config file to " + PlatformUtil.getUserDirectory() + "\\etc", ex); + } } boolean valid() { - return true; + return validateMemField(); } /** @@ -145,6 +319,14 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { jLabelTimeDisplay = new javax.swing.JLabel(); useLocalTimeRB = new javax.swing.JRadioButton(); useGMTTimeRB = new javax.swing.JRadioButton(); + runtimePanel = new javax.swing.JPanel(); + maxMemoryLabel = new javax.swing.JLabel(); + maxMemoryUnitsLabel = new javax.swing.JLabel(); + totalMemoryLabel = new javax.swing.JLabel(); + systemMemoryTotal = new javax.swing.JLabel(); + restartNecessaryWarning = new javax.swing.JLabel(); + memField = new javax.swing.JTextField(); + invalidReasonLabel = new javax.swing.JLabel(); jScrollPane1.setBorder(null); @@ -187,7 +369,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addComponent(browseLogosButton))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(agencyLogoPreview, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addContainerGap(149, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); logoPanelLayout.setVerticalGroup( logoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -286,20 +468,29 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addGroup(viewPanelLayout.createSequentialGroup() .addGap(10, 10, 10) .addGroup(viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(useGMTTimeRB) - .addComponent(keepCurrentViewerRB) - .addComponent(useBestViewerRB) - .addGroup(viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(viewPanelLayout.createSequentialGroup() + .addGroup(viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(dataSourcesHideSlackCB) + .addComponent(viewsHideSlackCB)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(viewPanelLayout.createSequentialGroup() + .addGroup(viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(useGMTTimeRB) + .addComponent(keepCurrentViewerRB) + .addComponent(useBestViewerRB) + .addComponent(dataSourcesHideKnownCB) + .addComponent(viewsHideKnownCB)) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(viewPanelLayout.createSequentialGroup() .addComponent(useLocalTimeRB) - .addComponent(dataSourcesHideSlackCB) - .addComponent(viewsHideSlackCB) - .addComponent(dataSourcesHideKnownCB) - .addComponent(viewsHideKnownCB)))) - .addComponent(jLabelHideSlackFiles) - .addComponent(jLabelTimeDisplay) - .addComponent(jLabelHideKnownFiles) - .addComponent(jLabelSelectFile)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) + .addGroup(viewPanelLayout.createSequentialGroup() + .addGroup(viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabelHideSlackFiles) + .addComponent(jLabelTimeDisplay) + .addComponent(jLabelHideKnownFiles) + .addComponent(jLabelSelectFile)) + .addGap(30, 30, 30)))) ); viewPanelLayout.setVerticalGroup( viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -330,6 +521,82 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addComponent(useGMTTimeRB)) ); + runtimePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.runtimePanel.border.title"))); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(maxMemoryLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.maxMemoryLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(maxMemoryUnitsLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.maxMemoryUnitsLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(totalMemoryLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.totalMemoryLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(restartNecessaryWarning, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.restartNecessaryWarning.text")); // NOI18N + + memField.setHorizontalAlignment(javax.swing.JTextField.TRAILING); + memField.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + memFieldActionPerformed(evt); + } + }); + memField.addKeyListener(new java.awt.event.KeyAdapter() { + public void keyPressed(java.awt.event.KeyEvent evt) { + memFieldKeyPressed(evt); + } + public void keyReleased(java.awt.event.KeyEvent evt) { + memFieldKeyReleased(evt); + } + public void keyTyped(java.awt.event.KeyEvent evt) { + memFieldKeyTyped(evt); + } + }); + + invalidReasonLabel.setForeground(new java.awt.Color(255, 0, 0)); + + javax.swing.GroupLayout runtimePanelLayout = new javax.swing.GroupLayout(runtimePanel); + runtimePanel.setLayout(runtimePanelLayout); + runtimePanelLayout.setHorizontalGroup( + runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(runtimePanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addGroup(runtimePanelLayout.createSequentialGroup() + .addComponent(totalMemoryLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(systemMemoryTotal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(runtimePanelLayout.createSequentialGroup() + .addComponent(maxMemoryLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(memField, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(maxMemoryUnitsLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(restartNecessaryWarning, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(invalidReasonLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + runtimePanelLayout.setVerticalGroup( + runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(runtimePanelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(maxMemoryUnitsLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(memField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(maxMemoryLabel)) + .addComponent(invalidReasonLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(runtimePanelLayout.createSequentialGroup() + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(totalMemoryLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(systemMemoryTotal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + .addGroup(runtimePanelLayout.createSequentialGroup() + .addGap(11, 11, 11) + .addComponent(restartNecessaryWarning))) + .addGap(0, 0, 0)) + ); + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( @@ -338,6 +605,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addContainerGap() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(viewPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(runtimePanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(logoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); @@ -347,6 +615,8 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addGap(0, 0, 0) .addComponent(viewPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0) + .addComponent(runtimePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) .addComponent(logoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0)) ); @@ -358,14 +628,12 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 672, Short.MAX_VALUE) + .addComponent(jScrollPane1) .addGap(0, 0, 0)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 489, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) ); }// //GEN-END:initComponents @@ -424,6 +692,59 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } }//GEN-LAST:event_browseLogosButtonActionPerformed + private void up() { + String memText = memField.getText(); + if (memText.equals(initialMemValue)) { + System.out.println("hasn't changed don't fire"); + return; + } + firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); + } + private void memFieldKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_memFieldKeyPressed + up(); + }//GEN-LAST:event_memFieldKeyPressed + + private void memFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_memFieldKeyReleased + up(); + }//GEN-LAST:event_memFieldKeyReleased + + private void memFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_memFieldKeyTyped + up(); + }//GEN-LAST:event_memFieldKeyTyped + + private void memFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_memFieldActionPerformed + // TODO add your handling code here: + }//GEN-LAST:event_memFieldActionPerformed + + private boolean validateMemField() { + String memText = memField.getText(); + invalidReasonLabel.setText(""); + if (!memField.isEnabled()) { + invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_not64BitInstall_text()); + return true; + } + + if (memText.length() == 0) { + invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_noValueEntered_text()); + return false; + } + if (memText.replaceAll("[^\\d]", "").length() != memText.length()) { + invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_invalidCharacters_text()); + return false; + } + int parsedInt = Integer.parseInt(memText); + if (parsedInt < HARD_MIN_MEMORY_IN_GB) { + invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_underMinMemory_text(SOFT_MIN_MEMORY_IN_GB)); + return false; + } + if (parsedInt >= getSystemMemoryInGB()) { + invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_overMaxMemory_text(getSystemMemoryInGB())); + return false; + } + + return true; + } + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel agencyLogoImageLabel; private javax.swing.JTextField agencyLogoPathField; @@ -433,6 +754,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private javax.swing.ButtonGroup buttonGroup3; private javax.swing.JCheckBox dataSourcesHideKnownCB; private javax.swing.JCheckBox dataSourcesHideSlackCB; + private javax.swing.JLabel invalidReasonLabel; private javax.swing.JLabel jLabelHideKnownFiles; private javax.swing.JLabel jLabelHideSlackFiles; private javax.swing.JLabel jLabelSelectFile; @@ -441,6 +763,13 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private javax.swing.JScrollPane jScrollPane1; private javax.swing.JRadioButton keepCurrentViewerRB; private javax.swing.JPanel logoPanel; + private javax.swing.JLabel maxMemoryLabel; + private javax.swing.JLabel maxMemoryUnitsLabel; + private javax.swing.JTextField memField; + private javax.swing.JLabel restartNecessaryWarning; + private javax.swing.JPanel runtimePanel; + private javax.swing.JLabel systemMemoryTotal; + private javax.swing.JLabel totalMemoryLabel; private javax.swing.JRadioButton useBestViewerRB; private javax.swing.JRadioButton useGMTTimeRB; private javax.swing.JRadioButton useLocalTimeRB; @@ -448,4 +777,5 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private javax.swing.JCheckBox viewsHideKnownCB; private javax.swing.JCheckBox viewsHideSlackCB; // End of variables declaration//GEN-END:variables + } From 80705a39f7109a8b6cc4a9c21f01bc298c03f447 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 1 Dec 2017 13:24:05 -0500 Subject: [PATCH 80/90] 3226 add 4 gigabyte default JVM heap size for developers --- nbproject/project.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nbproject/project.properties b/nbproject/project.properties index ac6c347444..04a6d5800b 100755 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -16,7 +16,7 @@ update_versions=false #custom JVM options #Note: can be higher on 64 bit systems, should be in sync with build.xml # for Japanese version add: -J-Duser.language=ja -run.args.extra=-J-Xms24m -J-XX:MaxPermSize=128M -J-Xverify:none -J-XX:+UseG1GC -J-XX:+UseStringDeduplication +run.args.extra=-J-Xms24m -J-Xmx4g -J-XX:MaxPermSize=128M -J-Xverify:none -J-XX:+UseG1GC -J-XX:+UseStringDeduplication auxiliary.org-netbeans-modules-apisupport-installer.license-type=apache.v2 auxiliary.org-netbeans-modules-apisupport-installer.os-linux=false auxiliary.org-netbeans-modules-apisupport-installer.os-macosx=false From e7c38d3f263c6936b53768289e200fabff50a11e Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 1 Dec 2017 14:30:04 -0500 Subject: [PATCH 81/90] 3226 clean up memory settings code and add additional comments --- .../corecomponents/AutopsyOptionsPanel.form | 3 - .../corecomponents/AutopsyOptionsPanel.java | 209 +++++++++++------- 2 files changed, 124 insertions(+), 88 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form index aebb685756..5f3ea9f6e6 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form @@ -504,10 +504,7 @@ - - - diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 86750ba738..91e3b179b9 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -70,6 +70,8 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private static final long serialVersionUID = 1L; private final JFileChooser fc; + private static final String ETC_FOLDER_NAME = "etc"; + private static final String CONFIG_FILE_EXTENSION = ".conf"; private static final long ONE_BILLION = 1000000000L; //used to roughly convert system memory from bytes to gigabytes private static final long MEGA_IN_GIGA = 1024; //used to convert memory settings saved as megabytes to gigabytes private static final int HARD_MIN_MEMORY_IN_GB = 2; //the enforced minimum memory in gigabytes @@ -95,12 +97,23 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { systemMemoryTotal.setText(Long.toString(getSystemMemoryInGB())); } + /** + * Get the total system memory in gigabytes which exists on the machine + * which the application is running. + * + * @return the total system memory + */ private long getSystemMemoryInGB() { long memorySize = ((com.sun.management.OperatingSystemMXBean) ManagementFactory .getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); return memorySize / ONE_BILLION; } + /** + * Gets the currently saved max java heap space in gigabytes. + * + * @return @throws IOException when unable to get a valid setting + */ private long getCurrentJvmMaxMemoryInGB() throws IOException { String currentXmx = getCurrentXmxValue(); char units = '-'; @@ -111,6 +124,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } else { throw new IOException("No memory setting found in String: " + currentXmx); } + //some older .conf files might have the units as megabytes instead of gigabytes switch (units) { case 'g': case 'G': @@ -123,28 +137,27 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } } + /* + * The value currently saved in the conf file as the max java heap space + * available to this application. Form will be an integer followed by a + * character indicating units. Helper method for + * getCurrentJvmMaxMemoryInGB() + * + * @return the saved value for the max java heap space + * + * @throws IOException if the conf file does not exist in either the user + * directory or the install directory + */ private String getCurrentXmxValue() throws IOException { - File userFolder = PlatformUtil.getUserDirectory(); - File userEtcFolder = new File(userFolder, "etc"); - String confFile = Version.getName() + ".conf"; - File userEtcConfigFile = new File(userEtcFolder, confFile); String[] settings; String currentSetting = ""; - if (!userEtcConfigFile.exists()) { - String installFolder = PlatformUtil.getInstallPath(); - File installFolderEtc = new File(installFolder, "etc"); - File installFolderConfigFile = new File(installFolderEtc, confFile); - if (installFolderConfigFile.exists()) { - settings = getDefaultsFromFileContents(readConfFile(installFolderConfigFile)); - //copy install folder config - } else { - throw new IOException("Conf file could not be found, software may not be properly installed. " + installFolderConfigFile.toString()); - } + File userConfFile = getInstallFolderConfFile(); + if (!userConfFile.exists()) { + settings = getDefaultsFromFileContents(readConfFile(getInstallFolderConfFile())); } else { - settings = getDefaultsFromFileContents(readConfFile(userEtcConfigFile)); + settings = getDefaultsFromFileContents(readConfFile(userConfFile)); } for (String option : settings) { - System.out.println("Setting: " + option); if (option.startsWith("-J-Xmx")) { currentSetting = option.replace("-J-Xmx", "").trim(); } @@ -152,58 +165,106 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { return currentSetting; } - private void writeEtcConfFile() throws IOException { - String confFileName = Version.getName() + ".conf"; - File userFolder = PlatformUtil.getUserDirectory(); - File userEtcFolder = new File(userFolder, "etc"); - File userEtcConfigFile = new File(userEtcFolder, confFileName); + /** + * Get the conf file from the install directory which stores the default + * values for the settings. + * + * @return the file which has the applications default .conf file + * + * @throws IOException when the file does not exist. + */ + private static File getInstallFolderConfFile() throws IOException { + String confFileName = Version.getName() + CONFIG_FILE_EXTENSION; String installFolder = PlatformUtil.getInstallPath(); - File installFolderEtc = new File(installFolder, "etc"); + File installFolderEtc = new File(installFolder, ETC_FOLDER_NAME); File installFolderConfigFile = new File(installFolderEtc, confFileName); - StringBuilder content = new StringBuilder(); - if (installFolderConfigFile.exists()) { - List confFile = readConfFile(installFolderConfigFile); - for (String line : confFile) { - if (line.contains("-J-Xmx")) { - // content.append("default_options=\""); - String[] splitLine = line.split(" "); - //.replace("default_options=", "").replaceAll("\"", "") - StringJoiner modifiedLine = new StringJoiner(" "); - - for (String piece : splitLine) { - if (piece.contains("-J-Xmx")) { - piece = "-J-Xmx" + memField.getText() + "g"; - } - modifiedLine.add(piece); - } - content.append(modifiedLine.toString()); - // content.append("\""); - } else { - content.append(line); - } - content.append("\n"); - } - Files.write(userEtcConfigFile.toPath(), content.toString().getBytes()); - //copy install folder config - } else { + if (!installFolderConfigFile.exists()) { throw new IOException("Conf file could not be found, software may not be properly installed. " + installFolderConfigFile.toString()); } + return installFolderConfigFile; } - private static List readConfFile(File ctConfigFile) { + /** + * Get the conf file from the directory which stores the currently in use + * settings. Creates the directory for the file if the directory does not + * exist. + * + * @return the file which has the applications current .conf file + */ + private static File getUserFolderConfFile() { + String confFileName = Version.getName() + CONFIG_FILE_EXTENSION; + File userFolder = PlatformUtil.getUserDirectory(); + File userEtcFolder = new File(userFolder, ETC_FOLDER_NAME); + if (!userEtcFolder.exists()) { + userEtcFolder.mkdir(); + } + return new File(userEtcFolder, confFileName); + } + + /** + * Take the conf file in the install directory and save a copy of it to the + * user directory. The copy will be modified to include the current memory + * setting. + * + * @throws IOException when unable to write a conf file or access the + * install folders conf file + */ + private void writeEtcConfFile() throws IOException { + StringBuilder content = new StringBuilder(); + List confFile = readConfFile(getInstallFolderConfFile()); + for (String line : confFile) { + if (line.contains("-J-Xmx")) { + String[] splitLine = line.split(" "); + StringJoiner modifiedLine = new StringJoiner(" "); + for (String piece : splitLine) { + if (piece.contains("-J-Xmx")) { + piece = "-J-Xmx" + memField.getText() + "g"; + } + modifiedLine.add(piece); + } + content.append(modifiedLine.toString()); + } else { + content.append(line); + } + content.append("\n"); + } + Files.write(getUserFolderConfFile().toPath(), content.toString().getBytes()); + } + + /** + * Reads a conf file line by line putting each line into a list of strings + * which will be returned. + * + * @param configFile the .conf file which you wish to read. + * + * @return a list of strings with a string for each line in the conf file + * specified. + */ + private static List readConfFile(File configFile) { List lines = new ArrayList<>(); - if (null != ctConfigFile) { - Path filePath = ctConfigFile.toPath(); + if (null != configFile) { + Path filePath = configFile.toPath(); Charset charset = Charset.forName("UTF-8"); try { lines = Files.readAllLines(filePath, charset); } catch (IOException e) { - logger.log(Level.SEVERE, "Error reading config file contents. {}", ctConfigFile.getAbsolutePath()); + logger.log(Level.SEVERE, "Error reading config file contents. {}", configFile.getAbsolutePath()); } } return lines; } + /** + * Find the string in the list of strings which contains the default options + * settings and split it into an array of strings containing one element for + * each setting specified. + * + * @param list a list of string representing lines of a .conf file + * + * @return an array of strings for each argument on the line which has the + * default options, returns an empty array of Strings if default + * options is not present. + */ private static String[] getDefaultsFromFileContents(List list) { Optional defaultSettings = list.stream().filter(line -> line.startsWith("default_options=")).findFirst(); @@ -281,12 +342,12 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { writeEtcConfFile(); } } catch (IOException ex) { - logger.log(Level.WARNING, "Unable to save config file to " + PlatformUtil.getUserDirectory() + "\\etc", ex); + logger.log(Level.WARNING, "Unable to save config file to " + PlatformUtil.getUserDirectory() + "\\" + ETC_FOLDER_NAME, ex); } } boolean valid() { - return validateMemField(); + return isMemFieldValid(); } /** @@ -532,21 +593,10 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { org.openide.awt.Mnemonics.setLocalizedText(restartNecessaryWarning, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.restartNecessaryWarning.text")); // NOI18N memField.setHorizontalAlignment(javax.swing.JTextField.TRAILING); - memField.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - memFieldActionPerformed(evt); - } - }); memField.addKeyListener(new java.awt.event.KeyAdapter() { public void keyPressed(java.awt.event.KeyEvent evt) { memFieldKeyPressed(evt); } - public void keyReleased(java.awt.event.KeyEvent evt) { - memFieldKeyReleased(evt); - } - public void keyTyped(java.awt.event.KeyEvent evt) { - memFieldKeyTyped(evt); - } }); invalidReasonLabel.setForeground(new java.awt.Color(255, 0, 0)); @@ -692,38 +742,28 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } }//GEN-LAST:event_browseLogosButtonActionPerformed - private void up() { + private void memFieldKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_memFieldKeyPressed String memText = memField.getText(); if (memText.equals(initialMemValue)) { - System.out.println("hasn't changed don't fire"); + //if it is still the initial value don't fire change return; } firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - } - private void memFieldKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_memFieldKeyPressed - up(); }//GEN-LAST:event_memFieldKeyPressed - private void memFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_memFieldKeyReleased - up(); - }//GEN-LAST:event_memFieldKeyReleased - - private void memFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_memFieldKeyTyped - up(); - }//GEN-LAST:event_memFieldKeyTyped - - private void memFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_memFieldActionPerformed - // TODO add your handling code here: - }//GEN-LAST:event_memFieldActionPerformed - - private boolean validateMemField() { + /** + * Checks that if the mem field is enabled it has a valid value. + * + * @return true if the memfield is valid false if it is not + */ + private boolean isMemFieldValid() { String memText = memField.getText(); invalidReasonLabel.setText(""); if (!memField.isEnabled()) { invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_not64BitInstall_text()); + //the panel should be valid when the memfield is disabled return true; } - if (memText.length() == 0) { invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_noValueEntered_text()); return false; @@ -741,7 +781,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_overMaxMemory_text(getSystemMemoryInGB())); return false; } - return true; } From 51eac3dfa9c436de02df871574183a61f5e7c61b Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Fri, 1 Dec 2017 15:27:50 -0500 Subject: [PATCH 82/90] open CR case by Autopsy Case, error if DB doesn't exist, return case after creating --- .../casemodule/CasePropertiesPanel.java | 5 ++- .../casemodule/NewCaseWizardAction.java | 2 +- .../OptionalCasePropertiesPanel.java | 4 +-- .../DataContentViewerOtherCases.java | 2 +- .../datamodel/AbstractSqlEamDb.java | 31 ++++++++++------- .../datamodel/CorrelationCase.java | 8 ++--- .../datamodel/EamArtifactUtil.java | 10 +++--- .../centralrepository/datamodel/EamDb.java | 15 +++++++-- .../datamodel/SqliteEamDb.java | 22 ++++++------- .../eventlisteners/CaseEventListener.java | 25 +++----------- .../ingestmodule/IngestModule.java | 33 +++++++------------ 11 files changed, 71 insertions(+), 86 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesPanel.java index 23e9d0b1c8..101f8688dd 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesPanel.java @@ -78,10 +78,9 @@ final class CasePropertiesPanel extends javax.swing.JPanel { try { EamDb dbManager = EamDb.getInstance(); if (dbManager != null) { - CorrelationCase correlationCase = dbManager.getCaseByUUID(Case.getCurrentCase().getName()); + CorrelationCase correlationCase = dbManager.getCase(Case.getCurrentCase()); if (null == correlationCase) { - dbManager.newCase(Case.getCurrentCase()); - correlationCase = dbManager.getCaseByUUID(Case.getCurrentCase().getName()); + correlationCase = dbManager.newCase(Case.getCurrentCase()); } currentOrg = correlationCase.getOrg(); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java index 7a4a1f7bf4..89d527fcc1 100755 --- a/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/NewCaseWizardAction.java @@ -91,7 +91,7 @@ final class NewCaseWizardAction extends CallableSystemAction { if (EamDb.isEnabled()) { //if the eam is enabled we need to save the case organization information now EamDb dbManager = EamDb.getInstance(); if (dbManager != null) { - CorrelationCase cRCase = dbManager.getCaseByUUID(Case.getCurrentCase().getName()); + CorrelationCase cRCase = dbManager.getCase(Case.getCurrentCase()); if (cRCase == null) { cRCase = dbManager.newCase(Case.getCurrentCase()); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/OptionalCasePropertiesPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/OptionalCasePropertiesPanel.java index a2793ec295..0a9649c45d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/OptionalCasePropertiesPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/OptionalCasePropertiesPanel.java @@ -89,7 +89,7 @@ final class OptionalCasePropertiesPanel extends javax.swing.JPanel { if (currentCase != null) { try { EamDb dbManager = EamDb.getInstance(); - selectedOrg = dbManager.getCaseByUUID(currentCase.getName()).getOrg(); + selectedOrg = dbManager.getCase(currentCase).getOrg(); } catch (EamDbException ex) { LOGGER.log(Level.SEVERE, "Unable to get Organization associated with the case from Central Repo", ex); } @@ -561,7 +561,7 @@ final class OptionalCasePropertiesPanel extends javax.swing.JPanel { if (EamDb.isEnabled()) { try { EamDb dbManager = EamDb.getInstance(); - CorrelationCase correlationCase = dbManager.getCaseByUUID(Case.getCurrentCase().getName()); + CorrelationCase correlationCase = dbManager.getCase(Case.getCurrentCase()); if (caseDisplayNameTextField.isVisible()) { correlationCase.setDisplayName(caseDisplayNameTextField.getText()); } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index 2a7fcf168b..fbc955ca72 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -177,7 +177,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D } caseDisplayName = eamCasePartial.getDisplayName(); // query case details - CorrelationCase eamCase = dbManager.getCaseByUUID(eamCasePartial.getCaseUUID()); + CorrelationCase eamCase = dbManager.getCase(Case.getCurrentCase()); if (eamCase == null) { JOptionPane.showConfirmDialog(showCaseDetailsMenuItem, Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(), diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index f9c2435472..9560d635c4 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -170,9 +170,10 @@ public abstract class AbstractSqlEamDb implements EamDb { * Expects the Organization for this case to already exist in the database. * * @param eamCase The case to add + * @returns New Case class with populated database ID */ @Override - public void newCase(CorrelationCase eamCase) throws EamDbException { + public CorrelationCase newCase(CorrelationCase eamCase) throws EamDbException { Connection conn = connect(); PreparedStatement preparedStatement = null; @@ -225,6 +226,9 @@ public abstract class AbstractSqlEamDb implements EamDb { EamDbUtil.closePreparedStatement(preparedStatement); EamDbUtil.closeConnection(conn); } + + // get a new version with the updated ID + return getCaseByUUID(eamCase.getCaseUUID()); } /** @@ -249,9 +253,14 @@ public abstract class AbstractSqlEamDb implements EamDb { autopsyCase.getExaminerEmail(), autopsyCase.getExaminerPhone(), autopsyCase.getCaseNotes()); - newCase(curCeCase); - return curCeCase; + return newCase(curCeCase); } + + @Override + public CorrelationCase getCase(Case autopsyCase) throws EamDbException { + return getCaseByUUID(autopsyCase.getName()); + } + /** * Updates an existing Case in the database @@ -432,7 +441,7 @@ public abstract class AbstractSqlEamDb implements EamDb { * @return The data source */ @Override - public CorrelationDataSource getDataSourceDetails(CorrelationCase correlationCase, String dataSourceDeviceId) throws EamDbException { + public CorrelationDataSource getDataSource(CorrelationCase correlationCase, String dataSourceDeviceId) throws EamDbException { Connection conn = connect(); CorrelationDataSource eamDataSourceResult = null; @@ -450,7 +459,7 @@ public abstract class AbstractSqlEamDb implements EamDb { eamDataSourceResult = getEamDataSourceFromResultSet(resultSet); } } catch (SQLException ex) { - throw new EamDbException("Error getting case details.", ex); // NON-NLS + throw new EamDbException("Error getting data source.", ex); // NON-NLS } finally { EamDbUtil.closePreparedStatement(preparedStatement); EamDbUtil.closeResultSet(resultSet); @@ -1057,12 +1066,12 @@ public abstract class AbstractSqlEamDb implements EamDb { // We could improve effiency by keeping a list of all datasources and cases // in the database, but we don't expect the user to be tagging large numbers // of items (that didn't have the CE ingest module run on them) at once. - CorrelationCase correlationCase = getCaseByUUID(eamInstance.getCorrelationCase().getCaseUUID()); - if (null == correlationCase) { - newCase(eamInstance.getCorrelationCase()); - correlationCase = getCaseByUUID(eamInstance.getCorrelationCase().getCaseUUID()); + CorrelationCase correlationCaseWithId = getCaseByUUID(eamInstance.getCorrelationCase().getCaseUUID()); + if (null == correlationCaseWithId) { + correlationCaseWithId = newCase(eamInstance.getCorrelationCase()); } - if (null == getDataSourceDetails(correlationCase, eamInstance.getCorrelationDataSource().getDeviceID())) { + + if (null == getDataSource(correlationCaseWithId, eamInstance.getCorrelationDataSource().getDeviceID())) { newDataSource(eamInstance.getCorrelationDataSource()); } eamArtifact.getInstances().get(0).setKnownStatus(knownStatus); @@ -2146,7 +2155,7 @@ public abstract class AbstractSqlEamDb implements EamDb { return null; } CorrelationAttributeInstance eamArtifactInstance = new CorrelationAttributeInstance( - new CorrelationCase(resultSet.getString("case_uid"), resultSet.getString("case_name")), + new CorrelationCase(resultSet.getInt("case_id"), resultSet.getString("case_uid"), resultSet.getString("case_name")), new CorrelationDataSource(-1, resultSet.getInt("case_id"), resultSet.getString("device_id"), resultSet.getString("name")), resultSet.getString("file_path"), resultSet.getString("comment"), diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationCase.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationCase.java index 466c73a7ee..79d94837ee 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationCase.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationCase.java @@ -49,16 +49,12 @@ public class CorrelationCase implements Serializable { * * @param caseUUID Globally unique identifier * @param displayName - */ - public CorrelationCase(String caseUUID, String displayName) { - this(-1, caseUUID, null, displayName, DATE_FORMAT.format(new Date()), null, null, null, null, null); - } - + */ CorrelationCase(int ID, String caseUUID, String displayName) { this(ID, caseUUID, null, displayName, DATE_FORMAT.format(new Date()), null, null, null, null, null); } - public CorrelationCase(int ID, + CorrelationCase(int ID, String caseUUID, EamOrganization org, String displayName, diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java index b3194e4b7f..c2bb0e0016 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java @@ -96,10 +96,9 @@ public class EamArtifactUtil { } // make an instance for the BB source file - CorrelationCase correlationCase = EamDb.getInstance().getCaseByUUID(Case.getCurrentCase().getName()); + CorrelationCase correlationCase = EamDb.getInstance().getCase(Case.getCurrentCase()); if (null == correlationCase) { - EamDb.getInstance().newCase(Case.getCurrentCase()); - correlationCase = EamDb.getInstance().getCaseByUUID(Case.getCurrentCase().getName()); + correlationCase = EamDb.getInstance().newCase(Case.getCurrentCase()); } CorrelationAttributeInstance eamInstance = new CorrelationAttributeInstance( correlationCase, @@ -250,10 +249,9 @@ public class EamArtifactUtil { try { CorrelationAttribute.Type filesType = EamDb.getInstance().getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); eamArtifact = new CorrelationAttribute(filesType, af.getMd5Hash()); - CorrelationCase correlationCase = EamDb.getInstance().getCaseByUUID(Case.getCurrentCase().getName()); + CorrelationCase correlationCase = EamDb.getInstance().getCase(Case.getCurrentCase()); if (null == correlationCase) { - EamDb.getInstance().newCase(Case.getCurrentCase()); - correlationCase = EamDb.getInstance().getCaseByUUID(Case.getCurrentCase().getName()); + correlationCase = EamDb.getInstance().newCase(Case.getCurrentCase()); } CorrelationAttributeInstance cei = new CorrelationAttributeInstance( correlationCase, diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java index 5f2cdfa816..fa53f00b24 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java @@ -141,7 +141,7 @@ public interface EamDb { * * @param eamCase The case to add */ - void newCase(CorrelationCase eamCase) throws EamDbException; + CorrelationCase newCase(CorrelationCase eamCase) throws EamDbException; /** * Creates new Case in the database from the given case @@ -149,6 +149,8 @@ public interface EamDb { * @param autopsyCase The case to add */ CorrelationCase newCase(Case autopsyCase) throws EamDbException; + + /** * Updates an existing Case in the database @@ -157,6 +159,15 @@ public interface EamDb { */ void updateCase(CorrelationCase eamCase) throws EamDbException; + /** + * Retrieves Central Repo case based on an Autopsy Case + * + * @param autopsyCase Autopsy case to find corresponding CR case for + * @return CR Case + * @throws EamDbException + */ + CorrelationCase getCase(Case autopsyCase) throws EamDbException; + /** * Retrieves Case details based on Case UUID * @@ -189,7 +200,7 @@ public interface EamDb { * * @return The data source */ - CorrelationDataSource getDataSourceDetails(CorrelationCase correlationCase, String dataSourceDeviceId) throws EamDbException; + CorrelationDataSource getDataSource(CorrelationCase correlationCase, String dataSourceDeviceId) throws EamDbException; /** * Retrieves data sources that are in DB diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java index 3e79f5abca..85fda8d4a1 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java @@ -149,16 +149,14 @@ public class SqliteEamDb extends AbstractSqlEamDb { * */ private void setupConnectionPool() throws EamDbException { + + if (dbSettings.dbFileExists() == false) { + throw new EamDbException("Central repository database missing"); + } + connectionPool = new BasicDataSource(); connectionPool.setDriverClassName(dbSettings.getDriver()); - - StringBuilder connectionURL = new StringBuilder(); - connectionURL.append(dbSettings.getJDBCBaseURI()); - connectionURL.append(dbSettings.getDbDirectory()); - connectionURL.append(File.separator); - connectionURL.append(dbSettings.getDbName()); - - connectionPool.setUrl(connectionURL.toString()); + connectionPool.setUrl(dbSettings.getConnectionURL()); // tweak pool configuration connectionPool.setInitialSize(50); @@ -279,10 +277,10 @@ public class SqliteEamDb extends AbstractSqlEamDb { * @param eamCase The case to add */ @Override - public void newCase(CorrelationCase eamCase) throws EamDbException { + public CorrelationCase newCase(CorrelationCase eamCase) throws EamDbException { try{ acquireExclusiveLock(); - super.newCase(eamCase); + return super.newCase(eamCase); } finally { releaseExclusiveLock(); } @@ -359,10 +357,10 @@ public class SqliteEamDb extends AbstractSqlEamDb { * @return The data source */ @Override - public CorrelationDataSource getDataSourceDetails(CorrelationCase correlationCase, String dataSourceDeviceId) throws EamDbException { + public CorrelationDataSource getDataSource(CorrelationCase correlationCase, String dataSourceDeviceId) throws EamDbException { try{ acquireSharedLock(); - return super.getDataSourceDetails(correlationCase, dataSourceDeviceId); + return super.getDataSource(correlationCase, dataSourceDeviceId); } finally { releaseSharedLock(); } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index dbe17d6e6d..e5b2f185ee 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -315,12 +315,11 @@ final class CaseEventListener implements PropertyChangeListener { try { String deviceId = Case.getCurrentCase().getSleuthkitCase().getDataSource(newDataSource.getId()).getDeviceId(); - CorrelationCase correlationCase = dbManager.getCaseByUUID(Case.getCurrentCase().getName()); + CorrelationCase correlationCase = dbManager.getCase(Case.getCurrentCase()); if (null == correlationCase) { - dbManager.newCase(Case.getCurrentCase()); - correlationCase = dbManager.getCaseByUUID(Case.getCurrentCase().getName()); + correlationCase = dbManager.newCase(Case.getCurrentCase()); } - if (null == dbManager.getDataSourceDetails(correlationCase, deviceId)) { + if (null == dbManager.getDataSource(correlationCase, deviceId)) { dbManager.newDataSource(CorrelationDataSource.fromTSKDataSource(correlationCase, newDataSource)); } } catch (EamDbException ex) { @@ -351,18 +350,6 @@ final class CaseEventListener implements PropertyChangeListener { Case curCase = (Case) event.getNewValue(); IngestEventsListener.resetCeModuleInstanceCount(); - CorrelationCase curCeCase = new CorrelationCase( - -1, - curCase.getName(), // unique case ID - EamOrganization.getDefault(), - curCase.getDisplayName(), - curCase.getCreatedDate(), - curCase.getNumber(), - curCase.getExaminer(), - curCase.getExaminerEmail(), - curCase.getExaminerPhone(), - curCase.getCaseNotes()); - if (!EamDb.isEnabled()) { return; } @@ -370,10 +357,8 @@ final class CaseEventListener implements PropertyChangeListener { try { // NOTE: Cannot determine if the opened case is a new case or a reopened case, // so check for existing name in DB and insert if missing. - CorrelationCase existingCase = dbManager.getCaseByUUID(curCeCase.getCaseUUID()); - - if (null == existingCase) { - dbManager.newCase(curCeCase); + if (dbManager.getCase(curCase) == null) { + dbManager.newCase(curCase); } } catch (EamDbException ex) { LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); //NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java index 30d374f133..9e1e36cb8a 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java @@ -201,47 +201,36 @@ class IngestModule implements FileIngestModule { } jobId = context.getJobId(); - EamDb dbManager; + EamDb centralRepoDb; try { - dbManager = EamDb.getInstance(); + centralRepoDb = EamDb.getInstance(); } catch (EamDbException ex) { LOGGER.log(Level.SEVERE, "Error connecting to central repository database.", ex); // NON-NLS throw new IngestModuleException("Error connecting to central repository database.", ex); // NON-NLS } try { - filesType = dbManager.getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); + filesType = centralRepoDb.getCorrelationTypeById(CorrelationAttribute.FILES_TYPE_ID); } catch (EamDbException ex) { LOGGER.log(Level.SEVERE, "Error getting correlation type FILES in ingest module start up.", ex); // NON-NLS throw new IngestModuleException("Error getting correlation type FILES in ingest module start up.", ex); // NON-NLS } - Case curCase = Case.getCurrentCase(); + Case autopsyCase = Case.getCurrentCase(); try { - eamCase = dbManager.getCaseByUUID(curCase.getName()); + eamCase = centralRepoDb.getCase(autopsyCase); } catch (EamDbException ex) { throw new IngestModuleException("Unable to get case from central repository database ", ex); } if (eamCase == null) { // ensure we have this case defined in the EAM DB - CorrelationCase curCeCase = new CorrelationCase( - -1, - curCase.getName(), // unique case ID - EamOrganization.getDefault(), - curCase.getDisplayName(), - curCase.getCreatedDate(), - curCase.getNumber(), - curCase.getExaminer(), - curCase.getExaminerEmail(), - curCase.getExaminerPhone(), - curCase.getCaseNotes()); try { - dbManager.newCase(curCeCase); - eamCase = dbManager.getCaseByUUID(curCase.getName()); + eamCase = centralRepoDb.newCase(autopsyCase); } catch (EamDbException ex) { LOGGER.log(Level.SEVERE, "Error creating new case in ingest module start up.", ex); // NON-NLS throw new IngestModuleException("Error creating new case in ingest module start up.", ex); // NON-NLS } } + try { eamDataSource = CorrelationDataSource.fromTSKDataSource(eamCase, context.getDataSource()); } catch (EamDbException ex) { @@ -255,12 +244,12 @@ class IngestModule implements FileIngestModule { == 1) { // ensure we have this data source in the EAM DB try { - if (null == dbManager.getDataSourceDetails(eamCase, eamDataSource.getDeviceID())) { - dbManager.newDataSource(eamDataSource); + if (null == centralRepoDb.getDataSource(eamCase, eamDataSource.getDeviceID())) { + centralRepoDb.newDataSource(eamDataSource); } } catch (EamDbException ex) { - LOGGER.log(Level.SEVERE, "Error creating new data source in ingest module start up.", ex); // NON-NLS - throw new IngestModuleException("Error creating new data source in ingest module start up.", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Error adding data source to Central Repository.", ex); // NON-NLS + throw new IngestModuleException("Error adding data source to Central Repository.", ex); // NON-NLS } } From 81c677d828bdfad674307e24a9aaae1428c6b95a Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 1 Dec 2017 15:56:02 -0500 Subject: [PATCH 83/90] 3226 check Developer mode for enabling of memory settings --- .../corecomponents/AutopsyOptionsPanel.form | 5 +- .../corecomponents/AutopsyOptionsPanel.java | 47 ++++++++++--------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form index 5f3ea9f6e6..9d8fc97508 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form @@ -494,6 +494,9 @@ + + + @@ -504,7 +507,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 91e3b179b9..b1a9eeb627 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -58,13 +58,14 @@ import org.sleuthkit.autopsy.report.ReportBranding; "AutopsyOptionsPanel.maxMemoryLabel.text=Maximum JVM Memory:", "AutopsyOptionsPanel.maxMemoryUnitsLabel.text=GB", "AutopsyOptionsPanel.runtimePanel.border.title=Runtime", - "AutopsyOptionsPanel.invalidReasonLabel.not64BitInstall.text=JVM memory settings only enabled for installed 64 bit version", + "AutopsyOptionsPanel.invalidReasonLabel.not64BitInstall.text=JVM memory settings only enabled for 64 bit version", "AutopsyOptionsPanel.invalidReasonLabel.noValueEntered.text=No value entered", "AutopsyOptionsPanel.invalidReasonLabel.invalidCharacters.text=Invalid characters, value must be a positive integer", "# {0} - minimumMemory", "AutopsyOptionsPanel.invalidReasonLabel.underMinMemory.text=Value must be at least {0}GB", "# {0} - systemMemory", - "AutopsyOptionsPanel.invalidReasonLabel.overMaxMemory.text=Value must be less than the total system memory of {0}GB"}) + "AutopsyOptionsPanel.invalidReasonLabel.overMaxMemory.text=Value must be less than the total system memory of {0}GB", + "AutopsyOptionsPanel.invalidReasonLabel.developerMode.text=Memory settings are not available while running in developer mode"}) final class AutopsyOptionsPanel extends javax.swing.JPanel { @@ -86,13 +87,12 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { fc.setMultiSelectionEnabled(false); fc.setAcceptAllFileFilterUsed(false); fc.setFileFilter(new GeneralFilter(GeneralFilter.GRAPHIC_IMAGE_EXTS, GeneralFilter.GRAPHIC_IMG_DECR)); - if (!PlatformUtil.is64BitJVM()) { + if (!PlatformUtil.is64BitJVM() || Version.getBuildType() == Version.Type.DEVELOPMENT) { //32 bit JVM has a max heap size of 1.4 gb to 4 gb depending on OS //So disabling the setting of heap size when the JVM is not 64 bit //Is the safest course of action + //And the file won't exist in the install folder when running through netbeans memField.setEnabled(false); - invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_not64BitInstall_text()); - } systemMemoryTotal.setText(Long.toString(getSystemMemoryInGB())); } @@ -179,7 +179,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { File installFolderEtc = new File(installFolder, ETC_FOLDER_NAME); File installFolderConfigFile = new File(installFolderEtc, confFileName); if (!installFolderConfigFile.exists()) { - throw new IOException("Conf file could not be found, software may not be properly installed. " + installFolderConfigFile.toString()); + throw new IOException("Conf file could not be found" + installFolderConfigFile.toString()); } return installFolderConfigFile; } @@ -274,8 +274,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { return new String[]{}; } - @Messages({"# {0} - installedFolder", - "AutopsyOptionsPanel.invalidReasonLabel.configFileMissing.text=Unable to find JVM memory settings in installed folder {0}"}) void load() { boolean keepPreferredViewer = UserPreferences.keepPreferredContentViewer(); keepCurrentViewerRB.setSelected(keepPreferredViewer); @@ -293,16 +291,16 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } catch (IOException ex) { logger.log(Level.WARNING, "Error loading image from previously saved agency logo path", ex); } - if (PlatformUtil.is64BitJVM()) { + if (memField.isEnabled()) { try { initialMemValue = Long.toString(getCurrentJvmMaxMemoryInGB()); } catch (IOException ex) { - logger.log(Level.INFO, "Can't read current Jvm setting from file", ex); + logger.log(Level.SEVERE, "Can't read current Jvm max memory setting from file", ex); memField.setEnabled(false); - invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_configFileMissing_text(PlatformUtil.getInstallPath())); } memField.setText(initialMemValue); } + isMemFieldValid(); //ensure the error message is up to date } private void updateAgencyLogo(String path) throws IOException { @@ -337,12 +335,12 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { ModuleSettings.setConfigSetting(ReportBranding.MODULE_NAME, ReportBranding.AGENCY_LOGO_PATH_PROP, agencyLogoPathField.getText()); } } - try { - if (memField.isEnabled()) { //if the field can't of been changed we don't need to save it + if (memField.isEnabled()) { //if the field could of been changed we need to try and save it + try { writeEtcConfFile(); + } catch (IOException ex) { + logger.log(Level.WARNING, "Unable to save config file to " + PlatformUtil.getUserDirectory() + "\\" + ETC_FOLDER_NAME, ex); } - } catch (IOException ex) { - logger.log(Level.WARNING, "Unable to save config file to " + PlatformUtil.getUserDirectory() + "\\" + ETC_FOLDER_NAME, ex); } } @@ -590,12 +588,13 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { org.openide.awt.Mnemonics.setLocalizedText(totalMemoryLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.totalMemoryLabel.text")); // NOI18N + restartNecessaryWarning.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/warning16.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(restartNecessaryWarning, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.restartNecessaryWarning.text")); // NOI18N memField.setHorizontalAlignment(javax.swing.JTextField.TRAILING); memField.addKeyListener(new java.awt.event.KeyAdapter() { - public void keyPressed(java.awt.event.KeyEvent evt) { - memFieldKeyPressed(evt); + public void keyReleased(java.awt.event.KeyEvent evt) { + memFieldKeyReleased(evt); } }); @@ -742,14 +741,14 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } }//GEN-LAST:event_browseLogosButtonActionPerformed - private void memFieldKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_memFieldKeyPressed + private void memFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_memFieldKeyReleased String memText = memField.getText(); if (memText.equals(initialMemValue)) { //if it is still the initial value don't fire change return; } firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - }//GEN-LAST:event_memFieldKeyPressed + }//GEN-LAST:event_memFieldKeyReleased /** * Checks that if the mem field is enabled it has a valid value. @@ -759,9 +758,14 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private boolean isMemFieldValid() { String memText = memField.getText(); invalidReasonLabel.setText(""); - if (!memField.isEnabled()) { + if (!PlatformUtil.is64BitJVM()) { invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_not64BitInstall_text()); - //the panel should be valid when the memfield is disabled + //the panel should be valid when it is a 32 bit jvm because the memfield will be disabled. + return true; + } + if (Version.getBuildType() == Version.Type.DEVELOPMENT) { + invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_developerMode_text()); + //the panel should be valid when you are running in developer mode because the memfield will be disabled return true; } if (memText.length() == 0) { @@ -783,7 +787,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { } return true; } - // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel agencyLogoImageLabel; private javax.swing.JTextField agencyLogoPathField; From 6bb0c8b70c3967d3b0b9a39496b9b39cb391ecea Mon Sep 17 00:00:00 2001 From: benhbasis <31926879+benhbasis@users.noreply.github.com> Date: Mon, 4 Dec 2017 07:49:32 -0500 Subject: [PATCH 84/90] Update StringsTextExtractor.java At the request of Brian Carrier, as suggested and tested in VIK-2979 --- .../sleuthkit/autopsy/keywordsearch/StringsTextExtractor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/StringsTextExtractor.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/StringsTextExtractor.java index 4ccc8d76c5..7183cf7346 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/StringsTextExtractor.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/StringsTextExtractor.java @@ -152,7 +152,7 @@ class StringsTextExtractor extends FileTextExtractor { private static final Logger logger = Logger.getLogger(EnglishOnlyStream.class.getName()); private static final String NLS = Character.toString((char) 10); //new line - private static final int READ_BUF_SIZE = 256; + private static final int READ_BUF_SIZE = 65536; private static final int MIN_PRINTABLE_CHARS = 4; //num. of chars needed to qualify as a char string //args From 87167854da55e673c9e63249328428cfa1dc961a Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Mon, 4 Dec 2017 15:42:25 -0500 Subject: [PATCH 85/90] Remove completion check from DataSourceIngestJob.cancel --- .../autopsy/ingest/DataSourceIngestJob.java | 32 ++++--------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java index f9caad7683..d07e764be5 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2016 Basis Technology Corp. + * Copyright 2014-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -125,10 +125,9 @@ final class DataSourceIngestJob { * class. */ private volatile boolean currentDataSourceIngestModuleCancelled; + private final List cancelledDataSourceIngestModules = new CopyOnWriteArrayList<>(); private volatile boolean cancelled; private volatile IngestJob.CancellationReason cancellationReason = IngestJob.CancellationReason.NOT_CANCELLED; - private final Object cancellationStateMonitor = new Object(); - private final List cancelledDataSourceIngestModules = new CopyOnWriteArrayList<>(); /** * A data source ingest job uses the task scheduler singleton to create and @@ -989,6 +988,10 @@ final class DataSourceIngestJob { * @param reason The cancellation reason. */ void cancel(IngestJob.CancellationReason reason) { + this.cancelled = true; + this.cancellationReason = reason; + DataSourceIngestJob.taskScheduler.cancelPendingTasksForIngestJob(this); + if (this.doUI) { /** * Put a cancellation message on data source level ingest progress @@ -1023,32 +1026,9 @@ final class DataSourceIngestJob { "IngestJob.progress.fileIngest.cancelMessage", this.currentFileIngestModule, this.currentFileIngestTask)); } - } } } - - /* - * If the work is not already done, show this job as cancelled for the - * given reason. - */ - if (Stages.FINALIZATION != stage) { - synchronized (cancellationStateMonitor) { - /* - * These fields are volatile for reading, synchronized on the - * monitor here for writing. - */ - this.cancelled = true; - this.cancellationReason = reason; - } - } - - /** - * Tell the task scheduler to cancel all pending tasks, i.e., tasks not - * not being performed by an ingest thread. - */ - DataSourceIngestJob.taskScheduler.cancelPendingTasksForIngestJob(this); - this.checkForStageCompleted(); } /** From 4151082c5aed55eff589f4fc1cce8d17e729f624 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Mon, 4 Dec 2017 16:26:14 -0500 Subject: [PATCH 86/90] Remove inaccurate ingest job cancellatino msg details --- .../autopsy/ingest/Bundle.properties | 3 +- .../autopsy/ingest/Bundle_ja.properties | 3 +- .../autopsy/ingest/DataSourceIngestJob.java | 36 ++++--------------- 3 files changed, 9 insertions(+), 33 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties index f23dd57f84..d240310b1c 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties @@ -20,8 +20,7 @@ IngestMessagePanel.totalUniqueMessagesNameVal.text=- IngestJob.progress.dataSourceIngest.initialDisplayName=Analyzing {0} IngestJob.progress.dataSourceIngest.displayName={0} for {1} IngestJob.progress.fileIngest.displayName=Analyzing files from {0} -IngestJob.progress.fileIngest.cancelMessage=Waiting for {0} on {1} -IngestJob.progress.cancelling={0} (Cancelling...) +IngestJob.progress.cancelling=Cancelling... IngestJob.cancellationDialog.title=Cancel Ingest IngestDialog.startButton.title=Start IngestDialog.closeButton.title=Close diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties index f7af8964cc..2fc82d0dd9 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle_ja.properties @@ -2,7 +2,7 @@ CTL_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8 HINT_IngestMessageTopComponent=\u30e1\u30c3\u30bb\u30fc\u30b8\u30a6\u30a3\u30f3\u30c9\u30a6 IngestDialog.closeButton.title=\u9589\u3058\u308b IngestDialog.startButton.title=\u958b\u59cb -IngestJob.progress.cancelling={0}\uff08\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026\uff09 +IngestJob.progress.cancelling=\u30ad\u30e3\u30f3\u30bb\u30eb\u4e2d\u2026 IngestJob.progress.dataSourceIngest.displayName={1}\u306e{0} IngestJob.progress.fileIngest.displayName={0}\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u89e3\u6790\u4e2d IngestManager.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc @@ -90,7 +90,6 @@ IngestProgressSnapshotPanel.SnapshotsTableModel.colNames.jobID=\u30b8\u30e7\u30d ModuleTableModel.colName.module=\u30e2\u30b8\u30e5\u30fc\u30eb Menu/Tools/RunIngestModules=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u5b9f\u884c -IngestJob.progress.fileIngest.cancelMessage={1}\u306e{0}\u3092\u5f85\u3063\u3066\u3044\u307e\u3059 IngestManager.OpenEventChannel.Fail.ErrMsg=\u3053\u306e\u30b1\u30fc\u30b9\u3067\u4f7f\u308f\u308c\u3066\u3044\u308b\u304b\u3082\u3057\u308c\u306a\u3044\u4ed6\u306e\u30ce\u30fc\u30c9\u306b\u89e3\u6790\u30d7\u30ed\u30bb\u30b9\u304c\u63a5\u7d9a\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 IngestManager.OpenEventChannel.Fail.Title=\u63a5\u7d9a\u5931\u6557 IngestJobSettings.moduleSettingsSave.warning={1}\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u306e{0}\u30e2\u30b8\u30e5\u30fc\u30eb\u7528\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30b8\u30e7\u30d6\u8a2d\u5b9a\u3092\u8aad\u307f\u8fbc\u307f\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java index d07e764be5..b8d5b7e359 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/DataSourceIngestJob.java @@ -991,41 +991,19 @@ final class DataSourceIngestJob { this.cancelled = true; this.cancellationReason = reason; DataSourceIngestJob.taskScheduler.cancelPendingTasksForIngestJob(this); - + if (this.doUI) { - /** - * Put a cancellation message on data source level ingest progress - * bar, if it is still running. - */ synchronized (this.dataSourceIngestProgressLock) { - if (dataSourceIngestProgress != null) { - final String displayName = NbBundle.getMessage(this.getClass(), - "IngestJob.progress.dataSourceIngest.initialDisplayName", - dataSource.getName()); - dataSourceIngestProgress.setDisplayName( - NbBundle.getMessage(this.getClass(), - "IngestJob.progress.cancelling", - displayName)); + if (null != dataSourceIngestProgress) { + dataSourceIngestProgress.setDisplayName(NbBundle.getMessage(this.getClass(), "IngestJob.progress.dataSourceIngest.initialDisplayName", dataSource.getName())); + dataSourceIngestProgress.progress(NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling")); } } - /** - * Put a cancellation message on the file level ingest progress bar, - * if it is still running. - */ synchronized (this.fileIngestProgressLock) { - if (this.fileIngestProgress != null) { - final String displayName = NbBundle.getMessage(this.getClass(), - "IngestJob.progress.fileIngest.displayName", - this.dataSource.getName()); - this.fileIngestProgress.setDisplayName( - NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling", - displayName)); - if (!this.currentFileIngestModule.isEmpty() && !this.currentFileIngestTask.isEmpty()) { - this.fileIngestProgress.progress(NbBundle.getMessage(this.getClass(), - "IngestJob.progress.fileIngest.cancelMessage", - this.currentFileIngestModule, this.currentFileIngestTask)); - } + if (null != this.fileIngestProgress) { + this.fileIngestProgress.setDisplayName(NbBundle.getMessage(this.getClass(), "IngestJob.progress.fileIngest.displayName", this.dataSource.getName())); + this.fileIngestProgress.progress(NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling")); } } } From 5f338c4f13dcdcd3b150afa736fb5e721e3703e5 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 5 Dec 2017 11:32:15 -0500 Subject: [PATCH 87/90] 3226 Fixed error displaying current memory setting, and layout issues --- .../corecomponents/AutopsyOptionsPanel.form | 101 +++++++++--------- .../corecomponents/AutopsyOptionsPanel.java | 88 +++++++-------- 2 files changed, 95 insertions(+), 94 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form index 9d8fc97508..2457e1be71 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form @@ -49,12 +49,12 @@ - + - - - + + + @@ -201,13 +201,6 @@ - - - - - - - @@ -218,9 +211,13 @@ - - - + + + + + + + @@ -401,7 +398,7 @@ - + @@ -414,25 +411,25 @@ - - - - - - - - - - - - + + - + + + + + + - - + + - + + + + + + @@ -440,28 +437,22 @@ - - - - - - - + + + + - + + - - - - - - - - - - - + + + + + + + @@ -491,6 +482,9 @@ + + + @@ -517,6 +511,13 @@ + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index b1a9eeb627..9fd8f10734 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -54,7 +54,7 @@ import org.sleuthkit.autopsy.report.ReportBranding; "AutopsyOptionsPanel.invalidImageFile.msg=The selected file was not able to be used as an agency logo.", "AutopsyOptionsPanel.invalidImageFile.title=Invalid Image File", "AutopsyOptionsPanel.restartNecessaryWarning.text=A restart is necessary for any changes to max memory to take effect.", - "AutopsyOptionsPanel.totalMemoryLabel.text=Total System Memory in Gigabytes:", + "AutopsyOptionsPanel.totalMemoryLabel.text=Total System Memory:", "AutopsyOptionsPanel.maxMemoryLabel.text=Maximum JVM Memory:", "AutopsyOptionsPanel.maxMemoryUnitsLabel.text=GB", "AutopsyOptionsPanel.runtimePanel.border.title=Runtime", @@ -75,8 +75,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private static final String CONFIG_FILE_EXTENSION = ".conf"; private static final long ONE_BILLION = 1000000000L; //used to roughly convert system memory from bytes to gigabytes private static final long MEGA_IN_GIGA = 1024; //used to convert memory settings saved as megabytes to gigabytes - private static final int HARD_MIN_MEMORY_IN_GB = 2; //the enforced minimum memory in gigabytes - private static final int SOFT_MIN_MEMORY_IN_GB = 4; //the minimum memory we inform the user is required in gigabytes + private static final int MIN_MEMORY_IN_GB = 2; //the enforced minimum memory in gigabytes private static final Logger logger = Logger.getLogger(AutopsyOptionsPanel.class.getName()); private String initialMemValue = Long.toString(Runtime.getRuntime().maxMemory() / ONE_BILLION); @@ -151,7 +150,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private String getCurrentXmxValue() throws IOException { String[] settings; String currentSetting = ""; - File userConfFile = getInstallFolderConfFile(); + File userConfFile = getUserFolderConfFile(); if (!userConfFile.exists()) { settings = getDefaultsFromFileContents(readConfFile(getInstallFolderConfFile())); } else { @@ -386,6 +385,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { restartNecessaryWarning = new javax.swing.JLabel(); memField = new javax.swing.JTextField(); invalidReasonLabel = new javax.swing.JLabel(); + maxMemoryUnitsLabel1 = new javax.swing.JLabel(); jScrollPane1.setBorder(null); @@ -527,11 +527,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addGroup(viewPanelLayout.createSequentialGroup() .addGap(10, 10, 10) .addGroup(viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(viewPanelLayout.createSequentialGroup() - .addGroup(viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(dataSourcesHideSlackCB) - .addComponent(viewsHideSlackCB)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGroup(viewPanelLayout.createSequentialGroup() .addGroup(viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(useGMTTimeRB) @@ -541,7 +536,10 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addComponent(viewsHideKnownCB)) .addGap(0, 0, Short.MAX_VALUE)) .addGroup(viewPanelLayout.createSequentialGroup() - .addComponent(useLocalTimeRB) + .addGroup(viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(dataSourcesHideSlackCB) + .addComponent(viewsHideSlackCB) + .addComponent(useLocalTimeRB)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) .addGroup(viewPanelLayout.createSequentialGroup() .addGroup(viewPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -588,6 +586,8 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { org.openide.awt.Mnemonics.setLocalizedText(totalMemoryLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.totalMemoryLabel.text")); // NOI18N + systemMemoryTotal.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + restartNecessaryWarning.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/warning16.png"))); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(restartNecessaryWarning, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.restartNecessaryWarning.text")); // NOI18N @@ -600,6 +600,8 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { invalidReasonLabel.setForeground(new java.awt.Color(255, 0, 0)); + org.openide.awt.Mnemonics.setLocalizedText(maxMemoryUnitsLabel1, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.maxMemoryUnitsLabel.text")); // NOI18N + javax.swing.GroupLayout runtimePanelLayout = new javax.swing.GroupLayout(runtimePanel); runtimePanel.setLayout(runtimePanelLayout); runtimePanelLayout.setHorizontalGroup( @@ -607,42 +609,39 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addGroup(runtimePanelLayout.createSequentialGroup() .addContainerGap() .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addGroup(runtimePanelLayout.createSequentialGroup() - .addComponent(totalMemoryLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(systemMemoryTotal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGroup(runtimePanelLayout.createSequentialGroup() - .addComponent(maxMemoryLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(memField, javax.swing.GroupLayout.PREFERRED_SIZE, 70, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(maxMemoryUnitsLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addComponent(maxMemoryLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(totalMemoryLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(systemMemoryTotal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(memField, javax.swing.GroupLayout.DEFAULT_SIZE, 37, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(restartNecessaryWarning, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(invalidReasonLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(maxMemoryUnitsLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 17, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(maxMemoryUnitsLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 17, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(restartNecessaryWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 326, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(invalidReasonLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 326, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap()) ); runtimePanelLayout.setVerticalGroup( runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(runtimePanelLayout.createSequentialGroup() .addContainerGap() - .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(maxMemoryUnitsLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(memField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(maxMemoryLabel)) - .addComponent(invalidReasonLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(runtimePanelLayout.createSequentialGroup() - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) - .addComponent(totalMemoryLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(systemMemoryTotal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) - .addGroup(runtimePanelLayout.createSequentialGroup() - .addGap(11, 11, 11) - .addComponent(restartNecessaryWarning))) + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(maxMemoryUnitsLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(memField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(invalidReasonLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(maxMemoryLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(restartNecessaryWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(maxMemoryUnitsLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(totalMemoryLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(systemMemoryTotal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGap(0, 0, 0)) ); @@ -650,12 +649,12 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createSequentialGroup() .addContainerGap() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(logoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(viewPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(runtimePanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(logoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(runtimePanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); jPanel1Layout.setVerticalGroup( @@ -777,8 +776,8 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { return false; } int parsedInt = Integer.parseInt(memText); - if (parsedInt < HARD_MIN_MEMORY_IN_GB) { - invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_underMinMemory_text(SOFT_MIN_MEMORY_IN_GB)); + if (parsedInt < MIN_MEMORY_IN_GB) { + invalidReasonLabel.setText(Bundle.AutopsyOptionsPanel_invalidReasonLabel_underMinMemory_text(MIN_MEMORY_IN_GB)); return false; } if (parsedInt >= getSystemMemoryInGB()) { @@ -807,6 +806,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { private javax.swing.JPanel logoPanel; private javax.swing.JLabel maxMemoryLabel; private javax.swing.JLabel maxMemoryUnitsLabel; + private javax.swing.JLabel maxMemoryUnitsLabel1; private javax.swing.JTextField memField; private javax.swing.JLabel restartNecessaryWarning; private javax.swing.JPanel runtimePanel; From b69bc2731ef9474254f92b9eb70918e6e4e40f00 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 5 Dec 2017 12:05:20 -0500 Subject: [PATCH 88/90] 3226 fix horizontal allignment of notifications --- .../corecomponents/AutopsyOptionsPanel.form | 13 ++++++------- .../corecomponents/AutopsyOptionsPanel.java | 15 +++++++-------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form index 2457e1be71..00881c2ca7 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.form @@ -65,9 +65,9 @@ - + - + @@ -424,12 +424,12 @@ - + - - + + - + @@ -454,7 +454,6 @@ - diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java index 9fd8f10734..a62ae4400c 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AutopsyOptionsPanel.java @@ -619,11 +619,11 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(maxMemoryUnitsLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 17, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(maxMemoryUnitsLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 17, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(18, 18, 18) .addGroup(runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(restartNecessaryWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 326, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(invalidReasonLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 326, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addContainerGap()) + .addComponent(restartNecessaryWarning, javax.swing.GroupLayout.DEFAULT_SIZE, 417, Short.MAX_VALUE) + .addComponent(invalidReasonLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); runtimePanelLayout.setVerticalGroup( runtimePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -641,8 +641,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addComponent(restartNecessaryWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(maxMemoryUnitsLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(totalMemoryLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(systemMemoryTotal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) - .addGap(0, 0, 0)) + .addComponent(systemMemoryTotal, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) ); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); @@ -662,9 +661,9 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel { .addGroup(jPanel1Layout.createSequentialGroup() .addGap(0, 0, 0) .addComponent(viewPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, 0) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(runtimePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, 0) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(logoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, 0)) ); From f2d31e588236ffe649fbe64393a53a0627fe6ed5 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Tue, 5 Dec 2017 12:19:36 -0500 Subject: [PATCH 89/90] Make search responsive to both job and thread cancellation --- .../KeywordSearchIngestModule.java | 2 +- .../autopsy/keywordsearch/SearchRunner.java | 32 ++++++++++--------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java index 830c93325a..dbbca6394b 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java @@ -280,7 +280,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule { return ProcessResult.OK; } List keywordListNames = settings.getNamesOfEnabledKeyWordLists(); - SearchRunner.getInstance().startJob(jobId, dataSourceId, keywordListNames); + SearchRunner.getInstance().startJob(context, keywordListNames); startedSearching = true; } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java index b998294fe4..da1d5092a7 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/SearchRunner.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 - 2017 Basis Technology Corp. + * Copyright 2014 - 2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -43,6 +43,7 @@ import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.StopWatch; +import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestServices; @@ -79,19 +80,15 @@ public final class SearchRunner { } /** - * Add a new job. Searches will be periodically performed after this is - * called. * - * @param jobId Job ID that this is associated with - * @param dataSourceId Data source that is being indexed and that - * searches should be restricted to. - * @param keywordListNames List of keyword lists that will be searched. List - * contents will be refreshed each search. + * @param jobContext + * @param keywordListNames */ - public synchronized void startJob(long jobId, long dataSourceId, List keywordListNames) { + public synchronized void startJob(IngestJobContext jobContext, List keywordListNames) { + long jobId = jobContext.getJobId(); if (jobs.containsKey(jobId) == false) { logger.log(Level.INFO, "Adding job {0}", jobId); //NON-NLS - SearchJobInfo jobData = new SearchJobInfo(jobId, dataSourceId, keywordListNames); + SearchJobInfo jobData = new SearchJobInfo(jobContext, keywordListNames); jobs.put(jobId, jobData); } @@ -266,6 +263,7 @@ public final class SearchRunner { */ private class SearchJobInfo { + private final IngestJobContext jobContext; private final long jobId; private final long dataSourceId; // mutable state: @@ -278,15 +276,20 @@ public final class SearchRunner { private AtomicLong moduleReferenceCount = new AtomicLong(0); private final Object finalSearchLock = new Object(); //used for a condition wait - private SearchJobInfo(long jobId, long dataSourceId, List keywordListNames) { - this.jobId = jobId; - this.dataSourceId = dataSourceId; + private SearchJobInfo(IngestJobContext jobContext, List keywordListNames) { + this.jobContext = jobContext; + this.jobId = jobContext.getJobId(); + this.dataSourceId = jobContext.getDataSource().getId(); this.keywordListNames = new ArrayList<>(keywordListNames); currentResults = new HashMap<>(); workerRunning = false; currentSearcher = null; } + private IngestJobContext getJobContext() { + return jobContext; + } + private long getJobId() { return jobId; } @@ -435,7 +438,7 @@ public final class SearchRunner { int keywordsSearched = 0; for (Keyword keyword : keywords) { - if (this.isCancelled()) { + if (this.isCancelled() || this.job.getJobContext().fileIngestIsCancelled()) { logger.log(Level.INFO, "Cancel detected, bailing before new keyword processed: {0}", keyword.getSearchTerm()); //NON-NLS return null; } @@ -480,7 +483,6 @@ public final class SearchRunner { if (!newResults.getKeywords().isEmpty()) { // Write results to BB - //scale progress bar more more granular, per result sub-progress, within per keyword int totalUnits = newResults.getKeywords().size(); subProgresses[keywordsSearched].start(totalUnits); From ec2a6bf3ba9d80d5be9b5bea9e50979261984dc9 Mon Sep 17 00:00:00 2001 From: esaunders Date: Tue, 5 Dec 2017 13:12:19 -0500 Subject: [PATCH 90/90] Update default JVM max heap size and document. --- build-windows-installer.xml | 6 +++--- build.xml | 2 +- docs/doxygen-user/images/runtime_settings.PNG | Bin 0 -> 2747 bytes docs/doxygen-user/installation.dox | 6 +++++- 4 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 docs/doxygen-user/images/runtime_settings.PNG diff --git a/build-windows-installer.xml b/build-windows-installer.xml index e3f0401632..b82e28ca24 100755 --- a/build-windows-installer.xml +++ b/build-windows-installer.xml @@ -109,7 +109,7 @@ - + @@ -144,7 +144,7 @@ - + @@ -170,7 +170,7 @@ - + diff --git a/build.xml b/build.xml index bba4207f1b..4eaa7df1c8 100755 --- a/build.xml +++ b/build.xml @@ -92,7 +92,7 @@ - + diff --git a/docs/doxygen-user/images/runtime_settings.PNG b/docs/doxygen-user/images/runtime_settings.PNG new file mode 100644 index 0000000000000000000000000000000000000000..1d02f96a4238ea84b199d34527e4db9d378b8f9c GIT binary patch literal 2747 zcmb7G3s6&M7QSlLVnw$28XgU6XJ{>x)&)%fdA3z720;iRT%KwO!2}2x0Yd=YbylmD zMwb$mNa9vONl0iC5+32T+cl|RxUD6G1QJvRQiw^4X%Zj=_A+f}XJ=<;+JELg{<-JB z=R4o||8u@8#}kiuZt>j$0Dx!wCx=o1U_AzYKl%D5_^#MF&43^4XemcN0))f4S-wf0S(Y-PGW_$u|!3HYK@zAmnQ6SDv5l@P3@v6ny2tzf%0t8!puQe>E_0A~yDG zd39xKe3L`a&2^*P@~8J0!;Crq$v#BH&hZAd*;Td~c3zwB0RVSnC9eU%@w?!90NDF2 zavcEdC}6=Kw;WiDWMe}h09;tF@&IE8G@Bq_12wED9Q@}PMof5Xd*{%QoRWP zVP&78G1?3{qef3!LD2lz=^FsxD=#rvx%k4gN}%vg&t|gg_@y%Fp%M0d>+K@e3nE1j zJipvm82v7Os+`%{{QSkwBV#Uz9Vnggs~fwYXAAH0RaV1DTp@h$s;#gnQK-;H!> z#jI1KikvJa4Yyk(5s9|00lLRt!;AUox5o76-$wy#UKh1Gw;2DNvI~yx0OnRJYA^o0 z{Gf-KzR<7{c)3C4{f;Dmc8AarS-u%K5f58jgI$z(6tMo}1GD(d`&;D65SY|~!1Q)7 zLy#6xtv!x)9wS2JnBwL6YT@W9)--7D3Qv=a7_xhGwz1w*R>P|QLpVCxQ`J+^n2iUW zs*vuIAR#iO3T_BwRLqkhf-}J}Oj!9tO)&rrfjuD4f<{M6L|m7A-j*I4Oypstj;slH!h!?F7PTQF>oCRb2C;tMfGDQ@*XgZJx33(wI^czl`!WUX~R|@&XjtvSzA2 zuWUu>Q^^V?CI#4$Sgsd}(MB)`CJC<8@&c2Ub2gx6No+y~$cihbSS`9I(cJTMUFtqU zuZa-x0IKFel`Xjuv;;coV<*yWdlO>QR#G6@%@{CaX(PWoFlQiT-**&}f`+?9ABk|# z0{OSkjDBh8nJZpd)C!YzRaH{E*i_SNF3wqQ%Iv4NIA1q+Iqfg8P}G7va)a@w#6&x| z*zHRljPUCw&2pLN40midD`gi^nD_T%L;Uc!2dBd0RG0Hh^)}R8F`o>R!wT!w6Y{&P9-0XrQgC=aSd+4pJE*i^?b<9N)^SLNu$H#Y1YwQWZYv{)n!~#C zTZlPnyBB?>ZM9S3WW=NH!qyN}v2!oqPT=C`le&*@^fIsIQrAv)6&KETU$P(jT>8*`ZD~K8QjH* zHc}bPtAs9_Y%hbv>D!ee#ls$J`}E4P}BT2a;KKBNq#|5phP01FUxn zT6(BCL=MF3?#xk-={1k&_vgfgSL?{EOQY}gHS09u!fdrN(vP1|tLEJD(%ys%lhdtRh1_h`iDyr%!l+>+qnRWWI3KzkZwmxav=NKdBuo`FkhWmX-MM2{O zGOoJ3nWuWyI@)eepV}{Ne$|JnC)o&&AH< z$Bu+>imXH9oD6z4Ww*3VqGQgl$cyUQ>8s~VbE99f%wCThlC%U_{+ZmUP)wg literal 0 HcmV?d00001 diff --git a/docs/doxygen-user/installation.dox b/docs/doxygen-user/installation.dox index c924708201..aa67e55d7a 100755 --- a/docs/doxygen-user/installation.dox +++ b/docs/doxygen-user/installation.dox @@ -6,12 +6,16 @@ It is _highly_ recommended to remove or disable any antivirus software from computers that will be processing or reviewing cases. Antivirus software will often conflict with forensic software, and may quarantine or even delete some of your results before you get a chance to look at them.

- \section install Deployment Types Starting with Autopsy 4.0, there are two ways to deploy Autopsy: - **Single-User**: Cases can be open by only a single instance of Autopsy at a time. Autopsy installations do not communicate with each other. This is the easiest to install and deploy. This page outlines that installation process. - **Multi-User**: Cases can be open by multiple users at the same time and users can see what each other is doing. This collaborative deployment requires installation and configuration of other network-based services. The installation of this deployment is covered in \ref install_multiuser_page. +\section sysreqs System Memory Requirements +The 64 bit version of Autopsy requires a minimum of 8GB RAM (16 GB recommended). +When the 64 bit version of Autopsy is installed on Windows it will be limited to a maximum heap size of 4GB leaving the remaining memory for the operating system, the internal Solr text indexing service and other applications. If you wish to change the maximum heap size you can do so after installation by changing the Maximum JVM Memory value in the Runtime section under Tools -> Options -> Application. + +\image html runtime_settings.PNG \section download Download Download Autopsy from the website: