Finished condition adding.

This commit is contained in:
Oliver Spohngellert
2016-02-22 15:43:09 -05:00
parent f824131d65
commit 0fba2152da
5 changed files with 279 additions and 168 deletions
@@ -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<E>.
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;
/**
@@ -351,6 +351,9 @@
<ResourceString bundle="org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties" key="FilesSetRulePanel.filesRadio.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="filesRadioActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="dirsRadio">
<Properties>
@@ -361,6 +364,9 @@
<ResourceString bundle="org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties" key="FilesSetRulePanel.dirsRadio.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="dirsRadioActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="filesAndDirsRadio">
<Properties>
@@ -371,6 +377,9 @@
<ResourceString bundle="org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties" key="FilesSetRulePanel.filesAndDirsRadio.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="filesAndDirsRadioActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>
@@ -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<MediaType> 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;
@@ -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<String> ILLEGAL_FILE_NAME_CHARS = Collections.unmodifiableList(new ArrayList<>(Arrays.asList("\\", "/", ":", "*", "?", "\"", "<", ">")));
private static final List<String> 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<String, FilesSet> 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<String, FilesSet> 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<String, FilesSet> readSerializedDefinitions() {
String filePath = INTERESING_FILES_SET_DEFS_SERIALIZATION_PATH;
try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(filePath.toString()))) {
Map<String, FilesSet> filesSetMap = (Map<String, FilesSet>) 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<String, FilesSet> 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<String, FilesSet> 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);
}
}
}
}
@@ -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);