Autopsy  3.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
IngestJobSettings.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2014 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.ingest;
20 
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.nio.file.Paths;
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.logging.Level;
33 import org.openide.util.NbBundle;
34 import org.openide.util.io.NbObjectInputStream;
35 import org.openide.util.io.NbObjectOutputStream;
39 import org.python.util.PythonObjectInputStream;
40 
45 public class IngestJobSettings {
46 
47  private static final String ENABLED_MODULES_KEY = "Enabled_Ingest_Modules"; //NON-NLS
48  private static final String DISABLED_MODULES_KEY = "Disabled_Ingest_Modules"; //NON-NLS
49  private static final String PARSE_UNALLOC_SPACE_KEY = "Process_Unallocated_Space"; //NON-NLS
50  private static final String PROCESS_UNALLOC_SPACE_DEFAULT = "true"; //NON-NLS
51  private static final String MODULE_SETTINGS_FOLDER = "IngestModuleSettings"; //NON-NLS
52  private static final String MODULE_SETTINGS_FOLDER_PATH = Paths.get(PlatformUtil.getUserConfigDirectory(), IngestJobSettings.MODULE_SETTINGS_FOLDER).toAbsolutePath().toString();
53  private static final String MODULE_SETTINGS_FILE_EXT = ".settings"; //NON-NLS
54  private static final Logger logger = Logger.getLogger(IngestJobSettings.class.getName());
55  private final String context;
56  private String moduleSettingsFolderPath;
57  private static final CharSequence pythonModuleSettingsPrefixCS = "org.python.proxies.".subSequence(0, "org.python.proxies.".length()-1);
58  private final List<IngestModuleTemplate> moduleTemplates;
59  private boolean processUnallocatedSpace;
60  private final List<String> warnings;
61 
67  public IngestJobSettings(String context) {
68  this.context = context;
69  this.moduleTemplates = new ArrayList<>();
70  this.processUnallocatedSpace = Boolean.parseBoolean(IngestJobSettings.PROCESS_UNALLOC_SPACE_DEFAULT);
71  this.warnings = new ArrayList<>();
73  this.load();
74  }
75 
79  public void save() {
80  this.store();
81  }
82 
89  public List<String> getWarnings() {
90  List<String> warningMessages = new ArrayList<>(this.warnings);
91  this.warnings.clear();
92  return warningMessages;
93  }
94 
100  List<IngestModuleTemplate> getIngestModuleTemplates() {
101  return Collections.unmodifiableList(this.moduleTemplates);
102  }
103 
110  List<IngestModuleTemplate> getEnabledIngestModuleTemplates() {
111  List<IngestModuleTemplate> enabledModuleTemplates = new ArrayList<>();
112  for (IngestModuleTemplate moduleTemplate : this.moduleTemplates) {
113  if (moduleTemplate.isEnabled()) {
114  enabledModuleTemplates.add(moduleTemplate);
115  }
116  }
117  return enabledModuleTemplates;
118  }
119 
125  void setIngestModuleTemplates(List<IngestModuleTemplate> moduleTemplates) {
126  this.moduleTemplates.clear();
127  this.moduleTemplates.addAll(moduleTemplates);
128  }
129 
136  boolean getProcessUnallocatedSpace() {
137  return this.processUnallocatedSpace;
138  }
139 
145  void setProcessUnallocatedSpace(boolean processUnallocatedSpace) {
146  this.processUnallocatedSpace = processUnallocatedSpace;
147  }
148 
154  try {
155  Path folder = Paths.get(IngestJobSettings.MODULE_SETTINGS_FOLDER_PATH, context);
156  Files.createDirectories(folder);
157  this.moduleSettingsFolderPath = folder.toAbsolutePath().toString();
158  } catch (IOException | SecurityException ex) {
159  logger.log(Level.SEVERE, "Failed to create ingest module settings directory " + this.moduleSettingsFolderPath, ex); //NON-NLS
160  this.warnings.add(NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.createModuleSettingsFolder.warning")); //NON-NLS
161  }
162  }
163 
167  private void load() {
172  List<IngestModuleFactory> moduleFactories = IngestModuleFactoryLoader.getIngestModuleFactories();
173  HashSet<String> loadedModuleNames = new HashSet<>();
174  for (IngestModuleFactory moduleFactory : moduleFactories) {
175  loadedModuleNames.add(moduleFactory.getModuleDisplayName());
176  }
177 
182  HashSet<String> enabledModuleNames = getModulesNamesFromSetting(IngestJobSettings.ENABLED_MODULES_KEY, makeCommaSeparatedValuesList(loadedModuleNames));
183  HashSet<String> disabledModuleNames = getModulesNamesFromSetting(IngestJobSettings.DISABLED_MODULES_KEY, ""); //NON-NLS
184 
188  List<String> missingModuleNames = new ArrayList<>();
189  for (String moduleName : enabledModuleNames) {
190  if (!loadedModuleNames.contains(moduleName)) {
191  missingModuleNames.add(moduleName);
192  }
193  }
194  for (String moduleName : disabledModuleNames) {
195  if (!loadedModuleNames.contains(moduleName)) {
196  missingModuleNames.add(moduleName);
197  }
198  }
199  for (String moduleName : missingModuleNames) {
200  enabledModuleNames.remove(moduleName);
201  disabledModuleNames.remove(moduleName);
202  String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.missingModule.warning", moduleName); //NON-NLS
203  logger.log(Level.WARNING, warning);
204  this.warnings.add(warning);
205  }
206 
211  for (IngestModuleFactory moduleFactory : moduleFactories) {
212  IngestModuleTemplate moduleTemplate = new IngestModuleTemplate(moduleFactory, loadModuleSettings(moduleFactory));
213  String moduleName = moduleTemplate.getModuleName();
214  if (enabledModuleNames.contains(moduleName)) {
215  moduleTemplate.setEnabled(true);
216  } else if (disabledModuleNames.contains(moduleName)) {
217  moduleTemplate.setEnabled(false);
218  } else {
219  // The module factory was loaded, but the module name does not
220  // appear in the enabled/disabled module settings. Treat the
221  // module as a new module and enable it by default.
222  moduleTemplate.setEnabled(true);
223  enabledModuleNames.add(moduleName);
224  }
225  this.moduleTemplates.add(moduleTemplate);
226  }
227 
234 
235  // Get the process unallocated space flag setting. If the setting does
236  // not exist yet, default it to true.
239  }
240  this.processUnallocatedSpace = Boolean.parseBoolean(ModuleSettings.getConfigSetting(this.context, IngestJobSettings.PARSE_UNALLOC_SPACE_KEY));
241  }
242 
250  private HashSet<String> getModulesNamesFromSetting(String key, String defaultSetting) {
251  if (ModuleSettings.settingExists(this.context, key) == false) {
252  ModuleSettings.setConfigSetting(this.context, key, defaultSetting);
253  }
254  HashSet<String> moduleNames = new HashSet<>();
255  String modulesSetting = ModuleSettings.getConfigSetting(this.context, key);
256  if (!modulesSetting.isEmpty()) {
257  String[] settingNames = modulesSetting.split(", ");
258  for (String name : settingNames) {
259  // Map some old core module names to the current core module names.
260  switch (name) {
261  case "Thunderbird Parser": //NON-NLS
262  case "MBox Parser": //NON-NLS
263  moduleNames.add("Email Parser"); //NON-NLS
264  break;
265  case "File Extension Mismatch Detection": //NON-NLS
266  moduleNames.add("Extension Mismatch Detector"); //NON-NLS
267  break;
268  case "EWF Verify": //NON-NLS
269  case "E01 Verify": //NON-NLS
270  moduleNames.add("E01 Verifier"); //NON-NLS
271  break;
272  case "Archive Extractor": //NON-NLS
273  moduleNames.add("Embedded File Extractor");
274  break;
275  default:
276  moduleNames.add(name);
277  }
278  }
279  }
280  return moduleNames;
281  }
282 
290  private boolean isPythonModuleSettingsFile(String moduleSettingsFilePath) {
291  return moduleSettingsFilePath.contains(pythonModuleSettingsPrefixCS);
292  }
293 
302  IngestModuleIngestJobSettings settings = null;
303  String moduleSettingsFilePath = getModuleSettingsFilePath(factory);
304  File settingsFile = new File(moduleSettingsFilePath);
305  if (settingsFile.exists()) {
306  if (!isPythonModuleSettingsFile(moduleSettingsFilePath)) {
307  try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(settingsFile.getAbsolutePath()))) {
308  settings = (IngestModuleIngestJobSettings) in.readObject();
309  } catch (IOException | ClassNotFoundException ex) {
310  String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsLoad.warning", factory.getModuleDisplayName(), this.context); //NON-NLS
311  logger.log(Level.WARNING, warning, ex);
312  this.warnings.add(warning);
313  }
314  } else {
315  try (PythonObjectInputStream in = new PythonObjectInputStream(new FileInputStream(settingsFile.getAbsolutePath()))) {
316  settings = (IngestModuleIngestJobSettings) in.readObject();
317  } catch (IOException | ClassNotFoundException exception) {
318  String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsLoad.warning", factory.getModuleDisplayName(), this.context); //NON-NLS
319  logger.log(Level.WARNING, warning, exception);
320  this.warnings.add(warning);
321  }
322  }
323  }
324  if (settings == null) {
325  settings = factory.getDefaultIngestJobSettings();
326  }
327  return settings;
328  }
329 
338  String fileName = factory.getClass().getCanonicalName() + IngestJobSettings.MODULE_SETTINGS_FILE_EXT;
339  Path path = Paths.get(this.moduleSettingsFolderPath, fileName);
340  return path.toAbsolutePath().toString();
341  }
342 
346  private void store() {
350  HashSet<String> enabledModuleNames = new HashSet<>();
351  HashSet<String> disabledModuleNames = new HashSet<>();
352  for (IngestModuleTemplate moduleTemplate : moduleTemplates) {
353  saveModuleSettings(moduleTemplate.getModuleFactory(), moduleTemplate.getModuleSettings());
354  String moduleName = moduleTemplate.getModuleName();
355  if (moduleTemplate.isEnabled()) {
356  enabledModuleNames.add(moduleName);
357  } else {
358  disabledModuleNames.add(moduleName);
359  }
360  }
361  ModuleSettings.setConfigSetting(this.context, ENABLED_MODULES_KEY, makeCommaSeparatedValuesList(enabledModuleNames));
362  ModuleSettings.setConfigSetting(this.context, DISABLED_MODULES_KEY, makeCommaSeparatedValuesList(disabledModuleNames));
363 
367  String processUnalloc = Boolean.toString(this.processUnallocatedSpace);
368  ModuleSettings.setConfigSetting(this.context, PARSE_UNALLOC_SPACE_KEY, processUnalloc);
369  }
370 
379  try {
380  String moduleSettingsFilePath = getModuleSettingsFilePath(factory);
381  // compiled python modules have substring org.python.proxies. It can be used to identify them.
382  if (isPythonModuleSettingsFile(moduleSettingsFilePath)) {
383  // compiled python modules have variable instance number as a part of their file name.
384  // This block of code gets rid of that variable instance number and helps maitains constant module name over multiple runs.
385  moduleSettingsFilePath.replaceAll("[$][\\d]+.settings$", "\\$.settings");
386  }
387  try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(moduleSettingsFilePath))) {
388  out.writeObject(settings);
389  }
390  } catch (IOException ex) {
391  String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsSave.warning", factory.getModuleDisplayName(), this.context); //NON-NLS
392  logger.log(Level.SEVERE, warning, ex);
393  this.warnings.add(warning);
394  }
395  }
396 
404  private static String makeCommaSeparatedValuesList(HashSet<String> input) {
405  if (input == null || input.isEmpty()) {
406  return "";
407  }
408 
409  ArrayList<String> list = new ArrayList<>();
410  list.addAll(input);
411  StringBuilder csvList = new StringBuilder();
412  for (int i = 0; i < list.size() - 1; ++i) {
413  csvList.append(list.get(i)).append(", ");
414  }
415  csvList.append(list.get(list.size() - 1));
416  return csvList.toString();
417  }
418 
419 }
void saveModuleSettings(IngestModuleFactory factory, IngestModuleIngestJobSettings settings)
static String makeCommaSeparatedValuesList(HashSet< String > input)
IngestModuleIngestJobSettings getDefaultIngestJobSettings()
HashSet< String > getModulesNamesFromSetting(String key, String defaultSetting)
final List< IngestModuleTemplate > moduleTemplates
static synchronized void setConfigSetting(String moduleName, String settingName, String settingVal)
IngestModuleIngestJobSettings loadModuleSettings(IngestModuleFactory factory)
String getModuleSettingsFilePath(IngestModuleFactory factory)
static String getConfigSetting(String moduleName, String settingName)
boolean isPythonModuleSettingsFile(String moduleSettingsFilePath)
static boolean settingExists(String moduleName, String settingName)
static Logger getLogger(String name)
Definition: Logger.java:131

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