Autopsy  4.22.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
TagSetDefinition.java
Go to the documentation of this file.
1 /*
2  * To change this license header, choose License Headers in Project Properties.
3  * To change this template file, choose Tools | Templates
4  * and open the template in the editor.
5  */
6 package org.sleuthkit.autopsy.casemodule.services;
7 
8 import com.google.gson.Gson;
9 import com.google.gson.GsonBuilder;
10 import com.google.gson.JsonArray;
11 import com.google.gson.JsonDeserializationContext;
12 import com.google.gson.JsonDeserializer;
13 import com.google.gson.JsonElement;
14 import com.google.gson.JsonObject;
15 import com.google.gson.JsonParseException;
16 import com.google.gson.JsonSyntaxException;
17 import java.lang.reflect.Type;
18 import java.io.File;
19 import java.io.FileWriter;
20 import java.io.IOException;
21 import java.nio.file.Path;
22 import java.nio.file.Paths;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.List;
26 import javax.annotation.concurrent.Immutable;
27 import java.io.FileFilter;
28 import java.io.FileReader;
29 import java.util.logging.Level;
34 
38 @Immutable
39 final public class TagSetDefinition {
40 
41  private static final Logger LOGGER = Logger.getLogger(TagSetDefinition.class.getName());
42 
43  private final static String FILE_NAME_TEMPLATE = "%s-tag-set.json";
44  private final static Path TAGS_USER_CONFIG_DIR = Paths.get(PlatformUtil.getUserConfigDirectory(), "tags");
45 
46  private final String name;
47  private final List<TagNameDefinition> tagNameDefinitionList;
48 
49  public TagSetDefinition(String name, List<TagNameDefinition> tagNameDefinitionList) {
50  if (name == null || name.isEmpty()) {
51  throw new IllegalArgumentException("Invalid parameter passed to TagSetDefinition constructor. TagSet name was null or empty.");
52  }
53 
54  if (tagNameDefinitionList == null || tagNameDefinitionList.isEmpty()) {
55  throw new IllegalArgumentException("Invalid parameter passed to TagSetDefinition constructor. TagNameDefinition list was null or empty.");
56  }
57 
58  this.name = name;
59  this.tagNameDefinitionList = tagNameDefinitionList;
60  }
61 
67  public String getName() {
68  return name;
69  }
70 
76  public List<TagNameDefinition> getTagNameDefinitions() {
77  return Collections.unmodifiableList(tagNameDefinitionList);
78  }
79 
88  static synchronized void writeTagSetDefinition(TagSetDefinition tagSetDefinition) throws IOException {
89  // Create the tags directory if it doesn't exist.
90  File dir = TAGS_USER_CONFIG_DIR.toFile();
91  if (!dir.exists()) {
92  dir.mkdirs();
93  }
94 
95  File file = Paths.get(TAGS_USER_CONFIG_DIR.toString(), tagSetDefinition.getFileName()).toFile();
96  if (file.exists()) {
97  file.delete();
98  }
99 
100  try (FileWriter writer = new FileWriter(file)) {
101  (new Gson()).toJson(tagSetDefinition, writer);
102  }
103  }
104 
111  static synchronized List<TagSetDefinition> readTagSetDefinitions() throws IOException {
112  List<TagSetDefinition> tagSetList = new ArrayList<>();
113  File dir = TAGS_USER_CONFIG_DIR.toFile();
114 
115  if (!dir.exists()) {
116  return tagSetList;
117  }
118 
119  File[] fileList = dir.listFiles(new TagSetJsonFileFilter());
120  if (fileList == null) {
121  return tagSetList;
122  }
123 
124  Gson gson = new GsonBuilder()
125  .registerTypeAdapter(TagSetDefinition.class, new TagSetDefinitionDeserializer()) // Use custom deserializer
126  .create();
127 
128  for (File file : fileList) {
129  try (FileReader reader = new FileReader(file)) {
130  TagSetDefinition tagSet = gson.fromJson(reader, TagSetDefinition.class);
131  if (tagSet != null) {
132  tagSetList.add(tagSet);
133  }
134  } catch (JsonSyntaxException e) {
135  LOGGER.log(Level.SEVERE, "Skipping invalid JSON file: " + file.getName() + " - " + e.getMessage());
136  } catch (IOException e) {
137  LOGGER.log(Level.SEVERE, "Error reading file: " + file.getName() + " - " + e.getMessage());
138  }
139  }
140 
141  return tagSetList;
142  }
143 
149  private String getFileName() {
150  return String.format(FILE_NAME_TEMPLATE, name.replace(" ", "-"));
151  }
152 
156  private static final class TagSetJsonFileFilter implements FileFilter {
157 
158  @Override
159  public boolean accept(File file) {
160  return file.getName().endsWith("tag-set.json");
161  }
162 
163  }
164 
165  // Custom JSON Deserializer for TagSetDefinition to support legacy user tags and tag set JSON files.
166  // In TSK release 4.13.0 and Autopsy release 4.22.0 we:
167  // 1) renamed "TskData.KnownStatus" to "TskData.TagType"
168  // 2) renamed "TagSetDefinition.knownStatus" to "TagSetDefinition.tagType"
169  // 3) "TskData.KnownStatus" of "unknown" used to carry a score of "suspicious".
170  // Now "TskData.TagType" of "unknown" carries a score of "unknown".
171  //
172  private static class TagSetDefinitionDeserializer implements JsonDeserializer<TagSetDefinition> {
173 
174  @Override
175  public TagSetDefinition deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
176  JsonObject jsonObject = json.getAsJsonObject();
177 
178  String name = jsonObject.has("name") ? jsonObject.get("name").getAsString() : null;
179  JsonArray tagArray = jsonObject.has("tagNameDefinitionList") ? jsonObject.getAsJsonArray("tagNameDefinitionList") : new JsonArray();
180  List<TagNameDefinition> tagNameDefinitions = new ArrayList<>();
181 
182  for (JsonElement element : tagArray) {
183  JsonObject tagObject = element.getAsJsonObject();
184 
185  String displayName = tagObject.has("displayName") ? tagObject.get("displayName").getAsString() : null;
186  String description = tagObject.has("description") ? tagObject.get("description").getAsString() : null;
187  TagName.HTML_COLOR color = context.deserialize(tagObject.get("color"), TagName.HTML_COLOR.class);
188 
189  TskData.TagType tagType = null;
190  // Handle tagType vs knownStatus
191  if (tagObject.has("tagType") && !tagObject.get("tagType").isJsonNull()) {
192  tagType = context.deserialize(tagObject.get("tagType"), TskData.TagType.class);
193  } else if (tagObject.has("knownStatus") && !tagObject.get("knownStatus").isJsonNull()) {
194  TskData.TagType legacyStatus = context.deserialize(tagObject.get("knownStatus"), TskData.TagType.class);
195 
196  // "UNKNOWN" tag type used to carry an automatic "SUSPICIOUS" score.
197  // If knownStatus was "UNKNOWN", use "SUSPICIOUS" instead
198  if (legacyStatus == TskData.TagType.UNKNOWN) {
199  tagType = TskData.TagType.SUSPICIOUS;
200  } else {
201  tagType = legacyStatus;
202  }
203  }
204 
205  if (tagType == null) {
206  LOGGER.log(Level.SEVERE, "Failed to initialize tagType for tag: {0}. Skipping entry.", displayName);
207  continue;
208  }
209 
210  tagNameDefinitions.add(new TagNameDefinition(displayName, description, color, tagType));
211  }
212 
213  return new TagSetDefinition(name, tagNameDefinitions);
214  }
215  }
216 }
TagSetDefinition deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
TagSetDefinition(String name, List< TagNameDefinition > tagNameDefinitionList)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

Copyright © 2012-2024 Sleuth Kit Labs. Generated on: Mon Mar 17 2025
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.