19 package org.sleuthkit.autopsy.report.infrastructure;
 
   23 import java.io.FileInputStream;
 
   24 import java.io.FileOutputStream;
 
   25 import java.io.IOException;
 
   26 import java.nio.file.Files;
 
   27 import java.nio.file.Path;
 
   28 import java.nio.file.Paths;
 
   29 import java.util.Arrays;
 
   30 import java.util.Iterator;
 
   31 import java.util.List;
 
   33 import java.util.Map.Entry;
 
   35 import java.util.TreeSet;
 
   36 import java.util.logging.Level;
 
   37 import org.apache.commons.io.FileUtils;
 
   38 import org.openide.util.io.NbObjectInputStream;
 
   39 import org.openide.util.io.NbObjectOutputStream;
 
   49 final class ReportingConfigLoader {
 
   51     private static final Logger logger = Logger.getLogger(ReportingConfigLoader.class.getName());
 
   52     private static final String REPORT_CONFIG_FOLDER = 
"ReportingConfigs"; 
 
   54     private static final String REPORT_CONFIG_FOLDER_PATH_LEGACY = Paths.get(
 
   55             PlatformUtil.getUserConfigDirectory(),
 
   56             ReportingConfigLoader.REPORT_CONFIG_FOLDER
 
   57     ).toAbsolutePath().toString();
 
   59     private static final String REPORT_CONFIG_FOLDER_PATH = Paths.get(
 
   60             PlatformUtil.getModuleConfigDirectory(),
 
   61             ReportingConfigLoader.REPORT_CONFIG_FOLDER
 
   62     ).toAbsolutePath().toString();
 
   64     private static final String REPORT_SETTINGS_FILE_EXTENSION = 
".settings";
 
   65     private static final String TABLE_REPORT_CONFIG_FILE = 
"TableReportSettings.settings";
 
   66     private static final String FILE_REPORT_CONFIG_FILE = 
"FileReportSettings.settings";
 
   67     private static final String GENERAL_REPORT_CONFIG_FILE = 
"GeneralReportSettings.settings";
 
   68     private static final String MODULE_CONFIG_FILE = 
"ModuleConfigs.settings";
 
   73     private static final List<String> DELETED_REPORT_MODULES = Arrays.asList(
"org.sleuthkit.autopsy.report.modules.stix.STIXReportModule");
 
   87     @SuppressWarnings(
"unchecked")
 
   88     static synchronized ReportingConfig loadConfig(String configName) throws ReportConfigException {
 
   91         Path reportDirPath = Paths.get(ReportingConfigLoader.REPORT_CONFIG_FOLDER_PATH, configName);
 
   92         File reportDirectory = reportDirPath.toFile();
 
   95         if (!reportDirectory.exists()) {
 
   96             throw new ReportConfigException(
"Unable to find report configuration folder for " + reportDirPath.toString() + 
". Please configure in the application Options panel.");
 
   99         if (!reportDirectory.isDirectory() || !reportDirectory.canRead()) {
 
  100             throw new ReportConfigException(
"Unable to read reporting configuration directory " + reportDirPath.toString());
 
  104         ReportingConfig config = 
new ReportingConfig(configName);
 
  107         String filePath = reportDirPath.toString() + File.separator + TABLE_REPORT_CONFIG_FILE;
 
  108         try (NbObjectInputStream in = 
new NbObjectInputStream(
new FileInputStream(filePath))) {
 
  109             config.setTableReportSettings((TableReportSettings) in.readObject());
 
  110         } 
catch (IOException | ClassNotFoundException ex) {
 
  111             throw new ReportConfigException(
"Unable to read table report settings " + filePath, ex);
 
  115         filePath = reportDirPath.toString() + File.separator + FILE_REPORT_CONFIG_FILE;
 
  116         try (NbObjectInputStream in = 
new NbObjectInputStream(
new FileInputStream(filePath))) {
 
  117             config.setFileReportSettings((FileReportSettings) in.readObject());
 
  118         } 
catch (IOException | ClassNotFoundException ex) {
 
  119             throw new ReportConfigException(
"Unable to read file report settings " + filePath, ex);
 
  122         filePath = reportDirPath.resolve(GENERAL_REPORT_CONFIG_FILE).toString();
 
  123         try (NbObjectInputStream in = 
new NbObjectInputStream(
new FileInputStream(filePath))) {
 
  124             config.setGeneralReportSettings((GeneralReportSettings) in.readObject());
 
  125         } 
catch (IOException | ClassNotFoundException ex) {
 
  126             throw new ReportConfigException(
"Unable to read general report settings " + filePath, ex);
 
  130         Map<String, ReportModuleConfig> moduleConfigs = null;
 
  131         filePath = reportDirPath.toString() + File.separator + MODULE_CONFIG_FILE;
 
  132         try (NbObjectInputStream in = 
new NbObjectInputStream(
new FileInputStream(filePath))) {
 
  133             moduleConfigs = (Map<String, ReportModuleConfig>) in.readObject();
 
  134         } 
catch (IOException | ClassNotFoundException ex) {
 
  135             throw new ReportConfigException(
"Unable to read module configurations map " + filePath, ex);
 
  138         if (moduleConfigs == null || moduleConfigs.isEmpty()) {
 
  143         for (Iterator<Entry<String, ReportModuleConfig>> iterator = moduleConfigs.entrySet().iterator(); iterator.hasNext();) {
 
  144             ReportModuleConfig moduleConfig = iterator.next().getValue();
 
  145             if (DELETED_REPORT_MODULES.contains(moduleConfig.getModuleClassName())) {
 
  149             filePath = reportDirPath.toString() + File.separator + moduleConfig.getModuleClassName() + REPORT_SETTINGS_FILE_EXTENSION;
 
  150             try (NbObjectInputStream in = 
new NbObjectInputStream(
new FileInputStream(filePath))) {
 
  151                 moduleConfig.setModuleSettings((ReportModuleSettings) in.readObject());
 
  152             } 
catch (IOException | ClassNotFoundException ex) {
 
  159                 logger.log(Level.SEVERE, 
"Unable to read module settings " + filePath, ex);
 
  164         config.setModuleConfigs(moduleConfigs);
 
  178     static synchronized void saveConfig(ReportingConfig reportConfig) 
throws ReportConfigException {
 
  180         if (reportConfig == null) {
 
  181             throw new ReportConfigException(
"Reporting configuration is NULL");
 
  185         Path pathToConfigDir = Paths.get(ReportingConfigLoader.REPORT_CONFIG_FOLDER_PATH, reportConfig.getName());
 
  189             Files.createDirectories(pathToConfigDir); 
 
  190         } 
catch (IOException | SecurityException ex) {
 
  191             throw new ReportConfigException(
"Failed to create reporting configuration directory " + pathToConfigDir.toString(), ex);
 
  195         String filePath = pathToConfigDir.toString() + File.separator + TABLE_REPORT_CONFIG_FILE;
 
  196         try (NbObjectOutputStream out = 
new NbObjectOutputStream(
new FileOutputStream(filePath))) {
 
  197             out.writeObject(reportConfig.getTableReportSettings());
 
  198         } 
catch (IOException ex) {
 
  199             throw new ReportConfigException(
"Unable to save table report configuration " + filePath, ex);
 
  203         filePath = pathToConfigDir.toString() + File.separator + FILE_REPORT_CONFIG_FILE;
 
  204         try (NbObjectOutputStream out = 
new NbObjectOutputStream(
new FileOutputStream(filePath))) {
 
  205             out.writeObject(reportConfig.getFileReportSettings());
 
  206         } 
catch (IOException ex) {
 
  207             throw new ReportConfigException(
"Unable to save file report configuration " + filePath, ex);
 
  210         filePath = pathToConfigDir.resolve(GENERAL_REPORT_CONFIG_FILE).toString();
 
  211         try (NbObjectOutputStream out = 
new NbObjectOutputStream(
new FileOutputStream(filePath))) {
 
  212             out.writeObject(reportConfig.getGeneralReportSettings());
 
  213         } 
catch (IOException ex) {
 
  214             throw new ReportConfigException(
"Unable to save general report configuration " + filePath, ex);
 
  218         filePath = pathToConfigDir.toString() + File.separator + MODULE_CONFIG_FILE;
 
  219         try (NbObjectOutputStream out = 
new NbObjectOutputStream(
new FileOutputStream(filePath))) {
 
  220             out.writeObject(reportConfig.getModuleConfigs());
 
  221         } 
catch (IOException ex) {
 
  222             throw new ReportConfigException(
"Unable to save module configurations map " + filePath, ex);
 
  233         if (reportConfig.getModuleConfigs() == null) {
 
  236         for (ReportModuleConfig moduleConfig : reportConfig.getModuleConfigs().values()) {
 
  237             ReportModuleSettings settings = moduleConfig.getModuleSettings();
 
  238             filePath = pathToConfigDir.toString() + File.separator + moduleConfig.getModuleClassName() + REPORT_SETTINGS_FILE_EXTENSION;
 
  239             try (NbObjectOutputStream out = 
new NbObjectOutputStream(
new FileOutputStream(filePath))) {
 
  240                 out.writeObject(settings);
 
  241             } 
catch (IOException ex) {
 
  242                 throw new ReportConfigException(
"Unable to save module settings " + filePath, ex);
 
  254     static synchronized Set<String> getListOfReportConfigs() {
 
  255         File reportDirPath = 
new File(ReportingConfigLoader.REPORT_CONFIG_FOLDER_PATH);
 
  256         Set<String> reportNameList = 
new TreeSet<>();
 
  258         if (!reportDirPath.exists()) {
 
  259             return reportNameList;
 
  262         for (File file : reportDirPath.listFiles()) {
 
  263             reportNameList.add(file.getName());
 
  266         return reportNameList;
 
  278     static synchronized boolean configExists(String configName) {
 
  280         Path reportDirPath = Paths.get(ReportingConfigLoader.REPORT_CONFIG_FOLDER_PATH, configName);
 
  281         File reportDirectory = reportDirPath.toFile();
 
  283         return reportDirectory.exists();
 
  286     static void upgradeConfig() throws IOException {
 
  287         File oldPath = 
new File(REPORT_CONFIG_FOLDER_PATH_LEGACY);
 
  288         File newPath = 
new File(REPORT_CONFIG_FOLDER_PATH);
 
  290         if (oldPath.exists() && Files.list(oldPath.toPath()).findFirst().isPresent()
 
  291                 && (!newPath.exists() || !Files.list(newPath.toPath()).findFirst().isPresent())) {
 
  293             FileUtils.copyDirectory(oldPath, newPath);