Autopsy  4.15.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
InterestingItemsFilesSetSettings.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2018 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.modules.interestingitems;
20 
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.Serializable;
26 import java.nio.file.Path;
27 import java.nio.file.Paths;
28 import java.util.Arrays;
29 import java.util.Collection;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.logging.Level;
34 import java.util.regex.Pattern;
35 import java.util.regex.PatternSyntaxException;
36 import javax.xml.parsers.DocumentBuilder;
37 import javax.xml.parsers.DocumentBuilderFactory;
38 import javax.xml.parsers.ParserConfigurationException;
39 import org.apache.commons.lang.StringUtils;
40 import org.openide.util.io.NbObjectInputStream;
41 import org.openide.util.io.NbObjectOutputStream;
52 import org.w3c.dom.Document;
53 import org.w3c.dom.Element;
54 import org.w3c.dom.NodeList;
55 import java.util.Comparator;
56 import java.util.function.Function;
57 import java.util.stream.Collectors;
58 
59 class InterestingItemsFilesSetSettings implements Serializable {
60 
61  private static final long serialVersionUID = 1L;
62  // The following tags and attributes are identical to those used in the
63  // TSK Framework FilesSet definitions file schema.
64  private static final String FILE_SETS_ROOT_TAG = "INTERESTING_FILE_SETS"; //NON-NLS
65  private static final String DESC_ATTR = "description"; //NON-NLS
66  private static final String IGNORE_KNOWN_FILES_ATTR = "ignoreKnown"; //NON-NLS
67  private static final String PATH_REGEX_ATTR = "pathRegex"; //NON-NLS
68  private static final String TYPE_FILTER_VALUE_ALL = "all";
69  private static final String TYPE_FILTER_VALUE_FILES_AND_DIRS = "files_and_dirs"; //NON-NLS
70  private static final String IGNORE_UNALLOCATED_SPACE = "ingoreUnallocated"; //NON-NLS
71  private static final String PATH_FILTER_ATTR = "pathFilter"; //NON-NLS
72  private static final String TYPE_FILTER_VALUE_DIRS = "dir"; //NON-NLS
73  private static final String REGEX_ATTR = "regex"; //NON-NLS
74  private static final List<String> illegalFileNameChars = FilesSetsManager.getIllegalFileNameChars();
75  private static final String FILE_SET_TAG = "INTERESTING_FILE_SET"; //NON-NLS
76  private static final String NAME_RULE_TAG = "NAME"; //NON-NLS
77  private static final String NAME_ATTR = "name"; //NON-NLS
78  private static final String DAYS_INCLUDED_ATTR = "daysIncluded";
79  private static final String MIME_ATTR = "mimeType";
80  private static final String FS_COMPARATOR_ATTR = "comparatorSymbol";
81  private static final String FS_SIZE_ATTR = "sizeValue";
82  private static final String FS_UNITS_ATTR = "sizeUnits";
83  private static final String TYPE_FILTER_VALUE_FILES = "file"; //NON-NLS
84  private static final String XML_ENCODING = "UTF-8"; //NON-NLS
85  private static final Logger logger = Logger.getLogger(InterestingItemsFilesSetSettings.class.getName());
86  private static final String TYPE_FILTER_ATTR = "typeFilter"; //NON-NLS
87  private static final String EXTENSION_RULE_TAG = "EXTENSION"; //NON-NLS
88  private static final String STANDARD_SET = "standardSet";
89  private static final String VERSION_NUMBER = "versionNumber";
90 
91  private Map<String, FilesSet> filesSets;
92 
93  InterestingItemsFilesSetSettings(Map<String, FilesSet> filesSets) {
94  this.filesSets = filesSets;
95  }
96 
100  Map<String, FilesSet> getFilesSets() {
101  return filesSets;
102  }
103 
111  private static String readRuleName(Element elem) {
112  // The rule must have a name.
113  String ruleName = elem.getAttribute(NAME_ATTR);
114  return ruleName;
115  }
116 
125  private static Map<String, FilesSet> readSerializedDefinitions(String serialFileName) throws FilesSetsManager.FilesSetsManagerException {
126  Path filePath = Paths.get(PlatformUtil.getUserConfigDirectory(), serialFileName);
127  File fileSetFile = filePath.toFile();
128  String filePathStr = filePath.toString();
129  if (fileSetFile.exists()) {
130  try {
131  try (final NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(filePathStr))) {
132  InterestingItemsFilesSetSettings filesSetsSettings = (InterestingItemsFilesSetSettings) in.readObject();
133  return filesSetsSettings.getFilesSets();
134  }
135  } catch (IOException | ClassNotFoundException ex) {
136  throw new FilesSetsManager.FilesSetsManagerException(String.format("Failed to read settings from %s", filePathStr), ex);
137  }
138  } else {
139  return new HashMap<>();
140  }
141  }
142 
154  private static ParentPathCondition readPathCondition(Element ruleElement) throws FilesSetsManager.FilesSetsManagerException {
155  // Read in the optional path condition. Null is o.k., but if the attribute
156  // is there, be sure it is not malformed.
157  ParentPathCondition pathCondition = null;
158  if (!ruleElement.getAttribute(PATH_FILTER_ATTR).isEmpty() || !ruleElement.getAttribute(PATH_REGEX_ATTR).isEmpty()) {
159  String path = ruleElement.getAttribute(PATH_FILTER_ATTR);
160  String pathRegex = ruleElement.getAttribute(PATH_REGEX_ATTR);
161  if (!pathRegex.isEmpty() && path.isEmpty()) {
162  try {
163  Pattern pattern = Pattern.compile(pathRegex);
164  pathCondition = new ParentPathCondition(pattern);
165  } catch (PatternSyntaxException ex) {
166  logger.log(Level.SEVERE, "Error compiling " + PATH_REGEX_ATTR + " regex, ignoring malformed path condition definition", ex); // NON-NLS
167  throw new FilesSetsManager.FilesSetsManagerException(String.format("error compiling %s regex", PATH_REGEX_ATTR), ex);
168  }
169  } else if (!path.isEmpty() && pathRegex.isEmpty()) {
170  pathCondition = new ParentPathCondition(path);
171  }
172  if (pathCondition == null) {
173  // Malformed attribute.
174  throw new FilesSetsManager.FilesSetsManagerException(String.format("Error creating path condition for rule %s", readRuleName(ruleElement)));
175  }
176  }
177  return pathCondition;
178  }
179 
191  private static DateCondition readDateCondition(Element ruleElement) throws FilesSetsManager.FilesSetsManagerException {
192  // Read in the optional path condition. Null is o.k., but if the attribute
193  // is there, be sure it is not malformed.
194  DateCondition dateCondition = null;
195  if (!ruleElement.getAttribute(DAYS_INCLUDED_ATTR).isEmpty()) {
196  String daysIncluded = ruleElement.getAttribute(DAYS_INCLUDED_ATTR);
197  if (!daysIncluded.isEmpty()) {
198  try {
199  dateCondition = new DateCondition(Integer.parseInt(daysIncluded));
200  } catch (NumberFormatException ex) {
201  logger.log(Level.SEVERE, "Error creating condition for " + daysIncluded + ", ignoring malformed date condition definition", ex); // NON-NLS
202  throw new FilesSetsManager.FilesSetsManagerException(String.format("error compiling %s regex", DAYS_INCLUDED_ATTR), ex);
203  }
204  }
205  }
206  return dateCondition;
207  }
208 
216  private static Pattern compileRegex(String regex) {
217  try {
218  return Pattern.compile(regex);
219  } catch (PatternSyntaxException ex) {
220  logger.log(Level.SEVERE, "Error compiling rule regex: " + ex.getMessage(), ex); // NON-NLS
221  return null;
222  }
223  }
224 
237  private static FilesSet.Rule readRule(Element elem) throws FilesSetsManager.FilesSetsManagerException {
238  String ruleName = readRuleName(elem);
239  FileNameCondition nameCondition = readNameCondition(elem);
240  MetaTypeCondition metaCondition = readMetaTypeCondition(elem);
241  ParentPathCondition pathCondition = readPathCondition(elem);
242  MimeTypeCondition mimeCondition = readMimeCondition(elem);
243  FileSizeCondition sizeCondition = readSizeCondition(elem);
244  DateCondition dateCondition = readDateCondition(elem); //if meta type condition or all four types of conditions the user can create are all null then don't make the rule
245  if (metaCondition == null || (nameCondition == null && pathCondition == null && mimeCondition == null && sizeCondition == null && dateCondition == null)) {
246  logger.log(Level.WARNING, "Error Reading Rule, " + ruleName + " was either missing a meta condition or contained only a meta condition. No rule was imported."); // NON-NLS
247  throw new FilesSetsManager.FilesSetsManagerException(String.format("Invalid Rule in FilesSet xml, missing necessary conditions for %s", ruleName));
248  }
249  return new FilesSet.Rule(ruleName, nameCondition, metaCondition, pathCondition, mimeCondition, sizeCondition, dateCondition);
250  }
251 
263  private static FileNameCondition readNameCondition(Element elem) throws FilesSetsManager.FilesSetsManagerException {
264  FileNameCondition nameCondition = null;
265  String content = elem.getTextContent();
266  String regex = elem.getAttribute(REGEX_ATTR);
267  if (content != null && !content.isEmpty()) { //if there isn't content this is not a valid name condition
268  if ((!regex.isEmpty() && regex.equalsIgnoreCase("true")) || content.contains("*")) { // NON-NLS
269  Pattern pattern = compileRegex(content);
270  if (pattern != null) {
271  if (elem.getTagName().equals(NAME_RULE_TAG)) {
272  nameCondition = new FilesSet.Rule.FullNameCondition(pattern);
273  } else if (elem.getTagName().equals(EXTENSION_RULE_TAG)) {
274  nameCondition = new FilesSet.Rule.ExtensionCondition(pattern);
275  } else {
276  throw new FilesSetsManager.FilesSetsManagerException(String.format("Name condition has invalid tag name of %s for rule %s", elem.getTagName(), readRuleName(elem)));
277  }
278  } else {
279  logger.log(Level.SEVERE, "Error compiling " + elem.getTagName() + " regex, ignoring malformed '{0}' rule definition", readRuleName(elem)); // NON-NLS
280  throw new FilesSetsManager.FilesSetsManagerException(String.format("error compiling %s regex in rule %s", REGEX_ATTR, readRuleName(elem)));
281  }
282  } else {
283  for (String illegalChar : illegalFileNameChars) {
284  if (content.contains(illegalChar)) {
285  logger.log(Level.SEVERE, elem.getTagName() + " content has illegal chars, ignoring malformed '{0}' rule definition", new Object[]{elem.getTagName(), readRuleName(elem)}); // NON-NLS
286  throw new FilesSetsManager.FilesSetsManagerException(String.format("File name has illegal character of %s in rule %s", illegalChar, readRuleName(elem)));
287  }
288  }
289  if (elem.getTagName().equals(NAME_RULE_TAG)) {
290  nameCondition = new FilesSet.Rule.FullNameCondition(content);
291  } else if (elem.getTagName().equals(EXTENSION_RULE_TAG)) {
292  nameCondition = new FilesSet.Rule.ExtensionCondition(Arrays.asList(content.split(",")));
293  }
294  }
295  }
296  return nameCondition;
297  }
298 
307  private static MimeTypeCondition readMimeCondition(Element elem) {
308  MimeTypeCondition mimeCondition = null;
309  if (!elem.getAttribute(MIME_ATTR).isEmpty()) {
310  mimeCondition = new MimeTypeCondition(elem.getAttribute(MIME_ATTR));
311  //no checks on mime type here which means
312  //if they import a rule with a custom MIME type they don't have
313  //the rule will not get any hits
314  }
315  return mimeCondition;
316  }
317 
329  private static FileSizeCondition readSizeCondition(Element elem) throws FilesSetsManager.FilesSetsManagerException {
330  FileSizeCondition sizeCondition = null;
331  if (!elem.getAttribute(FS_COMPARATOR_ATTR).isEmpty() && !elem.getAttribute(FS_SIZE_ATTR).isEmpty() && !elem.getAttribute(FS_UNITS_ATTR).isEmpty()) {
332  try { //incase they modified the xml manually to invalid comparator, size unit, or non integer string for size
333  FileSizeCondition.COMPARATOR comparator = FileSizeCondition.COMPARATOR.fromSymbol(elem.getAttribute(FS_COMPARATOR_ATTR));
334  FileSizeCondition.SIZE_UNIT sizeUnit = FileSizeCondition.SIZE_UNIT.fromName(elem.getAttribute(FS_UNITS_ATTR));
335  int size = Integer.parseInt(elem.getAttribute(FS_SIZE_ATTR));
336  sizeCondition = new FileSizeCondition(comparator, sizeUnit, size);
337  } catch (NumberFormatException nfEx) {
338  logger.log(Level.SEVERE, "Value in file size attribute was not an integer, unable to create FileSizeCondition for rule: " + readRuleName(elem), nfEx);
339  throw new FilesSetsManager.FilesSetsManagerException(String.format("Non integer size in FilesSet XML for rule %s", readRuleName(elem)), nfEx);
340  } catch (IllegalArgumentException iaEx) {
341  logger.log(Level.SEVERE, "Invalid Comparator symbol or Size Unit set in FilesSet xml, unable to create FileSizeCondition for rule: " + readRuleName(elem), iaEx);
342  throw new FilesSetsManager.FilesSetsManagerException(String.format("Invalid Comparator or Size unit in FilesSet XML for rule %s", readRuleName(elem)), iaEx);
343  }
344  } //if all of them aren't populated but some of them are this is a malformed xml
345  else if (!elem.getAttribute(FS_COMPARATOR_ATTR).isEmpty() || !elem.getAttribute(FS_SIZE_ATTR).isEmpty() || !elem.getAttribute(FS_UNITS_ATTR).isEmpty()) {
346  logger.log(Level.SEVERE, "Invalid Comparator symbol or Size Unit set in FilesSet xml, unable to create FileSizeCondition for rule: " + readRuleName(elem));
347  throw new FilesSetsManager.FilesSetsManagerException(String.format("XML malformed missing at least one fileSize attribute for rule %s", readRuleName(elem)));
348  }
349  return sizeCondition;
350  }
351 
362  private static void readFilesSet(Element setElem, Map<String, FilesSet> filesSets, String filePath) throws FilesSetsManager.FilesSetsManagerException {
363  // The file set must have a unique name.
364  String setName = setElem.getAttribute(NAME_ATTR);
365  if (setName.isEmpty()) {
366  logger.log(Level.SEVERE, "Found {0} element without required {1} attribute, ignoring malformed file set definition in FilesSet definition file at {2}", new Object[]{FILE_SET_TAG, NAME_ATTR, filePath}); // NON-NLS
367  return;
368  }
369  if (filesSets.containsKey(setName)) {
370  logger.log(Level.SEVERE, "Found duplicate definition of set named {0} in FilesSet definition file at {1}, discarding duplicate set", new Object[]{setName, filePath}); // NON-NLS
371  return;
372  }
373  // The file set may have a description. The empty string is o.k.
374  String description = setElem.getAttribute(DESC_ATTR);
375  // The file set may or may not ignore known files. The default behavior
376  // is to not ignore them.
377  String ignoreKnown = setElem.getAttribute(IGNORE_KNOWN_FILES_ATTR);
378  boolean ignoreKnownFiles = false;
379  if (!ignoreKnown.isEmpty()) {
380  ignoreKnownFiles = Boolean.parseBoolean(ignoreKnown);
381  }
382  // The file set may or may not skip unallocated space. The default behavior
383  // is not to skip it.
384  String ignoreUnallocated = setElem.getAttribute(IGNORE_UNALLOCATED_SPACE);
385  boolean ignoreUnallocatedSpace = false;
386  if (!ignoreUnallocated.isEmpty()) {
387  ignoreUnallocatedSpace = Boolean.parseBoolean(ignoreUnallocated);
388  }
389 
390  String isStandardSetString = setElem.getAttribute(STANDARD_SET);
391  boolean isStandardSet = false;
392  if (StringUtils.isNotBlank(isStandardSetString)) {
393  isStandardSet = Boolean.parseBoolean(isStandardSetString);
394  }
395 
396  String versionNumberString = setElem.getAttribute(VERSION_NUMBER);
397  int versionNumber = 0;
398  if (StringUtils.isNotBlank(versionNumberString)) {
399  try {
400  versionNumber = Integer.parseInt(versionNumberString);
401  } catch (NumberFormatException ex) {
402  logger.log(Level.WARNING,
403  String.format("Unable to parse version number for files set named: %s with provided input: '%s'", setName, versionNumberString),
404  ex);
405  }
406  }
407 
408  // Read the set membership rules, if any.
409  Map<String, FilesSet.Rule> rules = new HashMap<>();
410  NodeList allRuleElems = setElem.getChildNodes();
411  for (int j = 0; j < allRuleElems.getLength(); ++j) {
412  if (allRuleElems.item(j) instanceof Element) { //All the children we need to parse here are elements
413  Element elem = (Element) allRuleElems.item(j);
414  FilesSet.Rule rule = readRule(elem);
415  if (rule != null) {
416  if (!rules.containsKey(rule.getUuid())) {
417  rules.put(rule.getUuid(), rule);
418  } else {
419  logger.log(Level.SEVERE, "Found duplicate rule {0} for set named {1} in FilesSet definition file at {2}, discarding malformed set", new Object[]{rule.getUuid(), setName, filePath}); // NON-NLS
420  return;
421  }
422  } else {
423  logger.log(Level.SEVERE, "Found malformed rule for set named {0} in FilesSet definition file at {1}, discarding malformed set", new Object[]{setName, filePath}); // NON-NLS
424  return;
425  }
426  }
427  }
428  // Make the files set. Note that degenerate sets with no rules are
429  // allowed to facilitate the separation of set definition and rule
430  // definitions. A set without rules is simply the empty set.
431  FilesSet set = new FilesSet(setName, description, ignoreKnownFiles, ignoreUnallocatedSpace, rules, isStandardSet, versionNumber);
432  filesSets.put(set.getName(), set);
433  }
434  // Note: This method takes a file path to support the possibility of
435  // multiple intersting files set definition files, e.g., one for
436  // definitions that ship with Autopsy and one for user definitions.
437 
450  static Map<String, FilesSet> readDefinitionsFile(String fileName, String legacyFileName) throws FilesSetsManager.FilesSetsManagerException {
451  Map<String, FilesSet> filesSets = readSerializedDefinitions(fileName);
452  if (!filesSets.isEmpty()) {
453  return filesSets;
454  }
455  // Check if the legacy xml file exists.
456  if (!legacyFileName.isEmpty()) {
457  return readDefinitionsXML(Paths.get(PlatformUtil.getUserConfigDirectory(), legacyFileName).toFile());
458  }
459  return filesSets;
460  }
461 
475  static Map<String, FilesSet> readDefinitionsXML(File xmlFile) throws FilesSetsManager.FilesSetsManagerException {
476  if (!xmlFile.exists()) {
477  return new HashMap<>();
478  }
479  // Check if the file can be read.
480  if (!xmlFile.canRead()) {
481  logger.log(Level.SEVERE, "FilesSet definition file at {0} exists, but cannot be read", xmlFile.getPath()); // NON-NLS
482  return new HashMap<>();
483  }
484 
485  Document doc = XMLUtil.loadDoc(InterestingItemsFilesSetSettings.class, xmlFile.getPath());
486  return readDefinitionsXML(doc, xmlFile.getPath());
487  }
488 
502  static Map<String, FilesSet> readDefinitionsXML(Document doc, String resourceName) throws FilesSetsManager.FilesSetsManagerException {
503  // Parse the XML in the file.
504  Map<String, FilesSet> filesSets = new HashMap<>();
505 
506  if (doc == null) {
507  logger.log(Level.SEVERE, "FilesSet definition file at {0}", resourceName); // NON-NLS
508  return filesSets;
509  }
510  // Get the root element.
511  Element root = doc.getDocumentElement();
512  if (root == null) {
513  logger.log(Level.SEVERE, "Failed to get root {0} element tag of FilesSet definition file at {1}",
514  new Object[]{FILE_SETS_ROOT_TAG, resourceName}); // NON-NLS
515  return filesSets;
516  }
517  // Read in the files set definitions.
518  NodeList setElems = root.getElementsByTagName(FILE_SET_TAG);
519  for (int i = 0; i < setElems.getLength(); ++i) {
520  readFilesSet((Element) setElems.item(i), filesSets, resourceName);
521  }
522  return filesSets;
523  }
524 
525  // Note: This method takes a file path to support the possibility of
526  // multiple intersting files set definition files, e.g., one for
527  // definitions that ship with Autopsy and one for user definitions.
535  static boolean writeDefinitionsFile(String fileName, Map<String, FilesSet> interestingFilesSets) throws FilesSetsManager.FilesSetsManagerException {
536  try (final NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(Paths.get(PlatformUtil.getUserConfigDirectory(), fileName).toString()))) {
537  out.writeObject(new InterestingItemsFilesSetSettings(interestingFilesSets));
538  } catch (IOException ex) {
539  throw new FilesSetsManager.FilesSetsManagerException(String.format("Failed to write settings to %s", fileName), ex);
540  }
541  return true;
542  }
543 
544 
551  private static <T> List<T> sortOnField(Collection<T> itemsToSort, final Function<T, String> getName) {
552  Comparator<T> comparator = (a,b) -> {
553  String aName = getName.apply(a);
554  String bName = getName.apply(b);
555  if (aName == null) {
556  aName = "";
557  }
558 
559  if (bName == null) {
560  bName = "";
561  }
562 
563  return aName.compareToIgnoreCase(bName);
564  };
565 
566  return itemsToSort.stream()
567  .sorted(comparator)
568  .collect(Collectors.toList());
569  }
570 
571 
581  static boolean exportXmlDefinitionsFile(File xmlFile, List<FilesSet> interestingFilesSets) {
582  DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
583  try {
584  // Create the new XML document.
585  DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
586  Document doc = docBuilder.newDocument();
587  Element rootElement = doc.createElement(FILE_SETS_ROOT_TAG);
588  doc.appendChild(rootElement);
589  // Add the interesting files sets to the document.
590 
591  List<FilesSet> sortedFilesSets = sortOnField(
592  interestingFilesSets,
593  filesSet -> filesSet == null ? null : filesSet.getName());
594 
595  for (FilesSet set : sortedFilesSets) {
596  // Add the files set element and its attributes.
597  Element setElement = doc.createElement(FILE_SET_TAG);
598  setElement.setAttribute(NAME_ATTR, set.getName());
599  setElement.setAttribute(DESC_ATTR, set.getDescription());
600  setElement.setAttribute(IGNORE_KNOWN_FILES_ATTR, Boolean.toString(set.ignoresKnownFiles()));
601  setElement.setAttribute(STANDARD_SET, Boolean.toString(set.isStandardSet()));
602  setElement.setAttribute(VERSION_NUMBER, Integer.toString(set.getVersionNumber()));
603  // Add the child elements for the set membership rules.
604  // All conditions of a rule will be written as a single element in the xml
605 
606  List<FilesSet.Rule> sortedRules = sortOnField(
607  set.getRules().values(),
608  rule -> rule == null ? null : rule.getName());
609 
610  for (FilesSet.Rule rule : sortedRules) {
611  // Add a rule element with the appropriate name Condition
612  // type tag.
613  Element ruleElement;
614 
615  FileNameCondition nameCondition = rule.getFileNameCondition();
616  //The element type is just being used as another attribute for
617  //the name condition in legacy xmls.
618  //For rules which don't contain a name condition it doesn't matter
619  //what type of element it is
620  if (nameCondition instanceof FilesSet.Rule.FullNameCondition) {
621  ruleElement = doc.createElement(NAME_RULE_TAG);
622  } else {
623  ruleElement = doc.createElement(EXTENSION_RULE_TAG);
624  }
625  // Add the optional rule name attribute.
626  ruleElement.setAttribute(NAME_ATTR, rule.getName());
627  if (nameCondition != null) {
628  // Add the name Condition regex attribute
629  ruleElement.setAttribute(REGEX_ATTR, Boolean.toString(nameCondition.isRegex()));
630  // Add the name Condition text as the rule element content.
631  ruleElement.setTextContent(nameCondition.getTextToMatch());
632  }
633  // Add the type Condition attribute.
634  MetaTypeCondition typeCondition = rule.getMetaTypeCondition();
635  switch (typeCondition.getMetaType()) {
636  case FILES:
637  ruleElement.setAttribute(TYPE_FILTER_ATTR, TYPE_FILTER_VALUE_FILES);
638  break;
639  case DIRECTORIES:
640  ruleElement.setAttribute(TYPE_FILTER_ATTR, TYPE_FILTER_VALUE_DIRS);
641  break;
642  default:
643  ruleElement.setAttribute(TYPE_FILTER_ATTR, TYPE_FILTER_VALUE_ALL);
644  break;
645  }
646  // Add the optional path Condition.
647  ParentPathCondition pathCondition = rule.getPathCondition();
648  if (pathCondition != null) {
649  if (pathCondition.isRegex()) {
650  ruleElement.setAttribute(PATH_REGEX_ATTR, pathCondition.getTextToMatch());
651  } else {
652  ruleElement.setAttribute(PATH_FILTER_ATTR, pathCondition.getTextToMatch());
653  }
654  }
655  //Add the optional MIME type condition
656  MimeTypeCondition mimeCondition = rule.getMimeTypeCondition();
657  if (mimeCondition != null) {
658  ruleElement.setAttribute(MIME_ATTR, mimeCondition.getMimeType());
659  }
660  //Add the optional file size condition
661  FileSizeCondition sizeCondition = rule.getFileSizeCondition();
662  if (sizeCondition != null) {
663  ruleElement.setAttribute(FS_COMPARATOR_ATTR, sizeCondition.getComparator().getSymbol());
664  ruleElement.setAttribute(FS_SIZE_ATTR, Integer.toString(sizeCondition.getSizeValue()));
665  ruleElement.setAttribute(FS_UNITS_ATTR, sizeCondition.getUnit().getName());
666  }
667 
668  //Add the optional date condition
669  DateCondition dateCondition = rule.getDateCondition();
670  if (dateCondition != null) {
671  ruleElement.setAttribute(DAYS_INCLUDED_ATTR, Integer.toString(dateCondition.getDaysIncluded()));
672  }
673 
674  setElement.appendChild(ruleElement);
675  }
676  rootElement.appendChild(setElement);
677  }
678  // Overwrite the previous definitions file. Note that the utility
679  // method logs an error on failure.
680  return XMLUtil.saveDoc(InterestingItemsFilesSetSettings.class, xmlFile.getPath(), XML_ENCODING, doc);
681  } catch (ParserConfigurationException ex) {
682  logger.log(Level.SEVERE, "Error writing interesting files definition file to " + xmlFile.getPath(), ex); // NON-NLS
683  return false;
684  }
685  }
686 
698  private static MetaTypeCondition readMetaTypeCondition(Element ruleElement) throws FilesSetsManager.FilesSetsManagerException {
699  MetaTypeCondition metaCondition = null;
700  // The rule must have a meta-type condition, unless a TSK Framework
701  // definitions file is being read.
702  if (!ruleElement.getAttribute(TYPE_FILTER_ATTR).isEmpty()) {
703  String conditionAttribute = ruleElement.getAttribute(TYPE_FILTER_ATTR);
704  if (!conditionAttribute.isEmpty()) {
705  switch (conditionAttribute) {
706  case TYPE_FILTER_VALUE_FILES:
707  metaCondition = new MetaTypeCondition(MetaTypeCondition.Type.FILES);
708  break;
709  case TYPE_FILTER_VALUE_DIRS:
710  metaCondition = new MetaTypeCondition(MetaTypeCondition.Type.DIRECTORIES);
711  break;
712  case TYPE_FILTER_VALUE_ALL:
713  case TYPE_FILTER_VALUE_FILES_AND_DIRS: //converts legacy xmls to current metaCondition terms
714  metaCondition = new MetaTypeCondition(MetaTypeCondition.Type.ALL);
715  break;
716  default:
717  logger.log(Level.SEVERE, "Found {0} " + TYPE_FILTER_ATTR + " attribute with unrecognized value ''{0}'', ignoring malformed rule definition", conditionAttribute); // NON-NLS
718  // Malformed attribute.
719  throw new FilesSetsManager.FilesSetsManagerException(String.format("Malformed XML for Metatype condition, %s, in rule %s", conditionAttribute, readRuleName(ruleElement)));
720  }
721  }
722  }
723  if (metaCondition == null) {
724  // Accept TSK Framework FilesSet definitions,
725  // default to files.
726  metaCondition = new MetaTypeCondition(MetaTypeCondition.Type.FILES);
727  }
728  return metaCondition;
729  }
730 }

Copyright © 2012-2020 Basis Technology. Generated on: Mon Jul 6 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.