/* * Autopsy Forensic Browser * * Copyright 2015 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sleuthkit.autopsy.experimental.autoingest; import com.github.lgooddatepicker.datetimepicker.DateTimePicker; import com.github.lgooddatepicker.optionalusertools.PickerUtilities; import com.github.lgooddatepicker.timepicker.TimePickerSettings; import java.awt.Color; import java.awt.Component; import java.awt.event.FocusEvent; import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; import java.text.ParseException; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashSet; import java.util.List; import java.util.NavigableMap; import java.util.Set; import java.util.SortedSet; import java.util.TreeMap; import java.util.HashMap; import java.util.Map; import java.util.Date; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.JTextField; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.sleuthkit.autopsy.corecomponents.TextPrompt; import org.sleuthkit.autopsy.experimental.autoingest.FileExportRuleSet.Rule; import org.sleuthkit.autopsy.experimental.autoingest.FileExportRuleSet.Rule.FileMIMETypeCondition; import org.sleuthkit.autopsy.experimental.autoingest.FileExportRuleSet.Rule.FileSizeCondition; import org.sleuthkit.autopsy.experimental.autoingest.FileExportRuleSet.Rule.FileSizeCondition.SizeUnit; import org.sleuthkit.autopsy.experimental.autoingest.FileExportRuleSet.Rule.RelationalOp; import org.sleuthkit.autopsy.coreutils.FileUtil; import java.util.logging.Level; import javax.swing.DefaultComboBoxModel; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JDialog; import javax.swing.JPanel; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import org.apache.tika.mime.MediaType; import org.apache.tika.mime.MimeTypes; import org.openide.util.ImageUtilities; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.experimental.autoingest.FileExportRuleSet.Rule.ArtifactCondition; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import javax.swing.DefaultListModel; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; /** * Global settings panel for data-source-level ingest modules that export and * catalog files based on user-defined export rules. */ public final class FileExporterSettingsPanel extends JPanel { private static final long serialVersionUID = 1L; private final JFileChooser rootDirectoryChooser = new JFileChooser(); private final JFileChooser reportDirectoryChooser = new JFileChooser(); private static final Logger logger = Logger.getLogger(FileExporterSettingsPanel.class.getName()); private FileExportRuleSet exportRuleSet = new FileExportRuleSet("DefaultRuleSet"); //NON-NLS private Rule localRule = null; // this is the rule to compare against to see if things have changed private static final SortedSet<MediaType> mediaTypes = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes(); private static final String ROOTNODE = "Rules"; //NON-NLS private final JDialog jDialog; private DefaultMutableTreeNode rootNode; private final TreeSelectionModel treeSelectionModel; private final DefaultTreeModel defaultTreeModel; private final DefaultListModel<String> attributeListModel; private List<TreePath> expandedNodes = null; private Map<String, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE> attributeTypeMap = new HashMap<>(); private static final String UNSET = "Unset"; //NON-NLS private final javax.swing.event.ListSelectionListener listSelectionListener; private final javax.swing.event.TreeSelectionListener treeSelectionListener; private TimePickerSettings timeSettings = new TimePickerSettings(); private enum ItemType { RULE_SET, RULE, MIME_TYPE_CLAUSE, SIZE_CLAUSE, ARTIFACT_CLAUSE } private class Item { private String name; private String parentRuleName; private ItemType itemType; Item(String name, String parentRuleName, ItemType itemType) { this.name = name; this.parentRuleName = parentRuleName; this.itemType = itemType; } /** * @return the name of the rule containing this Item */ String getRuleName() { if (this.itemType == ItemType.RULE) { return this.name; } else { return this.parentRuleName; } } /** * @return the name */ String getName() { return name; } /** * @param name the name to set */ void setName(String name) { this.name = name; } /** * @return the parentRUleName */ String getParentName() { return parentRuleName; } /** * @param parentName the parentRUleName to set */ void setParentName(String parentName) { this.parentRuleName = parentName; } /** * @return the itemType */ ItemType getItemType() { return itemType; } /** * @param itemType the itemType to set */ void setItemType(ItemType itemType) { this.itemType = itemType; } @Override public String toString() { return this.getName(); } } public FileExporterSettingsPanel(JDialog jDialog) { timeSettings.setFormatForDisplayTime(PickerUtilities.createFormatterFromPatternString("HH:mm:ss", timeSettings.getLocale())); timeSettings.setFormatForMenuTimes(PickerUtilities.createFormatterFromPatternString("HH:mm", timeSettings.getLocale())); initComponents(); rootNode = new DefaultMutableTreeNode(new Item(ROOTNODE, ROOTNODE, ItemType.RULE_SET)); trRuleList.setModel(new DefaultTreeModel(rootNode)); this.jDialog = jDialog; attributeListModel = (DefaultListModel<String>) lsAttributeList.getModel(); rootDirectoryChooser.setCurrentDirectory(rootDirectoryChooser.getFileSystemView().getParentDirectory(new File("C:\\"))); //NON-NLS rootDirectoryChooser.setAcceptAllFileFilterUsed(false); rootDirectoryChooser.setDialogTitle(NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.ChooseRootDirectory")); rootDirectoryChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); reportDirectoryChooser.setCurrentDirectory(reportDirectoryChooser.getFileSystemView().getParentDirectory(new File("C:\\"))); //NON-NLS reportDirectoryChooser.setAcceptAllFileFilterUsed(false); reportDirectoryChooser.setDialogTitle(NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.ChooseReportDirectory")); reportDirectoryChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); // Add text prompt to the text box fields TextPrompt textPromptRuleName = new TextPrompt(NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.RuleName"), tbRuleName); textPromptRuleName.setForeground(Color.LIGHT_GRAY); textPromptRuleName.changeAlpha(0.9f); TextPrompt textPromptRootDirectory = new TextPrompt(NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.RootDirectory"), tbRootDirectory); textPromptRootDirectory.setForeground(Color.LIGHT_GRAY); textPromptRootDirectory.changeAlpha(0.9f); TextPrompt textPromptReportDirectory = new TextPrompt(NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.ReportDirectory"), tbReportDirectory); textPromptReportDirectory.setForeground(Color.LIGHT_GRAY); textPromptReportDirectory.changeAlpha(0.9f); TextPrompt textPromptReportAttributeValue = new TextPrompt(NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.AttributeValue"), tbAttributeValue); textPromptReportAttributeValue.setForeground(Color.LIGHT_GRAY); textPromptReportAttributeValue.changeAlpha(0.9f); for (SizeUnit item : SizeUnit.values()) { comboBoxFileSizeUnits.addItem(item.toString()); } for (RelationalOp item : RelationalOp.values()) { comboBoxFileSizeComparison.addItem(item.getSymbol()); comboBoxAttributeComparison.addItem(item.getSymbol()); } comboBoxValueType.addItem(BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.INTEGER.getLabel()); comboBoxValueType.addItem(BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG.getLabel()); comboBoxValueType.addItem(BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DOUBLE.getLabel()); comboBoxValueType.addItem(BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING.getLabel()); comboBoxValueType.addItem(BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME.getLabel()); comboBoxValueType.addItem(BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE.getLabel()); comboBoxValueType.addItem(UNSET); load(); trRuleList.setCellRenderer(new DefaultTreeCellRenderer() { private static final long serialVersionUID = 1L; private final ImageIcon ruleSetIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/ruleset-icon.png", false)); private final ImageIcon ruleIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/extracted_content.png", false)); private final ImageIcon sizeIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/file-size-16.png", false)); private final ImageIcon artifactIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/artifact-icon.png", false)); private final ImageIcon mimetypeIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/mime-icon.png", false)); private final ImageIcon otherIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/knownbad-icon.png", false)); @Override public Component getTreeCellRendererComponent(javax.swing.JTree tree, Object value, boolean selected, boolean expanded, boolean isLeaf, int row, boolean focused) { Component component = super.getTreeCellRendererComponent(tree, value, selected, expanded, isLeaf, row, focused); Icon icon; switch (((Item) ((DefaultMutableTreeNode) value).getUserObject()).getItemType()) { case ARTIFACT_CLAUSE: icon = artifactIcon; break; case MIME_TYPE_CLAUSE: icon = mimetypeIcon; break; case RULE: icon = ruleIcon; break; case SIZE_CLAUSE: icon = sizeIcon; break; case RULE_SET: icon = ruleSetIcon; break; default: icon = otherIcon; break; } setIcon(icon); return component; } }); populateMimeTypes(); populateArtifacts(); populateAttributes(); populateRuleTree(); tbRuleName.getDocument().addDocumentListener(new DocumentListener() { @Override public void changedUpdate(DocumentEvent e) { setSaveButton(); } @Override public void removeUpdate(DocumentEvent e) { setSaveButton(); } @Override public void insertUpdate(DocumentEvent e) { setSaveButton(); } }); comboBoxMimeValue.getEditor().getEditorComponent().addFocusListener(new java.awt.event.FocusListener() { @Override public void focusGained(FocusEvent e) { comboBoxMimeValue.showPopup(); comboBoxMimeValue.getEditor().selectAll(); } @Override public void focusLost(FocusEvent e) { // do nothing } }); comboBoxArtifactName.getEditor().getEditorComponent().addFocusListener(new java.awt.event.FocusListener() { @Override public void focusGained(FocusEvent e) { comboBoxArtifactName.showPopup(); comboBoxArtifactName.getEditor().selectAll(); } @Override public void focusLost(FocusEvent e) { // do nothing } }); comboBoxAttributeName.getEditor().getEditorComponent().addFocusListener(new java.awt.event.FocusListener() { @Override public void focusGained(FocusEvent e) { comboBoxAttributeName.showPopup(); comboBoxAttributeName.getEditor().selectAll(); } @Override public void focusLost(FocusEvent e) { // do nothing } }); comboBoxMimeTypeComparison.addItem(RelationalOp.Equals.getSymbol()); comboBoxMimeTypeComparison.addItem(RelationalOp.NotEquals.getSymbol()); treeSelectionModel = trRuleList.getSelectionModel(); defaultTreeModel = (DefaultTreeModel) trRuleList.getModel(); bnDeleteRule.setEnabled(false); String selectedAttribute = comboBoxAttributeName.getSelectedItem().toString(); comboBoxValueType.setSelectedItem(selectedAttribute); localRule = makeRuleFromUserInput(); listSelectionListener = this::lsAttributeListValueChanged; lsAttributeList.addListSelectionListener(listSelectionListener); treeSelectionListener = this::trRuleListValueChanged; trRuleList.addTreeSelectionListener(treeSelectionListener); setDeleteAttributeButton(); setSaveButton(); } /** * Save the settings, issuing warnings if needed. * * @param tryValidation attempt to validate if set to true, otherwise do not * * @return true if form ready to close, false otherwise */ boolean saveAndValidateSettings(boolean tryValidation) { if (tryValidation) { try { validateRootDirectory(); } catch (FolderDidNotValidateException ex) { JOptionPane.showMessageDialog(this, NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.BadRootFolder") + " " + ex.getMessage(), NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.BadFolderForInterestingFileExport"), JOptionPane.OK_OPTION); return false; } try { validateReportDirectory(); } catch (FolderDidNotValidateException ex) { JOptionPane.showMessageDialog(this, NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.BadReportFolder") + " " + ex.getMessage(), NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.BadFolderForInterestingFileExport"), JOptionPane.OK_OPTION); return false; } if (hasRuleChanged()) { // if rule has changed without saving ask if we should save or discard if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.ChangesWillBeLost") + " " + NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.DoYouWantToSave"), NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.ChangesWillBeLost"), JOptionPane.YES_NO_OPTION)) { saveOrUpdateRule(); } } } store(); return true; } private void setValueField() { if (comboBoxValueType.getSelectedItem().toString().compareTo("DateTime") == 0) { dateTimePicker.setVisible(true); tbAttributeValue.setVisible(false); } else { dateTimePicker.setVisible(false); tbAttributeValue.setVisible(true); } } private void setTypeColor() { if (cbAttributeType.isSelected() && comboBoxValueType.getSelectedItem().toString().compareTo(UNSET) == 0) { comboBoxValueType.setForeground(Color.RED); } else { comboBoxValueType.setForeground(Color.BLACK); } } /** * Enable save button if we have a rule name and at least one condition in * use. */ private void setSaveButton() { String ruleName = tbRuleName.getText(); String selectedString = comboBoxValueType.getSelectedItem().toString(); if ((!cbEnableFileExport.isSelected()) || (cbAttributeType.isSelected() && selectedString.compareTo(UNSET) == 0)) { bnSaveRule.setEnabled(false); lbSaveRuleHelper.setVisible(true); return; } if (ruleName != null && !ruleName.isEmpty()) { boolean result = cbFileSize.isSelected() || cbMimeType.isSelected() || cbAttributeType.isSelected(); bnSaveRule.setEnabled(result); lbSaveRuleHelper.setVisible(!result); } else { bnSaveRule.setEnabled(false); lbSaveRuleHelper.setVisible(true); } } /** * Go through the ruleSet and populate the JList */ void populateRuleTree() { populateRuleTree(null); } /** * Go through the ruleSet and populate the JList * * @param ruleToBeSelected The path to the rule that should be selected * after populating the tree */ void populateRuleTree(String ruleToBeSelected) { TreePath ttt = new TreePath(rootNode); Enumeration<TreePath> expandedDescendants = trRuleList.getExpandedDescendants(ttt); expandedNodes = (expandedDescendants == null ? new ArrayList<>() : Collections.list(expandedDescendants)); if (rootNode != null) { rootNode.removeAllChildren(); } for (Rule rule : exportRuleSet.getRules().values()) { String ruleName = rule.getName(); DefaultMutableTreeNode ruleNode = new DefaultMutableTreeNode(new Item(ruleName, ROOTNODE, ItemType.RULE)); rootNode.add(ruleNode); FileMIMETypeCondition fileMIMETypeCondition = rule.getFileMIMETypeCondition(); if (fileMIMETypeCondition != null) { ruleNode.add(new DefaultMutableTreeNode(new Item("MIME Type", ruleName, ItemType.MIME_TYPE_CLAUSE))); } List<FileSizeCondition> fileSizeConditions = rule.getFileSizeConditions(); for (FileSizeCondition fsc : fileSizeConditions) { ruleNode.add(new DefaultMutableTreeNode(new Item("File Size", ruleName, ItemType.SIZE_CLAUSE))); } for (Rule.ArtifactCondition artifact : rule.getArtifactConditions()) { DefaultMutableTreeNode clauseNode = new DefaultMutableTreeNode( new Item(artifact.getTreeDisplayName(), ruleName, ItemType.ARTIFACT_CLAUSE)); ruleNode.add(clauseNode); } } ((DefaultTreeModel) trRuleList.getModel()).reload(); // Re-expand any rules that were open previously and that still exist for (TreePath e : expandedNodes) { TreePath treePath = findTreePathByRuleName(e.getLastPathComponent().toString()); trRuleList.expandPath(treePath); } expandedNodes.clear(); // select the rule to leave the cursor in a logical place if (ruleToBeSelected != null) { TreePath treePath = findTreePathByRuleName(ruleToBeSelected); treeSelectionModel.setSelectionPath(treePath); trRuleList.expandPath(treePath); } } /** * Populate the MIME types in the combo box. */ void populateMimeTypes() { Set<String> mimeTypesCollated = scanRulesForMimetypes(); for (MediaType mediaType : mediaTypes) { mimeTypesCollated.add(mediaType.toString()); } FileTypeDetector fileTypeDetector; try { fileTypeDetector = new FileTypeDetector(); List<String> userDefinedFileTypes = fileTypeDetector.getUserDefinedTypes(); mimeTypesCollated.addAll(userDefinedFileTypes); } catch (FileTypeDetector.FileTypeDetectorInitException ex) { logger.log(Level.SEVERE, "Unable to get user defined file types", ex); } List<String> sorted = new ArrayList<>(mimeTypesCollated); Collections.sort(sorted, String.CASE_INSENSITIVE_ORDER); for (String mime : sorted) { comboBoxMimeValue.addItem(mime); } } /** * Populate the Artifact types in the combo box. */ void populateArtifacts() { Set<String> artifactTypes = scanRulesForArtifacts(); try { SleuthkitCase currentCase = Case.getCurrentCase().getSleuthkitCase(); for (BlackboardArtifact.Type type : currentCase.getArtifactTypes()) { artifactTypes.add(type.getTypeName()); } } catch (IllegalStateException | TskCoreException ex) { // Unable to find and open case or cannot read the database. Use enum. for (BlackboardArtifact.ARTIFACT_TYPE artifact : BlackboardArtifact.ARTIFACT_TYPE.values()) { artifactTypes.add(artifact.toString()); } } List<String> sorted = new ArrayList<>(artifactTypes); Collections.sort(sorted, String.CASE_INSENSITIVE_ORDER); for (String artifact : sorted) { comboBoxArtifactName.addItem(artifact); } } /** * Find all MIME types from existing rules * * @return a Set of Strings with existing rule MIME types */ Set<String> scanRulesForMimetypes() { Set<String> mimeTypes = new HashSet<>(); NavigableMap<String, Rule> nmp = exportRuleSet.getRules(); for (Rule rule : nmp.values()) { if (rule.getFileMIMETypeCondition() != null) { mimeTypes.add(rule.getFileMIMETypeCondition().getMIMEType()); } } return mimeTypes; } /** * Find all artifact types from existing rules * * @return a Set of Strings with existing rule artifact types */ Set<String> scanRulesForArtifacts() { Set<String> artifacts = new HashSet<>(); NavigableMap<String, Rule> nmp = exportRuleSet.getRules(); for (Rule rule : nmp.values()) { for (ArtifactCondition ac : rule.getArtifactConditions()) { artifacts.add(ac.getArtifactTypeName()); } } return artifacts; } /** * Find all attribute types from existing rules * * @return a Set of Strings with existing rule attribute types */ Set<String> scanRulesForAttributes() { Set<String> attributes = new HashSet<>(); NavigableMap<String, Rule> nmp = exportRuleSet.getRules(); for (Rule rule : nmp.values()) { for (ArtifactCondition ac : rule.getArtifactConditions()) { attributes.add(ac.getAttributeTypeName()); attributeTypeMap.put(ac.getAttributeTypeName(), ac.getAttributeValueType()); } } return attributes; } /** * Populate the Attribute types in the combo box. */ void populateAttributes() { Set<String> attributeTypes = scanRulesForAttributes(); try { SleuthkitCase currentCase = Case.getCurrentCase().getSleuthkitCase(); for (BlackboardAttribute.Type type : currentCase.getAttributeTypes()) { attributeTypes.add(type.getTypeName()); attributeTypeMap.put(type.getTypeName(), type.getValueType()); } } catch (IllegalStateException | TskCoreException ex) { // Unable to find and open case or cannot read the database. Use enum. for (BlackboardAttribute.ATTRIBUTE_TYPE type : BlackboardAttribute.ATTRIBUTE_TYPE.values()) { attributeTypes.add(type.getLabel()); attributeTypeMap.put(type.getLabel(), type.getValueType()); } } List<String> sorted = new ArrayList<>(attributeTypes); Collections.sort(sorted, String.CASE_INSENSITIVE_ORDER); for (String attribute : sorted) { comboBoxAttributeName.addItem(attribute); } } private void populateArtifactEditor(ArtifactCondition artifactConditionToPopulateWith) { cbAttributeType.setSelected(true); comboBoxArtifactName.setSelectedItem(artifactConditionToPopulateWith.getArtifactTypeName()); comboBoxAttributeComparison.setSelectedItem(artifactConditionToPopulateWith.getRelationalOperator().getSymbol()); comboBoxAttributeName.setSelectedItem(artifactConditionToPopulateWith.getAttributeTypeName()); BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType = artifactConditionToPopulateWith.getAttributeValueType(); comboBoxValueType.setSelectedItem(valueType.getLabel()); comboBoxValueType.setEnabled(null == attributeTypeMap.get(artifactConditionToPopulateWith.getAttributeTypeName())); if (valueType == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) { Instant instant = Instant.ofEpochMilli(artifactConditionToPopulateWith.getDateTimeValue().toDate().getTime()); dateTimePicker.setDateTime(LocalDateTime.ofInstant(instant, ZoneId.systemDefault())); } else { tbAttributeValue.setText(artifactConditionToPopulateWith.getStringRepresentationOfValue()); } } /** * 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") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { mainPanel = new javax.swing.JPanel(); tbRootDirectory = new javax.swing.JTextField(); pnEditRule = new javax.swing.JPanel(); comboBoxMimeValue = new javax.swing.JComboBox<String>(); cbMimeType = new javax.swing.JCheckBox(); spFileSizeValue = new javax.swing.JSpinner(); comboBoxFileSizeUnits = new javax.swing.JComboBox<String>(); cbFileSize = new javax.swing.JCheckBox(); comboBoxFileSizeComparison = new javax.swing.JComboBox<String>(); comboBoxMimeTypeComparison = new javax.swing.JComboBox<String>(); tbRuleName = new javax.swing.JTextField(); bnSaveRule = new javax.swing.JButton(); comboBoxArtifactName = new javax.swing.JComboBox<String>(); comboBoxAttributeName = new javax.swing.JComboBox<String>(); comboBoxAttributeComparison = new javax.swing.JComboBox<String>(); tbAttributeValue = new javax.swing.JTextField(); bnAddAttribute = new javax.swing.JButton(); comboBoxValueType = new javax.swing.JComboBox<String>(); cbAttributeType = new javax.swing.JCheckBox(); dateTimePicker = new DateTimePicker(null, timeSettings); lbArtifact = new javax.swing.JLabel(); lbAttribute = new javax.swing.JLabel(); bnDeleteAttribute = new javax.swing.JButton(); jScrollPane1 = new javax.swing.JScrollPane(); lsAttributeList = new javax.swing.JList<String>(); lbRuleName = new javax.swing.JLabel(); lbSaveRuleHelper = new javax.swing.JLabel(); bnBrowseReportDirectory = new javax.swing.JButton(); tbReportDirectory = new javax.swing.JTextField(); ruleListScrollPane = new javax.swing.JScrollPane(); trRuleList = new javax.swing.JTree(); lbFiles = new javax.swing.JLabel(); lbReports = new javax.swing.JLabel(); bnBrowseRootDirectory = new javax.swing.JButton(); cbEnableFileExport = new javax.swing.JCheckBox(); bnNewRule = new javax.swing.JButton(); bnDeleteRule = new javax.swing.JButton(); bnClose = new javax.swing.JButton(); lbExplanation = new javax.swing.JLabel(); setBorder(javax.swing.BorderFactory.createEtchedBorder()); setName(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.Title")); // NOI18N mainPanel.setAutoscrolls(true); mainPanel.setPreferredSize(new java.awt.Dimension(657, 425)); tbRootDirectory.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.RuleOutputTooltip_1")); // NOI18N tbRootDirectory.setMaximumSize(new java.awt.Dimension(2000, 2000)); pnEditRule.setBorder(javax.swing.BorderFactory.createEtchedBorder()); pnEditRule.setAutoscrolls(true); comboBoxMimeValue.setEditable(true); comboBoxMimeValue.setMaximumRowCount(30); comboBoxMimeValue.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.MimetypeTooltip_1")); // NOI18N comboBoxMimeValue.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { comboBoxMimeValueActionPerformed(evt); } }); cbMimeType.setText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.MimetypeText")); // NOI18N cbMimeType.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.MimetypeCheckboxTooltip_1")); // NOI18N cbMimeType.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { checkButtonItemStateChanged(evt); } }); spFileSizeValue.setModel(new javax.swing.SpinnerNumberModel(Integer.valueOf(1024), Integer.valueOf(0), null, Integer.valueOf(1))); spFileSizeValue.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.FileSizeValueToolTip_1")); // NOI18N comboBoxFileSizeUnits.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.FileSizeUnitToolTip_1")); // NOI18N cbFileSize.setText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.FileSize")); // NOI18N cbFileSize.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.FileSize_1")); // NOI18N cbFileSize.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { checkButtonItemStateChanged(evt); } }); comboBoxFileSizeComparison.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.FileSizeComparisonTooltip_1")); // NOI18N comboBoxFileSizeComparison.setMinimumSize(new java.awt.Dimension(32, 20)); comboBoxMimeTypeComparison.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.MimeTypeComparisonTooltip_1")); // NOI18N comboBoxMimeTypeComparison.setMinimumSize(new java.awt.Dimension(32, 20)); tbRuleName.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.CurrentlySelectedRuleNameTooltip_1")); // NOI18N tbRuleName.setMaximumSize(new java.awt.Dimension(10, 1000)); tbRuleName.setPreferredSize(new java.awt.Dimension(733, 20)); tbRuleName.addKeyListener(new java.awt.event.KeyAdapter() { public void keyTyped(java.awt.event.KeyEvent evt) { tbRuleNameKeyTyped(evt); } }); bnSaveRule.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/experimental/images/save-icon.png"))); // NOI18N bnSaveRule.setText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.SaveText")); // NOI18N bnSaveRule.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.SaveTooltip_1")); // NOI18N bnSaveRule.setEnabled(false); bnSaveRule.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnSaveRuleActionPerformed(evt); } }); comboBoxArtifactName.setEditable(true); comboBoxArtifactName.setMaximumRowCount(30); comboBoxArtifactName.setToolTipText("The Artifact to match"); comboBoxArtifactName.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { comboBoxArtifactNameActionPerformed(evt); } }); comboBoxAttributeName.setEditable(true); comboBoxAttributeName.setMaximumRowCount(30); comboBoxAttributeName.setToolTipText("The attribute of the artifact to match"); comboBoxAttributeName.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { comboBoxAttributeNameActionPerformed(evt); } }); comboBoxAttributeComparison.setToolTipText("Select the conditional operator"); comboBoxAttributeComparison.setMinimumSize(new java.awt.Dimension(32, 23)); tbAttributeValue.setToolTipText("Type a value here"); tbAttributeValue.setMinimumSize(new java.awt.Dimension(6, 23)); tbAttributeValue.setPreferredSize(new java.awt.Dimension(6, 23)); bnAddAttribute.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/experimental/images/left-arrow-16-icon.png"))); // NOI18N bnAddAttribute.setText("Add Attribute"); bnAddAttribute.setToolTipText("Click to add an attribute to the current rule"); bnAddAttribute.setEnabled(false); bnAddAttribute.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnAddAttributeActionPerformed(evt); } }); comboBoxValueType.setToolTipText("Select the data type of attribute. This will affect how values are compared."); comboBoxValueType.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { comboBoxValueTypeActionPerformed(evt); } }); cbAttributeType.setText("Attributes"); cbAttributeType.setToolTipText("Select to include artifact/attribute pairs in the rule"); cbAttributeType.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { cbAttributeTypeItemStateChanged(evt); } }); dateTimePicker.setToolTipText("Choose a date and time"); lbArtifact.setText("Artifact"); lbAttribute.setText("Attribute"); bnDeleteAttribute.setText("Delete Attribute"); bnDeleteAttribute.setToolTipText("Click to remove the selected attribute"); bnDeleteAttribute.setEnabled(false); bnDeleteAttribute.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnDeleteAttributeActionPerformed(evt); } }); lsAttributeList.setModel(new DefaultListModel<String>()); lsAttributeList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); lsAttributeList.setToolTipText("The attributes for the selected rule"); jScrollPane1.setViewportView(lsAttributeList); lbRuleName.setText("Rule Name"); lbSaveRuleHelper.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT); lbSaveRuleHelper.setText("To save, a rule must have a name and at least one condition."); javax.swing.GroupLayout pnEditRuleLayout = new javax.swing.GroupLayout(pnEditRule); pnEditRule.setLayout(pnEditRuleLayout); pnEditRuleLayout.setHorizontalGroup( pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(pnEditRuleLayout.createSequentialGroup() .addContainerGap() .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(pnEditRuleLayout.createSequentialGroup() .addGap(21, 21, 21) .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 198, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(10, 10, 10) .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnEditRuleLayout.createSequentialGroup() .addComponent(lbSaveRuleHelper, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(bnSaveRule, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(pnEditRuleLayout.createSequentialGroup() .addComponent(comboBoxAttributeComparison, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(dateTimePicker, javax.swing.GroupLayout.PREFERRED_SIZE, 306, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(tbAttributeValue, javax.swing.GroupLayout.DEFAULT_SIZE, 158, Short.MAX_VALUE)) .addGroup(pnEditRuleLayout.createSequentialGroup() .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(pnEditRuleLayout.createSequentialGroup() .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(comboBoxArtifactName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lbArtifact)) .addGap(18, 18, 18) .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(pnEditRuleLayout.createSequentialGroup() .addComponent(comboBoxAttributeName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(comboBoxValueType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(lbAttribute))) .addGroup(pnEditRuleLayout.createSequentialGroup() .addComponent(bnAddAttribute, javax.swing.GroupLayout.PREFERRED_SIZE, 117, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(bnDeleteAttribute))) .addGap(0, 0, Short.MAX_VALUE)))) .addGroup(pnEditRuleLayout.createSequentialGroup() .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(cbMimeType) .addComponent(cbFileSize) .addComponent(cbAttributeType)) .addGap(89, 89, 89) .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(pnEditRuleLayout.createSequentialGroup() .addComponent(comboBoxMimeTypeComparison, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) .addComponent(comboBoxMimeValue, javax.swing.GroupLayout.PREFERRED_SIZE, 240, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(pnEditRuleLayout.createSequentialGroup() .addComponent(comboBoxFileSizeComparison, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) .addComponent(spFileSizeValue, javax.swing.GroupLayout.PREFERRED_SIZE, 105, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) .addComponent(comboBoxFileSizeUnits, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) .addGap(0, 0, Short.MAX_VALUE)) .addGroup(pnEditRuleLayout.createSequentialGroup() .addComponent(lbRuleName) .addGap(18, 18, 18) .addComponent(tbRuleName, javax.swing.GroupLayout.PREFERRED_SIZE, 1, Short.MAX_VALUE))) .addContainerGap()) ); pnEditRuleLayout.setVerticalGroup( pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(pnEditRuleLayout.createSequentialGroup() .addGap(14, 14, 14) .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(tbRuleName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lbRuleName)) .addGap(26, 26, 26) .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(cbMimeType) .addComponent(comboBoxMimeTypeComparison, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(comboBoxMimeValue, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(pnEditRuleLayout.createSequentialGroup() .addGap(78, 78, 78) .addComponent(lbAttribute) .addGap(8, 8, 8) .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addGroup(pnEditRuleLayout.createSequentialGroup() .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(comboBoxAttributeName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(comboBoxArtifactName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(comboBoxValueType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(tbAttributeValue, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(dateTimePicker, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) .addComponent(comboBoxAttributeComparison, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(bnAddAttribute) .addComponent(bnDeleteAttribute)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(bnSaveRule) .addComponent(lbSaveRuleHelper))) .addGroup(pnEditRuleLayout.createSequentialGroup() .addGap(26, 26, 26) .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(cbFileSize) .addComponent(spFileSizeValue, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(comboBoxFileSizeUnits, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(comboBoxFileSizeComparison, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(26, 26, 26) .addGroup(pnEditRuleLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(cbAttributeType) .addComponent(lbArtifact)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 187, Short.MAX_VALUE))) .addContainerGap()) ); bnBrowseReportDirectory.setText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.BrowseText")); // NOI18N bnBrowseReportDirectory.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.BrowseReportTooltip_1")); // NOI18N bnBrowseReportDirectory.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnBrowseReportDirectoryActionPerformed(evt); } }); tbReportDirectory.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.ReportOutputFolderTooltip_1")); // NOI18N tbReportDirectory.setMaximumSize(new java.awt.Dimension(2000, 2000)); javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("root"); trRuleList.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1)); trRuleList.setToolTipText("This tree shows the rules to collect files for automatic file export"); trRuleList.setName("trRuleList"); // NOI18N trRuleList.setShowsRootHandles(true); ruleListScrollPane.setViewportView(trRuleList); trRuleList.getAccessibleContext().setAccessibleParent(ruleListScrollPane); lbFiles.setText("Files Folder"); lbReports.setText("Reports Folder"); bnBrowseRootDirectory.setText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.BrowseText")); // NOI18N bnBrowseRootDirectory.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.BrowseRootOutputFolder_1")); // NOI18N bnBrowseRootDirectory.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnBrowseRootDirectoryActionPerformed(evt); } }); javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel); mainPanel.setLayout(mainPanelLayout); mainPanelLayout.setHorizontalGroup( mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup() .addContainerGap() .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(mainPanelLayout.createSequentialGroup() .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(lbFiles) .addComponent(lbReports)) .addGap(18, 18, 18) .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(tbRootDirectory, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(tbReportDirectory, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(bnBrowseReportDirectory, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(bnBrowseRootDirectory, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE))) .addGroup(mainPanelLayout.createSequentialGroup() .addComponent(ruleListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 278, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(pnEditRule, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) ); mainPanelLayout.setVerticalGroup( mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup() .addGap(1, 1, 1) .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(tbRootDirectory, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lbFiles) .addComponent(bnBrowseRootDirectory)) .addGap(6, 6, 6) .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(bnBrowseReportDirectory) .addComponent(tbReportDirectory, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lbReports)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(ruleListScrollPane) .addComponent(pnEditRule, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); cbEnableFileExport.setText("Enable File Export"); cbEnableFileExport.setToolTipText("Select to enable File Export"); cbEnableFileExport.addItemListener(new java.awt.event.ItemListener() { public void itemStateChanged(java.awt.event.ItemEvent evt) { cbEnableFileExportItemStateChanged(evt); } }); bnNewRule.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/experimental/images/plus-icon.png"))); // NOI18N bnNewRule.setText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.NewText")); // NOI18N bnNewRule.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.NewRuleTooltip_1")); // NOI18N bnNewRule.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnNewRuleActionPerformed(evt); } }); bnDeleteRule.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/experimental/images/minus-icon.png"))); // NOI18N bnDeleteRule.setText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.DeleteText")); // NOI18N bnDeleteRule.setToolTipText(org.openide.util.NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.DeleteTooltip_1")); // NOI18N bnDeleteRule.setEnabled(false); bnDeleteRule.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnDeleteRuleActionPerformed(evt); } }); bnClose.setText("Close"); bnClose.setToolTipText("Close the settings panel"); bnClose.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { bnCloseActionPerformed(evt); } }); lbExplanation.setText("File Export occurs after ingest has completed, automatically exporting files matching the rules specified below. Individual components of the rule are ANDed together."); 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() .addComponent(cbEnableFileExport) .addGap(39, 39, 39) .addComponent(lbExplanation) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() .addGap(36, 36, 36) .addComponent(bnNewRule, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(bnDeleteRule) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(bnClose, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(21, 21, 21)) .addGroup(layout.createSequentialGroup() .addComponent(mainPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 1051, Short.MAX_VALUE) .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(cbEnableFileExport) .addComponent(lbExplanation)) .addGap(7, 7, 7) .addComponent(mainPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 455, Short.MAX_VALUE) .addGap(1, 1, 1) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(bnDeleteRule) .addComponent(bnNewRule) .addComponent(bnClose)) .addContainerGap()) ); }// </editor-fold>//GEN-END:initComponents /** * Handles clicking the "New Rule" button. * * @param evt The event which caused this call. */ private void bnNewRuleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnNewRuleActionPerformed if (hasRuleChanged()) { // if rule has changed without saving if (JOptionPane.showConfirmDialog(this, NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.UnsavedChangesLost"), NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.ChangesWillBeLost"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE) == JOptionPane.CANCEL_OPTION) { // they were not quite ready to navigate away yet, so clear the selection treeSelectionModel.clearSelection(); return; } } clearRuleEditor(); localRule = makeRuleFromUserInput(); }//GEN-LAST:event_bnNewRuleActionPerformed /** * Handles clicking the "Delete Rule" button. * * @param evt The event which caused this call. */ private void bnDeleteRuleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnDeleteRuleActionPerformed Item item = (Item) ((DefaultMutableTreeNode) trRuleList.getLastSelectedPathComponent()).getUserObject(); if (item != null) { if (item.getItemType() == ItemType.RULE) { String ruleName = item.getName(); if (JOptionPane.showConfirmDialog(this, NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.ReallyDeleteRule") + " " + ruleName + NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.QuestionMark"), NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.ConfirmRuleDeletion"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE) == JOptionPane.OK_OPTION) { exportRuleSet.removeRule(ruleName); clearRuleEditor(); localRule = makeRuleFromUserInput(); populateRuleTree(ruleName); } } } else { logger.log(Level.WARNING, "Nothing selected to delete"); } }//GEN-LAST:event_bnDeleteRuleActionPerformed /** * Deconflict artifact names in the tree view. * * @param initalName The base name to start with * @param rule The rule we are deconflicting * * @return The new name, or throw IllegalArgumentException */ String getArtifactClauseNameAndNumber(String initialName, Rule rule) { int number = 1; if (rule != null) { for (ArtifactCondition ac : rule.getArtifactConditions()) { int location = ac.getTreeDisplayName().lastIndexOf('_'); if (ac.getTreeDisplayName().startsWith(initialName)) { int temp = Integer.parseInt(ac.getTreeDisplayName().substring(location + 1)); if (temp >= number) { number = temp + 1; } } } if (number == Integer.MAX_VALUE) { // It never became unique, so give up. throw new IllegalArgumentException("Too many attributes named " + initialName); //NON-NLS } } return (initialName + "_" + Integer.toString(number)); } /** * Creates a rule from the rule editor components on the right side of the * panel. * * @return the rule created from the user's inputs. */ private Rule makeRuleFromUserInput() { return makeRuleFromUserInput(false); } /** * Creates a rule from the rule editor components on the right side of the * panel. * * @param showFailures If there is a failure, shows the user a dialog box * with an explanation of why it failed. * * @return the rule created from the user's inputs. */ private Rule makeRuleFromUserInput(boolean showFailures) { String ruleName = tbRuleName.getText(); Rule rule = new Rule(ruleName); FileSizeCondition fileSizeCondition = null; if (cbFileSize.isSelected()) { try { spFileSizeValue.commitEdit(); fileSizeCondition = new Rule.FileSizeCondition((Integer) spFileSizeValue.getValue(), SizeUnit.valueOf(comboBoxFileSizeUnits.getSelectedItem().toString()), RelationalOp.fromSymbol(comboBoxFileSizeComparison.getSelectedItem().toString())); } catch (ParseException ex) { fileSizeCondition = null; logger.log(Level.WARNING, "Could not create size condition for rule %s: " + ruleName, ex); //NON-NLS } } FileMIMETypeCondition fileMIMETypeCondition = null; if (cbMimeType.isSelected()) { fileMIMETypeCondition = new Rule.FileMIMETypeCondition(comboBoxMimeValue.getSelectedItem().toString(), RelationalOp.fromSymbol(comboBoxMimeTypeComparison.getSelectedItem().toString())); } try { ArtifactCondition artifactCondition = getArtifactConditionFromInput(rule); if (fileSizeCondition != null) { rule.addFileSizeCondition(fileSizeCondition); } if (fileMIMETypeCondition != null) { rule.addFileMIMETypeCondition(fileMIMETypeCondition); } if (artifactCondition != null) { rule.addArtfactCondition(artifactCondition); } return rule; } catch (IllegalArgumentException ex) { String message = "Attribute value '" + tbAttributeValue.getText() + "' is not of type " + comboBoxValueType.getSelectedItem().toString() + ". Ignoring invalid Attribute Type clause."; logger.log(Level.INFO, message); if (showFailures) { JOptionPane.showMessageDialog(this, message, "Invalid Type Conversion", JOptionPane.OK_OPTION); } cbAttributeType.setSelected(false); return null; } } /** * Get the artifact condition from the user's input * * @return the ArtifactCondition, or null if there isn't one. */ ArtifactCondition getArtifactConditionFromInput(Rule rule) throws IllegalArgumentException { ArtifactCondition artifactCondition = null; if (cbAttributeType.isSelected()) { String selectedAttribute = comboBoxAttributeName.getSelectedItem().toString(); BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE typeFromComboBox = BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromLabel(comboBoxValueType.getSelectedItem().toString()); BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE intrinsicType = attributeTypeMap.get(comboBoxAttributeName.getSelectedItem().toString()); // if we don't have a type in the map, but they have set the combobox, put it in the map if (intrinsicType == null && typeFromComboBox != null) { intrinsicType = typeFromComboBox; attributeTypeMap.put(selectedAttribute, typeFromComboBox); } if (intrinsicType == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) { LocalDateTime localDateTime = dateTimePicker.getDateTime(); if (localDateTime == null) { throw new IllegalArgumentException("Bad date/time combination"); } Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); String stringValue = Long.toString(Date.from(instant).getTime()); artifactCondition = new Rule.ArtifactCondition( comboBoxArtifactName.getSelectedItem().toString(), comboBoxAttributeName.getSelectedItem().toString(), stringValue, intrinsicType, RelationalOp.fromSymbol(comboBoxAttributeComparison.getSelectedItem().toString())); } else if (intrinsicType == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE) { try { String stringValue = tbAttributeValue.getText(); byte[] hexValue = Hex.decodeHex(stringValue.toCharArray()); String finalValue = new String(Hex.encodeHex(hexValue)); artifactCondition = new Rule.ArtifactCondition( comboBoxArtifactName.getSelectedItem().toString(), comboBoxAttributeName.getSelectedItem().toString(), finalValue, intrinsicType, RelationalOp.fromSymbol(comboBoxAttributeComparison.getSelectedItem().toString())); } catch (DecoderException ex) { throw new IllegalArgumentException(ex); } } else if (intrinsicType != null) { artifactCondition = new Rule.ArtifactCondition( comboBoxArtifactName.getSelectedItem().toString(), comboBoxAttributeName.getSelectedItem().toString(), tbAttributeValue.getText(), intrinsicType, RelationalOp.fromSymbol(comboBoxAttributeComparison.getSelectedItem().toString())); } else { throw new IllegalArgumentException(); } } return artifactCondition; } /** * Handles clicking the "Save Rule" button. * * @param evt The event which caused this call. */ private void bnSaveRuleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnSaveRuleActionPerformed saveOrUpdateRule(); }//GEN-LAST:event_bnSaveRuleActionPerformed /** * Get the TreePath to this Artifact clause given a String rule and clause * name * * @param ruleName the rule name to find * @param clauseName the clause name to find * * @return */ private TreePath findTreePathByRuleAndArtifactClauseName(String ruleName, String clauseName) { @SuppressWarnings("unchecked") Enumeration<DefaultMutableTreeNode> enumeration = rootNode.preorderEnumeration(); boolean insideRule = false; while (enumeration.hasMoreElements()) { DefaultMutableTreeNode node = enumeration.nextElement(); Item item = (Item) node.getUserObject(); if (item.getItemType() == ItemType.RULE) { insideRule = node.toString().equalsIgnoreCase(ruleName); } if ((insideRule == true) && (item.getItemType() == ItemType.ARTIFACT_CLAUSE) && (item.getName().compareTo(clauseName) == 0)) { return new TreePath(node.getPath()); } } return null; } /** * Get the TreePath to this rule, given a String rule name. * * @param ruleName the name of the rule to find * * @return the TreePath to this rule, given a String rule name. */ private TreePath findTreePathByRuleName(String ruleName) { @SuppressWarnings("unchecked") Enumeration<DefaultMutableTreeNode> enumeration = rootNode.depthFirstEnumeration(); while (enumeration.hasMoreElements()) { DefaultMutableTreeNode node = enumeration.nextElement(); if (node.toString().equalsIgnoreCase(ruleName)) { return new TreePath(node.getPath()); } } return null; } /** * This method saves the rule from the editor to the tree, if the rule is * not malformed. This means the rule must have a name, and at least one * condition is selected. It updates any existing rule in the tree with the * same name. * */ void saveOrUpdateRule() { String ruleName = tbRuleName.getText(); Rule userInputRule = makeRuleFromUserInput(true); if (userInputRule == null) { // we had bad input. do not continue. return; } if ((ruleName != null && !ruleName.isEmpty()) && (cbFileSize.isSelected() || cbMimeType.isSelected() || cbAttributeType.isSelected())) { localRule = userInputRule; Rule existingRule = exportRuleSet.getRule(ruleName); if (existingRule == null) { // This is a new rule. Store it in the list and put it in the tree. List<ArtifactCondition> userRuleArtifactConditions = userInputRule.getArtifactConditions(); for (ArtifactCondition artifactCondition : userRuleArtifactConditions) { String displayName = artifactCondition.getTreeDisplayName(); artifactCondition.setTreeDisplayName(getArtifactClauseNameAndNumber(displayName, null)); } exportRuleSet.addRule(userInputRule); } else { // Update an existing rule. exportRuleSet.removeRule(existingRule); // remove rule if it exists already, does nothing if it does not exist if (cbMimeType.isSelected()) { FileMIMETypeCondition fileMIMETypeCondition = userInputRule.getFileMIMETypeCondition(); if (fileMIMETypeCondition != null) { existingRule.addFileMIMETypeCondition(fileMIMETypeCondition); } } else { existingRule.removeFileMIMETypeCondition(); } if (cbFileSize.isSelected()) { List<FileSizeCondition> fileSizeConditions = userInputRule.getFileSizeConditions(); for (FileSizeCondition fileSizeCondition : fileSizeConditions) { // Do not need to de-dupliate, as currently implmented in FileExportRuleSet existingRule.addFileSizeCondition(fileSizeCondition); } } else { existingRule.removeFileSizeCondition(); } if (cbAttributeType.isSelected()) { // for every artifact condition in the new rule, disambiguate the name List<ArtifactCondition> userRuleArtifactConditions = userInputRule.getArtifactConditions(); for (ArtifactCondition artifactCondition : userRuleArtifactConditions) { String displayName = artifactCondition.getTreeDisplayName(); String newName = getArtifactClauseNameAndNumber(displayName, existingRule); artifactCondition.setTreeDisplayName(newName); existingRule.addArtfactCondition(artifactCondition); } exportRuleSet.addRule(existingRule); } else { existingRule.removeArtifactConditions(); } exportRuleSet.addRule(existingRule); } populateRuleTree(ruleName); } else { JOptionPane.showMessageDialog(null, NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.RuleNotSaved"), NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.MalformedRule"), JOptionPane.OK_OPTION); } } /** * Handles clicking the "Browse Root Directory" button. * * @param evt The event which caused this call. */ private void bnBrowseRootDirectoryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnBrowseRootDirectoryActionPerformed int returnVal = rootDirectoryChooser.showOpenDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { try { validateAndSanitizeBrowsedDirectory(rootDirectoryChooser, tbRootDirectory); } catch (FolderDidNotValidateException ex) { JOptionPane.showMessageDialog(this, NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.BadRootFolder") + " " + ex.getMessage(), NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.BadFolderForInterestingFileExport"), JOptionPane.OK_OPTION); } } }//GEN-LAST:event_bnBrowseRootDirectoryActionPerformed /** * Handles when any 'condition' check boxes change. * * @param evt The event which caused this call. */ private void checkButtonItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_checkButtonItemStateChanged setSaveButton(); }//GEN-LAST:event_checkButtonItemStateChanged /** * Handles clicking the "Browse Report Directory" button. * * @param evt The event which caused this call. */ private void bnBrowseReportDirectoryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnBrowseReportDirectoryActionPerformed int returnVal = reportDirectoryChooser.showOpenDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { try { validateAndSanitizeBrowsedDirectory(reportDirectoryChooser, tbReportDirectory); } catch (FolderDidNotValidateException ex) { JOptionPane.showMessageDialog(this, NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.BadReportFolder") + " " + ex.getMessage(), NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.BadFolderForInterestingFileExport"), JOptionPane.OK_OPTION); } } }//GEN-LAST:event_bnBrowseReportDirectoryActionPerformed /** * Handles when the MIME value combo box changes * * @param evt */ private void comboBoxMimeValueActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboBoxMimeValueActionPerformed if (-1 == comboBoxMimeValue.getSelectedIndex()) { String item = comboBoxMimeValue.getSelectedItem().toString().trim(); if (-1 == ((DefaultComboBoxModel) comboBoxMimeValue.getModel()).getIndexOf(item)) { comboBoxMimeValue.addItem(item); } } }//GEN-LAST:event_comboBoxMimeValueActionPerformed /** * Set the state of the dialog based upon the input * * @param state the input state */ private void setEnabledState(boolean state) { bnBrowseReportDirectory.setEnabled(state); bnBrowseRootDirectory.setEnabled(state); bnDeleteRule.setEnabled(state); bnSaveRule.setEnabled(state); lbSaveRuleHelper.setVisible(!state); cbFileSize.setEnabled(state); cbMimeType.setEnabled(state); comboBoxFileSizeComparison.setEnabled(state); comboBoxFileSizeUnits.setEnabled(state); comboBoxMimeTypeComparison.setEnabled(state); comboBoxMimeValue.setEnabled(state); mainPanel.setEnabled(state); pnEditRule.setEnabled(state); spFileSizeValue.setEnabled(state); tbReportDirectory.setEnabled(state); tbRootDirectory.setEnabled(state); tbRuleName.setEnabled(state); tbAttributeValue.setEnabled(state); cbAttributeType.setEnabled(state); comboBoxArtifactName.setEnabled(state); comboBoxAttributeComparison.setEnabled(state); comboBoxAttributeName.setEnabled(state); comboBoxValueType.setEnabled(state); trRuleList.setEnabled(state); bnAddAttribute.setEnabled(state); dateTimePicker.setEnabled(state); bnNewRule.setEnabled(state); lbArtifact.setEnabled(state); lbAttribute.setEnabled(state); lbExplanation.setEnabled(state); lbFiles.setEnabled(state); lbReports.setEnabled(state); lsAttributeList.setEnabled(state); lbRuleName.setEnabled(state); lbSaveRuleHelper.setEnabled(state); } private void cbEnableFileExportItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cbEnableFileExportItemStateChanged setEnabledState(cbEnableFileExport.isSelected()); setDeleteAttributeButton(); setSaveButton(); }//GEN-LAST:event_cbEnableFileExportItemStateChanged private void bnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCloseActionPerformed if (saveAndValidateSettings(cbEnableFileExport.isSelected())) { jDialog.dispose(); } }//GEN-LAST:event_bnCloseActionPerformed private void cbAttributeTypeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cbAttributeTypeItemStateChanged setSaveButton(); setAddAttributeButton(); setDeleteAttributeButton(); setTypeColor(); }//GEN-LAST:event_cbAttributeTypeItemStateChanged private void bnAddAttributeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnAddAttributeActionPerformed saveOrUpdateRule(); }//GEN-LAST:event_bnAddAttributeActionPerformed private void tbRuleNameKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_tbRuleNameKeyTyped setAddAttributeButton(); }//GEN-LAST:event_tbRuleNameKeyTyped private void comboBoxArtifactNameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboBoxArtifactNameActionPerformed if (-1 == comboBoxArtifactName.getSelectedIndex()) { // if the selected item is not in the drop down list String item = comboBoxArtifactName.getSelectedItem().toString().trim(); if (-1 == ((DefaultComboBoxModel) comboBoxArtifactName.getModel()).getIndexOf(item)) { comboBoxArtifactName.addItem(item); } } setSaveButton(); setAddAttributeButton(); }//GEN-LAST:event_comboBoxArtifactNameActionPerformed private void comboBoxAttributeNameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboBoxAttributeNameActionPerformed if (-1 == comboBoxAttributeName.getSelectedIndex()) { // if the selected item is not in the drop down list String item = comboBoxAttributeName.getSelectedItem().toString().trim(); if (-1 == ((DefaultComboBoxModel) comboBoxAttributeName.getModel()).getIndexOf(item)) { comboBoxAttributeName.addItem(item); comboBoxValueType.setSelectedItem(UNSET); comboBoxValueType.setEnabled(true); } } else { BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE typeFromMap = attributeTypeMap.get(comboBoxAttributeName.getSelectedItem().toString()); if (typeFromMap != null) { comboBoxValueType.setSelectedItem(typeFromMap.getLabel()); comboBoxValueType.setEnabled(false); } else { comboBoxValueType.setSelectedItem(UNSET); comboBoxValueType.setEnabled(true); } } setSaveButton(); setAddAttributeButton(); setTypeColor(); }//GEN-LAST:event_comboBoxAttributeNameActionPerformed private void comboBoxValueTypeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboBoxValueTypeActionPerformed setSaveButton(); setAddAttributeButton(); setTypeColor(); setValueField(); }//GEN-LAST:event_comboBoxValueTypeActionPerformed private void bnDeleteAttributeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnDeleteAttributeActionPerformed String selection = lsAttributeList.getSelectedValue(); if (selection != null && !selection.isEmpty()) { Item item = (Item) ((DefaultMutableTreeNode) trRuleList.getLastSelectedPathComponent()).getUserObject(); if (item != null) { if (JOptionPane.showConfirmDialog(this, NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.ReallyDeleteCondition") + " " + selection + NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.QuestionMark"), NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.ConfirmClauseDeletion"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE) == JOptionPane.OK_OPTION) { String ruleName = item.getRuleName(); // get the rule Rule rule = exportRuleSet.getRule(ruleName); // find the clause and remove it for (ArtifactCondition ac : rule.getArtifactConditions()) { if (selection.compareTo(ac.getTreeDisplayName()) == 0) { rule.removeArtifactCondition(ac); break; } } if (isRuleEmpty(rule)) { exportRuleSet.removeRule(rule); } populateRuleTree(ruleName); } } } }//GEN-LAST:event_bnDeleteAttributeActionPerformed private void lsAttributeListValueChanged(javax.swing.event.ListSelectionEvent evt) { if (evt.getValueIsAdjusting() == false) { // if this is the final iteration through the value changed handler if (lsAttributeList.getSelectedIndex() >= 0) { // and we have a selected entry bnDeleteAttribute.setEnabled(true); DefaultMutableTreeNode node = (DefaultMutableTreeNode) trRuleList.getLastSelectedPathComponent(); if (node == null) { // Nothing is selected return; } Item ruleInfo = (Item) node.getUserObject(); if (ruleInfo.getItemType() == ItemType.RULE_SET) { return; } Object listItem = lsAttributeList.getSelectedValue(); if (listItem != null) { Rule rule = exportRuleSet.getRules().get(ruleInfo.getRuleName()); if (rule != null) { // find the attribute to select for (ArtifactCondition ac : rule.getArtifactConditions()) { if (ac.getTreeDisplayName().compareTo(listItem.toString()) == 0) { // set selected and expand it TreePath shortPath = findTreePathByRuleName(rule.getName()); TreePath treePath = findTreePathByRuleAndArtifactClauseName(rule.getName(), listItem.toString()); trRuleList.expandPath(shortPath); // Don't let treeSelectionListener respond trRuleList.removeTreeSelectionListener(treeSelectionListener); treeSelectionModel.setSelectionPath(treePath); populateArtifactEditor(ac); setDeleteAttributeButton(); trRuleList.addTreeSelectionListener(treeSelectionListener); localRule = makeRuleFromUserInput(); break; } } } } else { bnDeleteAttribute.setEnabled(false); } } } } private void trRuleListValueChanged(javax.swing.event.TreeSelectionEvent evt) { int selectionCount = treeSelectionModel.getSelectionCount(); lsAttributeList.removeAll(); attributeListModel.removeAllElements(); if (selectionCount > 0) { if (hasRuleChanged()) { // and the rule has changed without saving if (JOptionPane.showConfirmDialog(this, NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.UnsavedChangesLost"), NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.ChangesWillBeLost"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE) == JOptionPane.CANCEL_OPTION) { // they were not quite ready to navigate away yet, so clear the selection trRuleList.clearSelection(); return; } } DefaultMutableTreeNode node = (DefaultMutableTreeNode) trRuleList.getLastSelectedPathComponent(); if (node == null) { // Nothing is selected return; } Item nodeInfo = (Item) node.getUserObject(); bnDeleteRule.setEnabled(nodeInfo.getItemType() == ItemType.RULE); if (nodeInfo.getItemType() == ItemType.RULE_SET) { tbRuleName.setText(null); clearSizeCondition(); clearMIMECondition(); clearArtifactCondition(); localRule = makeRuleFromUserInput(); return; } String selectedRuleName = nodeInfo.getRuleName(); Rule rule = exportRuleSet.getRules().get(selectedRuleName); if (rule != null) { // Read values for this rule and display them in the UI tbRuleName.setText(rule.getName()); FileMIMETypeCondition fileMIMETypeCondition = rule.getFileMIMETypeCondition(); if (fileMIMETypeCondition != null) { // if there is a MIME type condition cbMimeType.setSelected(true); comboBoxMimeTypeComparison.setSelectedItem(fileMIMETypeCondition.getRelationalOp().getSymbol()); comboBoxMimeValue.setSelectedItem(fileMIMETypeCondition.getMIMEType()); } else { // Clear the selection clearMIMECondition(); } List<FileSizeCondition> fileSizeCondition = rule.getFileSizeConditions(); if (fileSizeCondition != null && !fileSizeCondition.isEmpty()) { // if there is a file size condition FileSizeCondition condition = fileSizeCondition.get(0); cbFileSize.setSelected(true); spFileSizeValue.setValue(condition.getSize()); comboBoxFileSizeUnits.setSelectedItem(condition.getUnit().toString()); comboBoxFileSizeComparison.setSelectedItem(condition.getRelationalOperator().getSymbol()); } else { // Clear the selection clearSizeCondition(); } ArtifactCondition artifactConditionToPopulateWith = null; List<ArtifactCondition> artifactConditions = rule.getArtifactConditions(); if (nodeInfo.getItemType() != ItemType.ARTIFACT_CLAUSE) { // if there are any attribute clauses, populate the first one, otherwise clear artifact editor if (artifactConditions.isEmpty()) { clearArtifactCondition(); } else { artifactConditionToPopulateWith = artifactConditions.get(0); } } else { // an artifact clause is selected. populate it. for (ArtifactCondition artifact : artifactConditions) { if (artifact.getTreeDisplayName().compareTo(nodeInfo.getName()) == 0) { artifactConditionToPopulateWith = artifact; break; } } } if (artifactConditionToPopulateWith != null) { for (ArtifactCondition artifact : artifactConditions) { attributeListModel.addElement(artifact.getTreeDisplayName()); } // Don't let listSelectionListener respond lsAttributeList.removeListSelectionListener(listSelectionListener); lsAttributeList.setSelectedValue(artifactConditionToPopulateWith.getTreeDisplayName(), true); populateArtifactEditor(artifactConditionToPopulateWith); setDeleteAttributeButton(); lsAttributeList.addListSelectionListener(listSelectionListener); } } localRule = makeRuleFromUserInput(); } else { bnDeleteRule.setEnabled(false); } } void setAddAttributeButton() { if (!tbRuleName.getText().isEmpty()) { bnAddAttribute.setEnabled((cbAttributeType.isSelected()) && (comboBoxValueType.getSelectedItem().toString().compareTo(UNSET) != 0)); } else { bnAddAttribute.setEnabled(false); } } void setDeleteAttributeButton() { String selection = lsAttributeList.getSelectedValue(); bnDeleteAttribute.setEnabled(selection != null && !selection.isEmpty() && cbEnableFileExport.isSelected() != false); } /** * Clears out the fields of the file size condition, reseting them to the * default value. */ private void clearSizeCondition() { cbFileSize.setSelected(false); spFileSizeValue.setValue(1024); comboBoxFileSizeUnits.setSelectedIndex(0); comboBoxFileSizeComparison.setSelectedIndex(0); } /** * Clears out the fields of the MIME Type condition, reseting them to the * default value. */ private void clearMIMECondition() { cbMimeType.setSelected(false); comboBoxMimeValue.setSelectedIndex(0); comboBoxMimeTypeComparison.setSelectedIndex(0); } /** * Clears out the fields of the Artifact condition, reseting them to the * default value. */ private void clearArtifactCondition() { tbAttributeValue.setText(""); cbAttributeType.setSelected(false); comboBoxArtifactName.setSelectedIndex(0); comboBoxAttributeComparison.setSelectedIndex(0); comboBoxAttributeName.setSelectedIndex(0); comboBoxValueType.setSelectedIndex(0); dateTimePicker.clear(); } /** * Clears out the fields of the entire rule editor, reseting them to the * default value and clearing the selection in the rule list on the left. */ private void clearRuleEditor() { tbRuleName.setText(null); clearSizeCondition(); clearMIMECondition(); clearArtifactCondition(); trRuleList.clearSelection(); } /** * Checks if a rule has changed since the last snapshot stored in localRule. * * @return True if the rule has changed, False otherwise */ boolean hasRuleChanged() { return (!localRule.equals(makeRuleFromUserInput())); } /** * Check if this rule has no clauses left. * * @param rule The rule to check * * @return True if the rule is empty, false otherwise. */ boolean isRuleEmpty(Rule rule) { FileMIMETypeCondition mtc = rule.getFileMIMETypeCondition(); List<FileSizeCondition> fsc = rule.getFileSizeConditions(); List<ArtifactCondition> arc = rule.getArtifactConditions(); // if there are no clauses in the rule, it's empty. return (mtc == null) && (fsc == null || fsc.isEmpty()) && (arc == null || arc.isEmpty()); } /** * Validates that the selected folder exists, and sets the passed-in * textField to empty if it does not exist. Then checks if the sanitized * folder is readable and writable with the current user's credentials, * returning True if so and False if not. This has the desirable effect that * a folder can show up in the text box (as chosen by the user while * browsing), and still return false if the permissions are incorrect. This * way the user can see the folder chosen and take appropriate action to fix * the permissions. Use this only for files chosen by the file chooser. * * @param fileChooser The fileChooser we want to use. * @param textField The text field to store the sanitized value in. * * Throws FolderDidNotValidateException */ private void validateAndSanitizeBrowsedDirectory(JFileChooser fileChooser, JTextField textField) throws FolderDidNotValidateException { File selectedFile = fileChooser.getSelectedFile(); if (selectedFile == null || !selectedFile.exists()) { textField.setText(""); //NON-NLS throw new FolderDidNotValidateException(NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.UnableToFindDirectory")); } else { textField.setText(selectedFile.toString()); File file = new File(selectedFile.toString()); fileChooser.setCurrentDirectory(file); if (!FileUtil.hasReadWriteAccess(file.toPath())) { throw new FolderDidNotValidateException(NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.PermissionsInvalid")); } } } /** * Validates that the selected folder exists, then checks if the sanitized * folder is readable and writable with the current user's credentials. * Throws and exception with explanatory text if the folder is not valid. * This has none of the side effects of the above method such as setting the * JFileChooser and JTextFields. This method only checks if the passed-in * String is a valid directory for our purposes. * * @param selectedString The String to validate * * @return Returns the validated String, if possible * * throws FolderDidNotValidateException */ private String validateDirectory(String selectedString) throws FolderDidNotValidateException { File selectedFile = new File(selectedString); if (!selectedFile.exists()) { throw new FolderDidNotValidateException(NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.UnableToFindDirectory")); } else { File file = new File(selectedFile.toString()); if (!FileUtil.hasReadWriteAccess(file.toPath())) { throw new FolderDidNotValidateException(NbBundle.getMessage(FileExporterSettingsPanel.class, "FileExporterSettingsPanel.PermissionsInvalid")); } } return selectedString; } /** * Allows Options Panel to tell if the root directory is valid. * Throws an exception with explanatory text if it is not valid. * * throws FolderDidNotValidateException */ void validateRootDirectory() throws FolderDidNotValidateException { tbRootDirectory.setText(validateDirectory(tbRootDirectory.getText())); } /** * Allows Options Panel to tell if the report directory is valid. * Throws an exception with explanatory text if it is not valid. * * throws FolderDidNotValidateException */ void validateReportDirectory() throws FolderDidNotValidateException { tbReportDirectory.setText(validateDirectory(tbReportDirectory.getText())); } /** * Store the settings to disk. */ public void store() { FileExportSettings settings = new FileExportSettings(); settings.setFilesRootDirectory(Paths.get(tbRootDirectory.getText())); settings.setReportsRootDirectory(Paths.get(tbReportDirectory.getText())); settings.setFileExportEnabledState(cbEnableFileExport.isSelected()); TreeMap<String, FileExportRuleSet> treeMap = new TreeMap<>(); treeMap.put(exportRuleSet.getName(), exportRuleSet); settings.setRuleSets(treeMap); try { FileExportSettings.store(settings); } catch (FileExportSettings.PersistenceException ex) { logger.log(Level.SEVERE, "Unable to save rules: ", ex); //NON-NLS } } /** * Read the settings from disk. */ public void load() { try { FileExportSettings settings = FileExportSettings.load(); if (settings != null) { Path path = settings.getFilesRootDirectory(); if (path != null) { tbRootDirectory.setText(path.toString()); } path = settings.getReportsRootDirectory(); if (path != null) { tbReportDirectory.setText(path.toString()); } TreeMap<String, FileExportRuleSet> treeMap = settings.getRuleSets(); if (treeMap != null && !treeMap.isEmpty()) { exportRuleSet = treeMap.firstEntry().getValue(); } boolean answer = settings.getFileExportEnabledState(); setEnabledState(answer); cbEnableFileExport.setSelected(answer); } return; } catch (FileExportSettings.PersistenceException ex) { logger.log(Level.INFO, "Unable to load rule settings: {0}", ex.getMessage()); //NON-NLS } setEnabledState(false); cbEnableFileExport.setSelected(false); } class FolderDidNotValidateException extends Exception { private static final long serialVersionUID = 1L; FolderDidNotValidateException(String message) { super(message); } } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton bnAddAttribute; private javax.swing.JButton bnBrowseReportDirectory; private javax.swing.JButton bnBrowseRootDirectory; private javax.swing.JButton bnClose; private javax.swing.JButton bnDeleteAttribute; private javax.swing.JButton bnDeleteRule; private javax.swing.JButton bnNewRule; private javax.swing.JButton bnSaveRule; private javax.swing.JCheckBox cbAttributeType; private javax.swing.JCheckBox cbEnableFileExport; private javax.swing.JCheckBox cbFileSize; private javax.swing.JCheckBox cbMimeType; private javax.swing.JComboBox<String> comboBoxArtifactName; private javax.swing.JComboBox<String> comboBoxAttributeComparison; private javax.swing.JComboBox<String> comboBoxAttributeName; private javax.swing.JComboBox<String> comboBoxFileSizeComparison; private javax.swing.JComboBox<String> comboBoxFileSizeUnits; private javax.swing.JComboBox<String> comboBoxMimeTypeComparison; private javax.swing.JComboBox<String> comboBoxMimeValue; private javax.swing.JComboBox<String> comboBoxValueType; private com.github.lgooddatepicker.datetimepicker.DateTimePicker dateTimePicker; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JLabel lbArtifact; private javax.swing.JLabel lbAttribute; private javax.swing.JLabel lbExplanation; private javax.swing.JLabel lbFiles; private javax.swing.JLabel lbReports; private javax.swing.JLabel lbRuleName; private javax.swing.JLabel lbSaveRuleHelper; private javax.swing.JList<String> lsAttributeList; private javax.swing.JPanel mainPanel; private javax.swing.JPanel pnEditRule; private javax.swing.JScrollPane ruleListScrollPane; private javax.swing.JSpinner spFileSizeValue; private javax.swing.JTextField tbAttributeValue; private javax.swing.JTextField tbReportDirectory; private javax.swing.JTextField tbRootDirectory; private javax.swing.JTextField tbRuleName; private javax.swing.JTree trRuleList; // End of variables declaration//GEN-END:variables }