19package org.sleuthkit.autopsy.report.infrastructure;
21import org.sleuthkit.autopsy.report.ReportModuleSettings;
23import java.io.FileInputStream;
24import java.io.FileOutputStream;
25import java.io.IOException;
26import java.nio.file.Files;
27import java.nio.file.Path;
28import java.nio.file.Paths;
29import java.util.Arrays;
30import java.util.Iterator;
33import java.util.Map.Entry;
35import java.util.TreeSet;
36import java.util.logging.Level;
37import org.apache.commons.io.FileUtils;
38import org.openide.util.io.NbObjectInputStream;
39import org.openide.util.io.NbObjectOutputStream;
40import org.sleuthkit.autopsy.coreutils.Logger;
41import org.sleuthkit.autopsy.coreutils.PlatformUtil;
42import org.sleuthkit.autopsy.report.GeneralReportSettings;
49final 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");
94 @SuppressWarnings(
"unchecked")
95 static synchronized ReportingConfig loadConfig(String configName) throws ReportConfigException {
98 if (configName ==
null || configName.isEmpty() || configName.equals(
".")
99 || configName.indexOf(
'/') >= 0 || configName.indexOf(
'\\') >= 0
100 || configName.indexOf(File.separatorChar) >= 0) {
101 throw new ReportConfigException(
"Invalid report configuration name: " + configName);
105 Path reportDirPath = Paths.get(ReportingConfigLoader.REPORT_CONFIG_FOLDER_PATH, configName).normalize();
106 if (!reportDirPath.startsWith(Paths.get(ReportingConfigLoader.REPORT_CONFIG_FOLDER_PATH).normalize())) {
107 throw new ReportConfigException(
"Invalid report configuration name: " + configName);
109 File reportDirectory = reportDirPath.toFile();
112 if (!reportDirectory.exists()) {
113 throw new ReportConfigException(
"Unable to find report configuration folder for " + reportDirPath.toString() +
". Please configure in the application Options panel.");
116 if (!reportDirectory.isDirectory() || !reportDirectory.canRead()) {
117 throw new ReportConfigException(
"Unable to read reporting configuration directory " + reportDirPath.toString());
121 ReportingConfig config =
new ReportingConfig(configName);
124 String filePath = reportDirPath.toString() + File.separator + TABLE_REPORT_CONFIG_FILE;
125 try (NbObjectInputStream in =
new NbObjectInputStream(
new FileInputStream(filePath))) {
126 config.setTableReportSettings((TableReportSettings) in.readObject());
127 }
catch (IOException | ClassNotFoundException ex) {
128 throw new ReportConfigException(
"Unable to read table report settings " + filePath, ex);
132 filePath = reportDirPath.toString() + File.separator + FILE_REPORT_CONFIG_FILE;
133 try (NbObjectInputStream in =
new NbObjectInputStream(
new FileInputStream(filePath))) {
134 config.setFileReportSettings((FileReportSettings) in.readObject());
135 }
catch (IOException | ClassNotFoundException ex) {
136 throw new ReportConfigException(
"Unable to read file report settings " + filePath, ex);
139 filePath = reportDirPath.resolve(GENERAL_REPORT_CONFIG_FILE).toString();
140 try (NbObjectInputStream in =
new NbObjectInputStream(
new FileInputStream(filePath))) {
141 config.setGeneralReportSettings((GeneralReportSettings) in.readObject());
142 }
catch (IOException | ClassNotFoundException ex) {
143 throw new ReportConfigException(
"Unable to read general report settings " + filePath, ex);
147 Map<String, ReportModuleConfig> moduleConfigs =
null;
148 filePath = reportDirPath.toString() + File.separator + MODULE_CONFIG_FILE;
149 try (NbObjectInputStream in =
new NbObjectInputStream(
new FileInputStream(filePath))) {
150 moduleConfigs = (Map<String, ReportModuleConfig>) in.readObject();
151 }
catch (IOException | ClassNotFoundException ex) {
152 throw new ReportConfigException(
"Unable to read module configurations map " + filePath, ex);
155 if (moduleConfigs ==
null || moduleConfigs.isEmpty()) {
160 for (Iterator<Entry<String, ReportModuleConfig>> iterator = moduleConfigs.entrySet().iterator(); iterator.hasNext();) {
161 ReportModuleConfig moduleConfig = iterator.next().getValue();
162 if (DELETED_REPORT_MODULES.contains(moduleConfig.getModuleClassName())) {
166 filePath = reportDirPath.toString() + File.separator + moduleConfig.getModuleClassName() + REPORT_SETTINGS_FILE_EXTENSION;
167 try (NbObjectInputStream in =
new NbObjectInputStream(
new FileInputStream(filePath))) {
168 moduleConfig.setModuleSettings((ReportModuleSettings) in.readObject());
169 }
catch (IOException | ClassNotFoundException ex) {
176 logger.log(Level.SEVERE,
"Unable to read module settings " + filePath, ex);
181 config.setModuleConfigs(moduleConfigs);
206 static synchronized void saveConfig(ReportingConfig reportConfig)
throws ReportConfigException {
208 if (reportConfig ==
null) {
209 throw new ReportConfigException(
"Reporting configuration is NULL");
213 String configName = reportConfig.getName();
214 if (configName ==
null || configName.isEmpty() || configName.equals(
".")
215 || configName.indexOf(
'/') >= 0 || configName.indexOf(
'\\') >= 0
216 || configName.indexOf(File.separatorChar) >= 0) {
217 throw new ReportConfigException(
"Invalid report configuration name: " + configName);
221 Path pathToConfigDir = Paths.get(ReportingConfigLoader.REPORT_CONFIG_FOLDER_PATH, configName).normalize();
222 if (!pathToConfigDir.startsWith(Paths.get(ReportingConfigLoader.REPORT_CONFIG_FOLDER_PATH).normalize())) {
223 throw new ReportConfigException(
"Invalid report configuration name: " + configName);
228 Files.createDirectories(pathToConfigDir);
229 }
catch (IOException | SecurityException ex) {
230 throw new ReportConfigException(
"Failed to create reporting configuration directory " + pathToConfigDir.toString(), ex);
234 String filePath = pathToConfigDir.toString() + File.separator + TABLE_REPORT_CONFIG_FILE;
235 try (NbObjectOutputStream out =
new NbObjectOutputStream(
new FileOutputStream(filePath))) {
236 out.writeObject(reportConfig.getTableReportSettings());
237 }
catch (IOException ex) {
238 throw new ReportConfigException(
"Unable to save table report configuration " + filePath, ex);
242 filePath = pathToConfigDir.toString() + File.separator + FILE_REPORT_CONFIG_FILE;
243 try (NbObjectOutputStream out =
new NbObjectOutputStream(
new FileOutputStream(filePath))) {
244 out.writeObject(reportConfig.getFileReportSettings());
245 }
catch (IOException ex) {
246 throw new ReportConfigException(
"Unable to save file report configuration " + filePath, ex);
249 filePath = pathToConfigDir.resolve(GENERAL_REPORT_CONFIG_FILE).toString();
250 try (NbObjectOutputStream out =
new NbObjectOutputStream(
new FileOutputStream(filePath))) {
251 out.writeObject(reportConfig.getGeneralReportSettings());
252 }
catch (IOException ex) {
253 throw new ReportConfigException(
"Unable to save general report configuration " + filePath, ex);
257 filePath = pathToConfigDir.toString() + File.separator + MODULE_CONFIG_FILE;
258 try (NbObjectOutputStream out =
new NbObjectOutputStream(
new FileOutputStream(filePath))) {
259 out.writeObject(reportConfig.getModuleConfigs());
260 }
catch (IOException ex) {
261 throw new ReportConfigException(
"Unable to save module configurations map " + filePath, ex);
272 if (reportConfig.getModuleConfigs() ==
null) {
275 for (ReportModuleConfig moduleConfig : reportConfig.getModuleConfigs().values()) {
277 filePath = pathToConfigDir.toString() + File.separator + moduleConfig.getModuleClassName() + REPORT_SETTINGS_FILE_EXTENSION;
278 try (NbObjectOutputStream out =
new NbObjectOutputStream(
new FileOutputStream(filePath))) {
279 out.writeObject(settings);
280 }
catch (IOException ex) {
281 throw new ReportConfigException(
"Unable to save module settings " + filePath, ex);
293 static synchronized Set<String> getListOfReportConfigs() {
294 File reportDirPath =
new File(ReportingConfigLoader.REPORT_CONFIG_FOLDER_PATH);
295 Set<String> reportNameList =
new TreeSet<>();
297 if (!reportDirPath.exists()) {
298 return reportNameList;
301 for (File file : reportDirPath.listFiles()) {
302 reportNameList.add(file.getName());
305 return reportNameList;
317 static synchronized boolean configExists(String configName) {
319 Path reportDirPath = Paths.get(ReportingConfigLoader.REPORT_CONFIG_FOLDER_PATH, configName);
320 File reportDirectory = reportDirPath.toFile();
322 return reportDirectory.exists();
325 static void upgradeConfig() throws IOException {
326 File oldPath =
new File(REPORT_CONFIG_FOLDER_PATH_LEGACY);
327 File newPath =
new File(REPORT_CONFIG_FOLDER_PATH);
329 if (oldPath.exists() && Files.list(oldPath.toPath()).findFirst().isPresent()
330 && (!newPath.exists() || !Files.list(newPath.toPath()).findFirst().isPresent())) {
332 FileUtils.copyDirectory(oldPath, newPath);