19 package org.sleuthkit.autopsy.modules.interestingitems;
21 import java.io.Serializable;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.List;
26 import java.util.UUID;
27 import java.util.regex.Pattern;
39 final class FilesSet
implements Serializable {
41 private static final long serialVersionUID = 1L;
42 private final String name;
43 private final String description;
44 private final boolean ignoreKnownFiles;
45 private final Map<String, Rule> rules =
new HashMap<>();
57 FilesSet(String name, String description,
boolean ignoreKnownFiles, Map<String, Rule> rules) {
58 if ((name == null) || (name.isEmpty())) {
59 throw new IllegalArgumentException(
"Interesting files set name cannot be null or empty");
62 this.description = (description != null ? description :
"");
63 this.ignoreKnownFiles = ignoreKnownFiles;
65 this.rules.putAll(rules);
83 String getDescription() {
84 return this.description;
96 boolean ignoresKnownFiles() {
97 return this.ignoreKnownFiles;
105 Map<String, Rule> getRules() {
106 return new HashMap<>(this.rules);
117 String fileIsMemberOf(AbstractFile file) {
118 if ((this.ignoreKnownFiles) && (file.getKnown() == TskData.FileKnown.KNOWN)) {
121 for (Rule rule : rules.values()) {
122 if (rule.isSatisfied(file)) {
123 return rule.getName();
130 public String toString() {
140 static class Rule
implements Serializable {
142 private static final long serialVersionUID = 1L;
143 private final String uuid;
144 private final String ruleName;
145 private final FileNameCondition fileNameCondition;
146 private final MetaTypeCondition metaTypeCondition;
147 private final ParentPathCondition pathCondition;
148 private final MimeTypeCondition mimeTypeCondition;
149 private final FileSizeCondition fileSizeCondition;
150 private final List<FileAttributeCondition> conditions =
new ArrayList<>();
162 Rule(String ruleName, FileNameCondition fileNameCondition, MetaTypeCondition metaTypeCondition, ParentPathCondition pathCondition, MimeTypeCondition mimeTypeCondition, FileSizeCondition fileSizeCondition) {
164 this.uuid = UUID.randomUUID().toString();
165 if (metaTypeCondition == null) {
166 throw new IllegalArgumentException(
"Interesting files set rule meta-type condition cannot be null");
168 if (pathCondition == null && fileNameCondition == null && mimeTypeCondition == null && fileSizeCondition == null) {
169 throw new IllegalArgumentException(
"Must have at least one condition on rule.");
172 this.ruleName = ruleName;
178 this.metaTypeCondition = metaTypeCondition;
179 this.conditions.add(this.metaTypeCondition);
181 this.fileSizeCondition = fileSizeCondition;
182 if (this.fileSizeCondition != null) {
183 this.conditions.add(this.fileSizeCondition);
186 this.fileNameCondition = fileNameCondition;
187 if (this.fileNameCondition != null) {
188 this.conditions.add(fileNameCondition);
191 this.mimeTypeCondition = mimeTypeCondition;
192 if (this.mimeTypeCondition != null) {
193 this.conditions.add(mimeTypeCondition);
196 this.pathCondition = pathCondition;
197 if (this.pathCondition != null) {
198 this.conditions.add(this.pathCondition);
216 FileNameCondition getFileNameCondition() {
217 return this.fileNameCondition;
225 MetaTypeCondition getMetaTypeCondition() {
226 return this.metaTypeCondition;
234 ParentPathCondition getPathCondition() {
235 return this.pathCondition;
245 boolean isSatisfied(AbstractFile file) {
246 for (FileAttributeCondition condition : conditions) {
247 if (!condition.passes(file)) {
258 public String toString() {
261 if (fileNameCondition != null) {
262 return this.ruleName +
" (" + fileNameCondition.getTextToMatch() +
")";
263 }
else if (this.pathCondition != null) {
264 return this.ruleName +
" (" + pathCondition.getTextToMatch() +
")";
265 }
else if (this.mimeTypeCondition != null) {
266 return this.ruleName +
" (" + mimeTypeCondition.getMimeType() +
")";
267 }
else if (this.fileSizeCondition != null) {
268 return this.ruleName +
" (" + fileSizeCondition.getComparator().getSymbol() +
" " + fileSizeCondition.getSizeValue()
269 +
" " + fileSizeCondition.getUnit().getName() +
")";
271 return this.ruleName +
" ()";
279 public String getUuid() {
286 MimeTypeCondition getMimeTypeCondition() {
287 return mimeTypeCondition;
293 FileSizeCondition getFileSizeCondition() {
294 return fileSizeCondition;
301 static interface FileAttributeCondition
extends Serializable {
310 boolean passes(AbstractFile file);
316 static final class MimeTypeCondition
implements FileAttributeCondition {
318 private static final long serialVersionUID = 1L;
319 private final String mimeType;
326 MimeTypeCondition(String mimeType) {
327 this.mimeType = mimeType;
334 public boolean passes(AbstractFile file) {
335 return this.mimeType.equals(file.getMIMEType());
343 String getMimeType() {
344 return this.mimeType;
353 static final class FileSizeCondition
implements FileAttributeCondition {
355 private static final long serialVersionUID = 1L;
360 static enum COMPARATOR {
363 LESS_THAN_EQUAL(
"≤"),
366 GREATER_THAN_EQUAL(
"≥");
368 private String symbol;
370 COMPARATOR(String symbol) {
371 this.symbol = symbol;
374 public static COMPARATOR fromSymbol(String symbol) {
375 if (symbol.equals(
"<=") || symbol.equals(
"≤")) {
376 return LESS_THAN_EQUAL;
377 }
else if (symbol.equals(
"<")) {
379 }
else if (symbol.equals(
"==") || symbol.equals(
"=")) {
381 }
else if (symbol.equals(
">")) {
383 }
else if (symbol.equals(
">=") || symbol.equals(
"≥")) {
384 return GREATER_THAN_EQUAL;
386 throw new IllegalArgumentException(
"Invalid symbol");
393 public String getSymbol() {
401 static enum SIZE_UNIT {
404 KILOBYTE(1024,
"Kilobytes"),
405 MEGABYTE(1024 * 1024,
"Megabytes"),
406 GIGABYTE(1024 * 1024 * 1024,
"Gigabytes");
410 private SIZE_UNIT(
long size, String name) {
415 public long getSize() {
419 public static SIZE_UNIT fromName(String name) {
420 for (SIZE_UNIT unit : SIZE_UNIT.values()) {
421 if (unit.getName().equals(name)) {
425 throw new IllegalArgumentException(
"Invalid name for size unit.");
431 public String getName() {
435 private final COMPARATOR comparator;
436 private final SIZE_UNIT unit;
437 private final int sizeValue;
439 FileSizeCondition(COMPARATOR comparator, SIZE_UNIT unit,
int sizeValue) {
440 this.comparator = comparator;
442 this.sizeValue = sizeValue;
450 COMPARATOR getComparator() {
459 SIZE_UNIT getUnit() {
473 public boolean passes(AbstractFile file) {
474 long fileSize = file.getSize();
475 long conditionSize = this.getUnit().getSize() * this.getSizeValue();
476 switch (this.getComparator()) {
478 return fileSize > conditionSize;
479 case GREATER_THAN_EQUAL:
480 return fileSize >= conditionSize;
481 case LESS_THAN_EQUAL:
482 return fileSize <= conditionSize;
484 return fileSize < conditionSize;
486 return fileSize == conditionSize;
498 static final class MetaTypeCondition
implements FileAttributeCondition {
500 private static final long serialVersionUID = 1L;
506 FILES_AND_DIRECTORIES
509 private final Type type;
516 MetaTypeCondition(Type type) {
524 public boolean passes(AbstractFile file) {
527 return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG;
529 return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR;
531 return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG
532 || file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR;
549 static interface TextCondition
extends FileAttributeCondition {
556 String getTextToMatch();
574 boolean textMatches(String textToMatch);
593 this.textMatcher =
new FilesSet.Rule.CaseInsensitivePartialStringComparisionMatcher(text);
595 this.textMatcher =
new FilesSet.Rule.CaseInsensitiveStringComparisionMatcher(text);
605 this.textMatcher =
new FilesSet.Rule.RegexMatcher(regex);
627 return this.textMatcher.
isRegex();
646 public abstract boolean passes(AbstractFile file);
655 static final class ParentPathCondition
extends AbstractTextCondition {
657 private static final long serialVersionUID = 1L;
664 ParentPathCondition(String path) {
673 ParentPathCondition(Pattern path) {
681 public boolean passes(AbstractFile file) {
682 return this.textMatches(file.getParentPath() +
"/");
692 static interface FileNameCondition
extends TextCondition {
700 static final class FullNameCondition
extends AbstractTextCondition implements FileNameCondition {
702 private static final long serialVersionUID = 1L;
709 FullNameCondition(String name) {
718 FullNameCondition(Pattern name) {
726 public boolean passes(AbstractFile file) {
737 static final class ExtensionCondition
extends AbstractTextCondition implements FileNameCondition {
739 private static final long serialVersionUID = 1L;
746 ExtensionCondition(String extension) {
750 super(extension.startsWith(
".") ? extension.substring(1) : extension,
false);
759 ExtensionCondition(Pattern extension) {
760 super(extension.pattern(),
false);
767 public boolean passes(AbstractFile file) {
811 private static final long serialVersionUID = 1L;
845 return subject.equalsIgnoreCase(textToMatch);
855 private static final long serialVersionUID = 1L;
867 this.pattern = Pattern.compile(Pattern.quote(textToMatch), Pattern.CASE_INSENSITIVE);
891 return pattern.matcher(subject).find();
900 private static final long serialVersionUID = 1L;
918 return this.regex.pattern();
935 return this.regex.matcher(subject).find();
boolean textMatches(String textToMatch)
abstract boolean passes(AbstractFile file)
boolean textMatches(String subject)
boolean textMatches(String subject)
final TextMatcher textMatcher
boolean textMatches(String subject)
boolean textMatches(String subject)