From 0fba2152daba209d6e299ca98b40ddcd59d61047 Mon Sep 17 00:00:00 2001 From: Oliver Spohngellert Date: Mon, 22 Feb 2016 15:43:09 -0500 Subject: [PATCH] Finished condition adding. --- .../modules/interestingitems/FilesSet.java | 115 ++++++++--- .../interestingitems/FilesSetRulePanel.form | 9 + .../interestingitems/FilesSetRulePanel.java | 113 ++++++++--- .../InterestingItemDefsManager.java | 178 +++++++----------- .../InterestingItemDefsPanel.java | 32 +++- 5 files changed, 279 insertions(+), 168 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java index 0e8fff948b..2bcdc56de9 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java @@ -257,7 +257,23 @@ final class FilesSet implements Serializable { public String toString() { // This override is designed to provide a display name for use with // javax.swing.DefaultListModel. - return this.ruleName + " (" + fileNameCondition.getTextToMatch() + ")"; + if(fileNameCondition != null) { + return this.ruleName + " (" + fileNameCondition.getTextToMatch() + ")"; + } + else if (this.pathCondition != null) { + return this.ruleName + " (" + pathCondition.getTextToMatch() + ")"; + } + else if (this.mimeTypeCondition != null) { + return this.ruleName + " (" + mimeTypeCondition.getMimeType() + ")"; + } + else if (this.fileSizeCondition != null) { + return this.ruleName + " (" + fileSizeCondition.getComparator().getSymbol() + " " + fileSizeCondition.getSizeValue() + + " " + fileSizeCondition.getUnit().getName() + ")"; + } + else { + return this.ruleName + " ()"; + } + } /** @@ -274,6 +290,13 @@ final class FilesSet implements Serializable { return mimeTypeCondition; } + /** + * @return the fileSizeCondition + */ + public FileSizeCondition getFileSizeCondition() { + return fileSizeCondition; + } + /** * An interface for the file attribute conditions of which interesting * files set membership rules are composed. @@ -331,13 +354,40 @@ final class FilesSet implements Serializable { private static final long serialVersionUID = 1L; + /** + * @return the comparator + */ + public COMPARATOR getComparator() { + return comparator; + } + + /** + * @return the unit + */ + public SIZE_UNIT getUnit() { + return unit; + } + + /** + * @return the sizeValue + */ + public int getSizeValue() { + return sizeValue; + } + static enum COMPARATOR { - LESS_THAN, - LESS_THAN_EQUAL, - EQUAL, - GREATER_THAN, - GREATER_THAN_EQUAL; + LESS_THAN("<"), + LESS_THAN_EQUAL("≤"), + EQUAL("="), + GREATER_THAN(">"), + GREATER_THAN_EQUAL("≥"); + + private String symbol; + + COMPARATOR(String symbol) { + this.symbol = symbol; + } public static COMPARATOR fromSymbol(String symbol) { if (symbol.equals("<=") || symbol.equals("≤")) { @@ -354,18 +404,27 @@ final class FilesSet implements Serializable { throw new IllegalArgumentException("Invalid symbol"); } } + + /** + * @return the symbol + */ + public String getSymbol() { + return symbol; + } } static enum SIZE_UNIT { - BYTE(1), - KILOBYTE(1024), - MEGABYTE(1024 * 1024), - GIGABYTE(1024 * 1024 * 1024); + BYTE(1, "Bytes"), + KILOBYTE(1024, "Kilobytes"), + MEGABYTE(1024 * 1024, "Megabytes"), + GIGABYTE(1024 * 1024 * 1024, "Gigabytes"); private long size; + private String name; - private SIZE_UNIT(long size) { + private SIZE_UNIT(long size, String name) { this.size = size; + this.name = name; } public long getSize() { @@ -373,24 +432,26 @@ final class FilesSet implements Serializable { } public static SIZE_UNIT fromName(String name) { - if (name.equals("Bytes")) { - return BYTE; - } else if (name.equals("Kilobytes")) { - return KILOBYTE; - } else if (name.equals("Megabytes")) { - return MEGABYTE; - } else if (name.equals("Gigabytes")) { - return GIGABYTE; - } else { - throw new IllegalArgumentException("Invalid symbol"); + for (SIZE_UNIT unit : SIZE_UNIT.values()) { + if (unit.getName().equals(name)) { + return unit; + } } + throw new IllegalArgumentException("Invalid name for size unit."); + } + + /** + * @return the name + */ + public String getName() { + return name; } } private COMPARATOR comparator; private SIZE_UNIT unit; private int sizeValue; - FileSizeCondition(COMPARATOR comparator, SIZE_UNIT uint, int sizeValue) { + FileSizeCondition(COMPARATOR comparator, SIZE_UNIT unit, int sizeValue) { this.comparator = comparator; this.unit = unit; this.sizeValue = sizeValue; @@ -399,8 +460,8 @@ final class FilesSet implements Serializable { @Override public boolean passes(AbstractFile file) { long fileSize = file.getSize(); - long conditionSize = this.unit.getSize() * this.sizeValue; - switch (this.comparator) { + long conditionSize = this.getUnit().getSize() * this.getSizeValue(); + switch (this.getComparator()) { case GREATER_THAN: return fileSize > conditionSize; case GREATER_THAN_EQUAL: @@ -508,7 +569,6 @@ final class FilesSet implements Serializable { */ private static abstract class AbstractTextCondition implements TextCondition { - private static final long serialVersionUID = 1L; private final TextMatcher textMatcher; /** @@ -702,7 +762,7 @@ final class FilesSet implements Serializable { * An interface for objects that do textual matches, used to compose a * text condition. */ - private static interface TextMatcher { + private static interface TextMatcher extends Serializable { /** * Get the text the matcher examines. @@ -736,6 +796,7 @@ final class FilesSet implements Serializable { */ private static class CaseInsensitiveStringComparisionMatcher implements TextMatcher { + private static final long serialVersionUID = 1L; private final String textToMatch; /** @@ -779,6 +840,7 @@ final class FilesSet implements Serializable { */ private static class CaseInsensitivePartialStringComparisionMatcher implements TextMatcher { + private static final long serialVersionUID = 1L; private final String textToMatch; private final Pattern pattern; @@ -823,6 +885,7 @@ final class FilesSet implements Serializable { */ private static class RegexMatcher implements TextMatcher { + private static final long serialVersionUID = 1L; private final Pattern regex; /** diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form index 75f9965d32..ee526067d5 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.form @@ -351,6 +351,9 @@ + + + @@ -361,6 +364,9 @@ + + + @@ -371,6 +377,9 @@ + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java index ae3acd545d..481a3debaf 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSetRulePanel.java @@ -50,7 +50,12 @@ final class FilesSetRulePanel extends javax.swing.JPanel { "FilesSetRulePanel.bytes=Bytes", "FilesSetRulePanel.kiloBytes=Kilobytes", "FilesSetRulePanel.megaBytes=Megabytes", - "FilesSetRulePanel.gigaBytes=Gigabytes" + "FilesSetRulePanel.gigaBytes=Gigabytes", + "FilesSetRulePanel.NoConditionError=Must have at least one condition to make a rule.", + "FilesSetRulePanel.NoMimeTypeError=Please select a valid MIME type.", + "FilesSetRulePanel.NoNameError=Name cannot be empty", + "FilesSetRulePanel.NoPathError=Path cannot be empty", + "FilesSetRulePanel.ZeroFileSizeError=File size condition value must not be 0." }) private static final SortedSet mediaTypes = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes(); @@ -139,8 +144,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { if (!(this.fileSizeCheck.isSelected() || this.mimeCheck.isSelected() || this.nameCheck.isSelected() || this.pathCheck.isSelected())) { this.okButton.setEnabled(false); - } - else { + } else { this.okButton.setEnabled(true); } } @@ -242,40 +246,55 @@ final class FilesSetRulePanel extends javax.swing.JPanel { */ boolean isValidRuleDefinition() { - // The rule must have name condition text. - if (this.nameTextField.getText().isEmpty()) { + if (!(this.mimeCheck.isSelected() || this.fileSizeCheck.isSelected() || this.pathCheck.isSelected() || this.nameCheck.isSelected())) { NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( - NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.emptyNameCondition"), + Bundle.FilesSetRulePanel_NoConditionError(), NotifyDescriptor.WARNING_MESSAGE); DialogDisplayer.getDefault().notify(notifyDesc); return false; } - // The name condition must either be a regular expression that compiles or - // a string without illegal file name chars. - if (this.nameRegexCheckbox.isSelected()) { - try { - Pattern.compile(this.nameTextField.getText()); - } catch (PatternSyntaxException ex) { + if (this.nameCheck.isSelected()) { + // The name condition must either be a regular expression that compiles or + // a string without illegal file name chars. + if (this.nameTextField.getText().isEmpty()) { NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( - NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.invalidNameRegex", ex.getLocalizedMessage()), + Bundle.FilesSetRulePanel_NoNameError(), NotifyDescriptor.WARNING_MESSAGE); DialogDisplayer.getDefault().notify(notifyDesc); return false; } - } else { - if (!FilesSetRulePanel.containsOnlyLegalChars(this.nameTextField.getText(), FilesSetRulePanel.ILLEGAL_FILE_NAME_CHARS)) { - NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( - NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.invalidCharInName"), - NotifyDescriptor.WARNING_MESSAGE); - DialogDisplayer.getDefault().notify(notifyDesc); - return false; + if (this.nameRegexCheckbox.isSelected()) { + try { + Pattern.compile(this.nameTextField.getText()); + } catch (PatternSyntaxException ex) { + NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( + NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.invalidNameRegex", ex.getLocalizedMessage()), + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDesc); + return false; + } + } else { + if (this.nameTextField.getText().isEmpty() || !FilesSetRulePanel.containsOnlyLegalChars(this.nameTextField.getText(), FilesSetRulePanel.ILLEGAL_FILE_NAME_CHARS)) { + NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( + NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.invalidCharInName"), + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDesc); + return false; + } } } // The path condition, if specified, must either be a regular expression - // that compiles or a string without illegal file path chars. - if (!this.pathTextField.getText().isEmpty()) { + // that compiles or a string without illegal file path chars. + if (this.pathCheck.isSelected()) { + if (this.pathTextField.getText().isEmpty()) { + NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( + Bundle.FilesSetRulePanel_NoPathError(), + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDesc); + return false; + } if (this.pathRegexCheckBox.isSelected()) { try { Pattern.compile(this.pathTextField.getText()); @@ -287,7 +306,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { return false; } } else { - if (!FilesSetRulePanel.containsOnlyLegalChars(this.pathTextField.getText(), FilesSetRulePanel.ILLEGAL_FILE_PATH_CHARS)) { + if (this.pathTextField.getText().isEmpty() || !FilesSetRulePanel.containsOnlyLegalChars(this.pathTextField.getText(), FilesSetRulePanel.ILLEGAL_FILE_PATH_CHARS)) { NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( NbBundle.getMessage(FilesSetPanel.class, "FilesSetRulePanel.messages.invalidCharInPath"), NotifyDescriptor.WARNING_MESSAGE); @@ -296,6 +315,24 @@ final class FilesSetRulePanel extends javax.swing.JPanel { } } } + if (this.mimeCheck.isSelected()) { + if (this.mimeTypeComboBox.getSelectedIndex() == 0) { + NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( + Bundle.FilesSetRulePanel_NoMimeTypeError(), + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDesc); + return false; + } + } + if (this.fileSizeCheck.isSelected()) { + if ((Integer) this.fileSizeSpinner.getValue() == 0) { + NotifyDescriptor notifyDesc = new NotifyDescriptor.Message( + Bundle.FilesSetRulePanel_ZeroFileSizeError(), + NotifyDescriptor.WARNING_MESSAGE); + DialogDisplayer.getDefault().notify(notifyDesc); + return false; + } + } return true; } @@ -461,7 +498,7 @@ final class FilesSetRulePanel extends javax.swing.JPanel { * state of the UI components in the type button group. */ private void setComponentsForSearchType() { - if (this.dirsRadio.isSelected()) { + if (!this.filesRadio.isSelected()) { this.fullNameRadioButton.setSelected(true); this.extensionRadioButton.setEnabled(false); this.mimeTypeComboBox.setEnabled(false); @@ -601,12 +638,27 @@ final class FilesSetRulePanel extends javax.swing.JPanel { typeButtonGroup.add(filesRadio); org.openide.awt.Mnemonics.setLocalizedText(filesRadio, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.filesRadio.text")); // NOI18N + filesRadio.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + filesRadioActionPerformed(evt); + } + }); typeButtonGroup.add(dirsRadio); org.openide.awt.Mnemonics.setLocalizedText(dirsRadio, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.dirsRadio.text")); // NOI18N + dirsRadio.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + dirsRadioActionPerformed(evt); + } + }); typeButtonGroup.add(filesAndDirsRadio); org.openide.awt.Mnemonics.setLocalizedText(filesAndDirsRadio, org.openide.util.NbBundle.getMessage(FilesSetRulePanel.class, "FilesSetRulePanel.filesAndDirsRadio.text")); // NOI18N + filesAndDirsRadio.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + filesAndDirsRadioActionPerformed(evt); + } + }); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); @@ -780,6 +832,19 @@ final class FilesSetRulePanel extends javax.swing.JPanel { // TODO add your handling code here: }//GEN-LAST:event_mimeTypeComboBoxActionPerformed + private void filesRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_filesRadioActionPerformed + + this.setComponentsForSearchType(); + }//GEN-LAST:event_filesRadioActionPerformed + + private void dirsRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dirsRadioActionPerformed + this.setComponentsForSearchType(); + }//GEN-LAST:event_dirsRadioActionPerformed + + private void filesAndDirsRadioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_filesAndDirsRadioActionPerformed + this.setComponentsForSearchType(); + }//GEN-LAST:event_filesAndDirsRadioActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JRadioButton dirsRadio; private javax.swing.JComboBox equalitySymbolComboBox; diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsManager.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsManager.java index a3fdc11926..6d967d545d 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsManager.java @@ -19,6 +19,9 @@ package org.sleuthkit.autopsy.modules.interestingitems; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -29,9 +32,13 @@ import java.util.Observable; import java.util.logging.Level; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; +import javax.persistence.PersistenceException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import org.openide.util.Exceptions; +import org.openide.util.io.NbObjectInputStream; +import org.openide.util.io.NbObjectOutputStream; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.XMLUtil; @@ -50,6 +57,8 @@ final class InterestingItemDefsManager extends Observable { private static final List ILLEGAL_FILE_NAME_CHARS = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("\\", "/", ":", "*", "?", "\"", "<", ">"))); private static final List ILLEGAL_FILE_PATH_CHARS = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("\\", ":", "*", "?", "\"", "<", ">"))); private static final String INTERESTING_FILES_SET_DEFS_FILE_NAME = "InterestingFilesSetDefs.xml"; //NON-NLS + private static final String INTERESING_FILES_SET_DEFS_SERIALIZATION_NAME = "interestingFileSets.settings"; + private static final String INTERESING_FILES_SET_DEFS_SERIALIZATION_PATH = PlatformUtil.getUserConfigDirectory() + File.separator + INTERESING_FILES_SET_DEFS_SERIALIZATION_NAME; private static final String DEFAULT_FILE_SET_DEFS_PATH = PlatformUtil.getUserConfigDirectory() + File.separator + INTERESTING_FILES_SET_DEFS_FILE_NAME; private static InterestingItemDefsManager instance; @@ -86,7 +95,7 @@ final class InterestingItemDefsManager extends Observable { * Gets a copy of the current interesting files set definitions. * * @return A map of interesting files set names to interesting file sets, - * possibly empty. + * possibly empty. */ synchronized Map getInterestingFilesSets() { return FilesSetXML.readDefinitionsFile(DEFAULT_FILE_SET_DEFS_PATH); @@ -97,10 +106,10 @@ final class InterestingItemDefsManager extends Observable { * previous definitions. * * @param filesSets A mapping of interesting files set names to files sets, - * used to enforce unique files set names. + * used to enforce unique files set names. */ synchronized void setInterestingFilesSets(Map filesSets) { - FilesSetXML.writeDefinitionsFile(DEFAULT_FILE_SET_DEFS_PATH, filesSets); + FilesSetXML.writeDefinitionsFile(INTERESING_FILES_SET_DEFS_SERIALIZATION_PATH, filesSets); this.setChanged(); this.notifyObservers(); } @@ -167,7 +176,7 @@ final class InterestingItemDefsManager extends Observable { // Check if the file exists. File defsFile = new File(filePath); if (!defsFile.exists()) { - return filesSets; + return readSerializedDefinitions(); } // Check if the file can be read. @@ -195,16 +204,25 @@ final class InterestingItemDefsManager extends Observable { for (int i = 0; i < setElems.getLength(); ++i) { readFilesSet((Element) setElems.item(i), filesSets, filePath); } - return filesSets; } + private static Map readSerializedDefinitions() { + String filePath = INTERESING_FILES_SET_DEFS_SERIALIZATION_PATH; + try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(filePath.toString()))) { + Map filesSetMap = (Map) in.readObject(); + return filesSetMap; + } catch (IOException | ClassNotFoundException ex) { + throw new PersistenceException(String.format("Failed to read settings from %s", filePath), ex); + } + } + /** * Reads in an interesting files set. * - * @param setElem An interesting files set XML element + * @param setElem An interesting files set XML element * @param filesSets A collection to which the set is to be added. - * @param filePath The source file, used for error reporting. + * @param filePath The source file, used for error reporting. */ private static void readFilesSet(Element setElem, Map filesSets, String filePath) { // The file set must have a unique name. @@ -279,11 +297,11 @@ final class InterestingItemDefsManager extends Observable { * XML element. * * @param filePath The path of the definitions file. - * @param setName The name of the files set. - * @param elem The file name rule XML element. + * @param setName The name of the files set. + * @param elem The file name rule XML element. * * @return A file name rule, or null if there is an error (the error is - * logged). + * logged). */ private static FilesSet.Rule readFileNameRule(Element elem) { String ruleName = FilesSetXML.readRuleName(elem); @@ -292,12 +310,12 @@ final class InterestingItemDefsManager extends Observable { // regex, or it may be from a TSK Framework rule definition with a // "*" globbing char, or it may be simple text. String content = elem.getTextContent(); - FilesSet.Rule.FullNameCondition namecondition; + FilesSet.Rule.FullNameCondition nameCondition; String regex = elem.getAttribute(FilesSetXML.REGEX_ATTR); if ((!regex.isEmpty() && regex.equalsIgnoreCase("true")) || content.contains("*")) { // NON-NLS Pattern pattern = compileRegex(content); if (pattern != null) { - namecondition = new FilesSet.Rule.FullNameCondition(pattern); + nameCondition = new FilesSet.Rule.FullNameCondition(pattern); } else { logger.log(Level.SEVERE, "Error compiling " + FilesSetXML.NAME_RULE_TAG + " regex, ignoring malformed '{0}' rule definition", ruleName); // NON-NLS return null; @@ -309,29 +327,29 @@ final class InterestingItemDefsManager extends Observable { return null; } } - namecondition = new FilesSet.Rule.FullNameCondition(content); + nameCondition = new FilesSet.Rule.FullNameCondition(content); } // Read in the type condition. - FilesSet.Rule.MetaTypeCondition metaTypecondition = FilesSetXML.readMetaTypecondition(elem); - if (metaTypecondition == null) { + FilesSet.Rule.MetaTypeCondition metaTypeCondition = FilesSetXML.readMetaTypeCondition(elem); + if (metaTypeCondition == null) { // Malformed attribute. return null; } // Read in the optional path condition. Null is o.k., but if the attribute // is there, be sure it is not malformed. - FilesSet.Rule.ParentPathCondition pathcondition = null; + FilesSet.Rule.ParentPathCondition pathCondition = null; if (!elem.getAttribute(FilesSetXML.PATH_FILTER_ATTR).isEmpty() || !elem.getAttribute(FilesSetXML.PATH_REGEX_ATTR).isEmpty()) { - pathcondition = FilesSetXML.readPathcondition(elem); - if (pathcondition == null) { + pathCondition = FilesSetXML.readPathCondition(elem); + if (pathCondition == null) { // Malformed attribute. return null; } } - return new FilesSet.Rule(ruleName, namecondition, metaTypecondition, pathcondition, null, null); + return new FilesSet.Rule(ruleName, nameCondition, metaTypeCondition, pathCondition, null, null); } /** @@ -341,7 +359,7 @@ final class InterestingItemDefsManager extends Observable { * @param elem The file name extension rule XML element. * * @return A file name extension rule, or null if there is an error (the - * error is logged). + * error is logged). */ private static FilesSet.Rule readFileExtensionRule(Element elem) { String ruleName = FilesSetXML.readRuleName(elem); @@ -350,12 +368,12 @@ final class InterestingItemDefsManager extends Observable { // be a regex, or it may be from a TSK Framework rule definition // with a "*" globbing char. String content = elem.getTextContent(); - FilesSet.Rule.ExtensionCondition extcondition; + FilesSet.Rule.ExtensionCondition extCondition; String regex = elem.getAttribute(FilesSetXML.REGEX_ATTR); if ((!regex.isEmpty() && regex.equalsIgnoreCase("true")) || content.contains("*")) { // NON-NLS Pattern pattern = compileRegex(content); if (pattern != null) { - extcondition = new FilesSet.Rule.ExtensionCondition(pattern); + extCondition = new FilesSet.Rule.ExtensionCondition(pattern); } else { logger.log(Level.SEVERE, "Error compiling " + FilesSetXML.EXTENSION_RULE_TAG + " regex, ignoring malformed {0} rule definition", ruleName); // NON-NLS return null; @@ -367,35 +385,35 @@ final class InterestingItemDefsManager extends Observable { return null; } } - extcondition = new FilesSet.Rule.ExtensionCondition(content); + extCondition = new FilesSet.Rule.ExtensionCondition(content); } // The rule must have a meta-type condition, unless a TSK Framework // definitions file is being read. - FilesSet.Rule.MetaTypeCondition metaTypecondition = null; + FilesSet.Rule.MetaTypeCondition metaTypeCondition = null; if (!elem.getAttribute(FilesSetXML.TYPE_FILTER_ATTR).isEmpty()) { - metaTypecondition = FilesSetXML.readMetaTypecondition(elem); - if (metaTypecondition == null) { + metaTypeCondition = FilesSetXML.readMetaTypeCondition(elem); + if (metaTypeCondition == null) { // Malformed attribute. return null; } } else { - metaTypecondition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES); + metaTypeCondition = new FilesSet.Rule.MetaTypeCondition(FilesSet.Rule.MetaTypeCondition.Type.FILES); } // The rule may have a path condition. Null is o.k., but if the attribute // is there, it must not be malformed. - FilesSet.Rule.ParentPathCondition pathcondition = null; + FilesSet.Rule.ParentPathCondition pathCondition = null; if (!elem.getAttribute(FilesSetXML.PATH_FILTER_ATTR).isEmpty() || !elem.getAttribute(FilesSetXML.PATH_REGEX_ATTR).isEmpty()) { - pathcondition = FilesSetXML.readPathcondition(elem); - if (pathcondition == null) { + pathCondition = FilesSetXML.readPathCondition(elem); + if (pathCondition == null) { // Malformed attribute. return null; } } - return new FilesSet.Rule(ruleName, extcondition, metaTypecondition, pathcondition, null, null); + return new FilesSet.Rule(ruleName, extCondition, metaTypeCondition, pathCondition, null, null); } /** @@ -428,14 +446,15 @@ final class InterestingItemDefsManager extends Observable { } /** - * Construct a meta-type condition for an interesting files set membership - * rule from data in an XML element. + * Construct a meta-type condition for an interesting files set + * membership rule from data in an XML element. * * @param ruleElement The XML element. * - * @return The meta-type condition, or null if there is an error (logged). + * @return The meta-type condition, or null if there is an error + * (logged). */ - private static FilesSet.Rule.MetaTypeCondition readMetaTypecondition(Element ruleElement) { + private static FilesSet.Rule.MetaTypeCondition readMetaTypeCondition(Element ruleElement) { FilesSet.Rule.MetaTypeCondition condition = null; String conditionAttribute = ruleElement.getAttribute(FilesSetXML.TYPE_FILTER_ATTR); if (!conditionAttribute.isEmpty()) { @@ -462,14 +481,14 @@ final class InterestingItemDefsManager extends Observable { } /** - * Construct a path condition for an interesting files set membership rule - * from data in an XML element. + * Construct a path condition for an interesting files set membership + * rule from data in an XML element. * * @param ruleElement The XML element. * * @return The path condition, or null if there is an error (logged). */ - private static FilesSet.Rule.ParentPathCondition readPathcondition(Element ruleElement) { + private static FilesSet.Rule.ParentPathCondition readPathCondition(Element ruleElement) { FilesSet.Rule.ParentPathCondition condition = null; String path = ruleElement.getAttribute(FilesSetXML.PATH_FILTER_ATTR); String pathRegex = ruleElement.getAttribute(FilesSetXML.PATH_REGEX_ATTR); @@ -499,84 +518,17 @@ final class InterestingItemDefsManager extends Observable { // multiple intersting files set definition files, e.g., one for // definitions that ship with Autopsy and one for user definitions. static boolean writeDefinitionsFile(String filePath, Map interestingFilesSets) { - DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); - try { - // Create the new XML document. - DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); - Document doc = docBuilder.newDocument(); - Element rootElement = doc.createElement(FilesSetXML.FILE_SETS_ROOT_TAG); - doc.appendChild(rootElement); - - // Add the interesting files sets to the document. - for (FilesSet set : interestingFilesSets.values()) { - // Add the files set element and its attributes. - Element setElement = doc.createElement(FilesSetXML.FILE_SET_TAG); - setElement.setAttribute(FilesSetXML.NAME_ATTR, set.getName()); - setElement.setAttribute(FilesSetXML.DESC_ATTR, set.getDescription()); - setElement.setAttribute(FilesSetXML.IGNORE_KNOWN_FILES_ATTR, Boolean.toString(set.ignoresKnownFiles())); - - // Add the child elements for the set membership rules. - for (FilesSet.Rule rule : set.getRules().values()) { - // Add a rule element with the appropriate name condition - // type tag. - FilesSet.Rule.FileNameCondition namecondition = rule.getFileNameCondition(); - Element ruleElement; - if (namecondition instanceof FilesSet.Rule.FullNameCondition) { - ruleElement = doc.createElement(FilesSetXML.NAME_RULE_TAG); - } else { - ruleElement = doc.createElement(FilesSetXML.EXTENSION_RULE_TAG); - } - - // Add the rule name attribute. - ruleElement.setAttribute(FilesSetXML.NAME_ATTR, rule.getName()); - - // Add the name condition regex attribute - ruleElement.setAttribute(FilesSetXML.REGEX_ATTR, Boolean.toString(namecondition.isRegex())); - - // Add the type condition attribute. - FilesSet.Rule.MetaTypeCondition typecondition = rule.getMetaTypeCondition(); - switch (typecondition.getMetaType()) { - case FILES: - ruleElement.setAttribute(FilesSetXML.TYPE_FILTER_ATTR, FilesSetXML.TYPE_FILTER_VALUE_FILES); - break; - case DIRECTORIES: - ruleElement.setAttribute(FilesSetXML.TYPE_FILTER_ATTR, FilesSetXML.TYPE_FILTER_VALUE_DIRS); - break; - default: - ruleElement.setAttribute(FilesSetXML.TYPE_FILTER_ATTR, FilesSetXML.TYPE_FILTER_VALUE_FILES_AND_DIRS); - break; - } - - // Add the optional path condition. - FilesSet.Rule.ParentPathCondition pathcondition = rule.getPathCondition(); - if (pathcondition != null) { - if (pathcondition.isRegex()) { - ruleElement.setAttribute(FilesSetXML.PATH_REGEX_ATTR, pathcondition.getTextToMatch()); - } else { - ruleElement.setAttribute(FilesSetXML.PATH_FILTER_ATTR, pathcondition.getTextToMatch()); - } - } - - // Add the name condition text as the rule element content. - ruleElement.setTextContent(namecondition.getTextToMatch()); - - setElement.appendChild(ruleElement); - } - - rootElement.appendChild(setElement); + try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(filePath))) { + out.writeObject(interestingFilesSets); + File xmlFile = new File(DEFAULT_FILE_SET_DEFS_PATH); + if(xmlFile.exists()) { + xmlFile.delete(); } - - // Overwrite the previous definitions file. Note that the utility - // method logs an error on failure. - return XMLUtil.saveDoc(FilesSetXML.class, filePath, XML_ENCODING, doc); - - } catch (ParserConfigurationException ex) { - logger.log(Level.SEVERE, "Error writing interesting files definition file to " + filePath, ex); // NON-NLS - return false; + return true; + } catch (IOException ex) { + throw new PersistenceException(String.format("Failed to write settings to %s", filePath), ex); } - } - } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java index 508c581913..0455574ca2 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/InterestingItemDefsPanel.java @@ -250,13 +250,22 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp FilesSet.Rule.MetaTypeCondition typeCondition = rule.getMetaTypeCondition(); FilesSet.Rule.ParentPathCondition pathCondition = rule.getPathCondition(); FilesSet.Rule.MimeTypeCondition mimeTypeCondition = rule.getMimeTypeCondition(); + FilesSet.Rule.FileSizeCondition fileSizeCondition = rule.getFileSizeCondition(); // Populate the components that display the properties of the // selected rule. - InterestingItemDefsPanel.this.fileNameTextField.setText(nameCondition.getTextToMatch()); - InterestingItemDefsPanel.this.fileNameRadioButton.setSelected(nameCondition instanceof FilesSet.Rule.FullNameCondition); - InterestingItemDefsPanel.this.fileNameExtensionRadioButton.setSelected(nameCondition instanceof FilesSet.Rule.ExtensionCondition); - InterestingItemDefsPanel.this.fileNameRegexCheckbox.setSelected(nameCondition.isRegex()); + if (nameCondition != null) { + InterestingItemDefsPanel.this.fileNameTextField.setText(nameCondition.getTextToMatch()); + InterestingItemDefsPanel.this.fileNameRadioButton.setSelected(nameCondition instanceof FilesSet.Rule.FullNameCondition); + InterestingItemDefsPanel.this.fileNameExtensionRadioButton.setSelected(nameCondition instanceof FilesSet.Rule.ExtensionCondition); + InterestingItemDefsPanel.this.fileNameRegexCheckbox.setSelected(nameCondition.isRegex()); + } + else { + InterestingItemDefsPanel.this.fileNameTextField.setText(""); + InterestingItemDefsPanel.this.fileNameRadioButton.setSelected(true); + InterestingItemDefsPanel.this.fileNameExtensionRadioButton.setSelected(false); + InterestingItemDefsPanel.this.fileNameRegexCheckbox.setSelected(false); + } switch (typeCondition.getMetaType()) { case FILES: InterestingItemDefsPanel.this.filesRadioButton.setSelected(true); @@ -275,7 +284,20 @@ final class InterestingItemDefsPanel extends IngestModuleGlobalSettingsPanel imp InterestingItemDefsPanel.this.rulePathConditionTextField.setText(""); InterestingItemDefsPanel.this.rulePathConditionRegexCheckBox.setSelected(false); } - InterestingItemDefsPanel.this.mimeTypeComboBox.setSelectedItem(mimeTypeCondition.getMimeType()); + if (mimeTypeCondition != null) { + InterestingItemDefsPanel.this.mimeTypeComboBox.setSelectedItem(mimeTypeCondition.getMimeType()); + } else { + InterestingItemDefsPanel.this.mimeTypeComboBox.setSelectedIndex(0); + } + if (fileSizeCondition != null) { + InterestingItemDefsPanel.this.fileSizeUnitComboBox.setSelectedItem(fileSizeCondition.getUnit().getName()); + InterestingItemDefsPanel.this.equalitySignComboBox.setSelectedItem(fileSizeCondition.getComparator().getSymbol()); + InterestingItemDefsPanel.this.jSpinner1.setValue(fileSizeCondition.getSizeValue()); + } else { + InterestingItemDefsPanel.this.fileSizeUnitComboBox.setSelectedIndex(1); + InterestingItemDefsPanel.this.equalitySignComboBox.setSelectedIndex(2); + InterestingItemDefsPanel.this.jSpinner1.setValue(0); + } // Enable the new, edit and delete rule buttons. InterestingItemDefsPanel.this.newRuleButton.setEnabled(true);