diff --git a/Core/build.xml b/Core/build.xml
index c698835266..73bda54795 100644
--- a/Core/build.xml
+++ b/Core/build.xml
@@ -54,6 +54,11 @@
+
+
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/Bundle.properties
deleted file mode 100644
index 15698d736c..0000000000
--- a/Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/Bundle.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-ILeappAnalyzerIngestModule.init.exception.msg=Unable to find {0}.
-ILeappAnalyzerIngestModule.processing.file=Processing file {0}
-ILeappAnalyzerIngestModule.parsing.file=Parsing file {0}
-ILeappAnalyzerIngestModule.processing.filesystem=Processing filesystem
\ No newline at end of file
diff --git a/Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/Bundle.properties-MERGED
deleted file mode 100644
index b4e8226a91..0000000000
--- a/Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/Bundle.properties-MERGED
+++ /dev/null
@@ -1,30 +0,0 @@
-ILeappAnalyzerIngestModule.completed=iLeapp Processing Completed
-ILeappAnalyzerIngestModule.error.creating.output.dir=Error creating iLeapp module output directory.
-ILeappAnalyzerIngestModule.error.ileapp.file.processor.init=Failure to initialize ILeappProcessFile
-ILeappAnalyzerIngestModule.error.running.iLeapp=Error running iLeapp, see log file.
-ILeappAnalyzerIngestModule.executable.not.found=iLeapp Executable Not Found.
-ILeappAnalyzerIngestModule.has.run=iLeapp
-ILeappAnalyzerIngestModule.iLeapp.cancelled=iLeapp run was canceled
-ILeappAnalyzerIngestModule.init.exception.msg=Unable to find {0}.
-ILeappAnalyzerIngestModule.processing.file=Processing file {0}
-ILeappAnalyzerIngestModule.parsing.file=Parsing file {0}
-ILeappAnalyzerIngestModule.processing.filesystem=Processing filesystem
-ILeappAnalyzerIngestModule.report.name=iLeapp Html Report
-ILeappAnalyzerIngestModule.requires.windows=iLeapp module requires windows.
-ILeappAnalyzerIngestModule.running.iLeapp=Running iLeapp
-ILeappAnalyzerIngestModule.starting.iLeapp=Starting iLeapp
-ILeappAnalyzerModuleFactory_moduleDesc=Uses iLEAPP to analyze logical acquisitions of iOS devices.
-ILeappAnalyzerModuleFactory_moduleName=iOS Analyzer (iLEAPP)
-ILeappFileProcessor.cannot.load.artifact.xml=Cannor load xml artifact file.
-ILeappFileProcessor.cannotBuildXmlParser=Cannot buld an XML parser.
-ILeappFileProcessor.completed=iLeapp Processing Completed
-ILeappFileProcessor.error.creating.new.artifacts=Error creating new artifacts.
-ILeappFileProcessor.error.creating.output.dir=Error creating iLeapp module output directory.
-ILeappFileProcessor.error.reading.iLeapp.directory=Error reading iLeapp Output Directory
-ILeappFileProcessor.error.running.iLeapp=Error running iLeapp, see log file.
-ILeappFileProcessor.has.run=iLeapp
-ILeappFileProcessor.iLeapp.cancelled=iLeapp run was canceled
-ILeappFileProcessor.postartifacts_error=Error posting Blackboard Artifact
-ILeappFileProcessor.running.iLeapp=Running iLeapp
-ILeappFileProcessor.starting.iLeapp=Starting iLeapp
-ILeappFileProcessor_cannotParseXml=Cannot Parse XML file.
diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ALeappAnalyzerIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ALeappAnalyzerIngestModule.java
new file mode 100644
index 0000000000..e82215a7de
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ALeappAnalyzerIngestModule.java
@@ -0,0 +1,492 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2020 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.modules.leappanalyzers;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.SimpleDateFormat;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Locale;
+import java.util.logging.Level;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.commons.io.FilenameUtils;
+import org.openide.modules.InstalledFileLocator;
+import org.openide.util.NbBundle;
+import org.sleuthkit.autopsy.casemodule.Case;
+import static org.sleuthkit.autopsy.casemodule.Case.getCurrentCase;
+import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
+import org.sleuthkit.autopsy.casemodule.services.FileManager;
+import org.sleuthkit.autopsy.coreutils.ExecUtil;
+import org.sleuthkit.autopsy.coreutils.Logger;
+import org.sleuthkit.autopsy.coreutils.PlatformUtil;
+import org.sleuthkit.autopsy.datamodel.ContentUtils;
+import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
+import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProcessTerminator;
+import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
+import org.sleuthkit.autopsy.ingest.IngestJobContext;
+import org.sleuthkit.autopsy.ingest.IngestMessage;
+import org.sleuthkit.autopsy.ingest.IngestServices;
+import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException;
+import org.sleuthkit.datamodel.AbstractFile;
+import org.sleuthkit.datamodel.Content;
+import org.sleuthkit.datamodel.LocalFilesDataSource;
+import org.sleuthkit.datamodel.ReadContentInputStream;
+import org.sleuthkit.datamodel.TskCoreException;
+
+/**
+ * Data source ingest module that runs aLeapp against logical iOS files.
+ */
+public class ALeappAnalyzerIngestModule implements DataSourceIngestModule {
+
+ private static final Logger logger = Logger.getLogger(ALeappAnalyzerIngestModule.class.getName());
+ private static final String MODULE_NAME = ALeappAnalyzerModuleFactory.getModuleName();
+
+ private static final String ALEAPP = "aLeapp"; //NON-NLS
+ private static final String ALEAPP_FS = "fs_"; //NON-NLS
+ private static final String ALEAPP_EXECUTABLE = "aleapp.exe";//NON-NLS
+ private static final String ALEAPP_PATHS_FILE = "aLeapp_paths.txt"; //NON-NLS
+
+ private static final String XMLFILE = "aleap-artifact-attribute-reference.xml"; //NON-NLS
+
+
+ private File aLeappExecutable;
+
+ private IngestJobContext context;
+
+ private LeappFileProcessor aLeappFileProcessor;
+
+ ALeappAnalyzerIngestModule() {
+ // This constructor is intentionally empty. Nothing special is needed here.
+ }
+
+ @NbBundle.Messages({
+ "ALeappAnalyzerIngestModule.executable.not.found=aLeapp Executable Not Found.",
+ "ALeappAnalyzerIngestModule.requires.windows=aLeapp module requires windows.",
+ "ALeappAnalyzerIngestModule.error.ileapp.file.processor.init=Failure to initialize aLeappProcessFile"})
+ @Override
+ public void startUp(IngestJobContext context) throws IngestModuleException {
+ this.context = context;
+
+ if (false == PlatformUtil.isWindowsOS()) {
+ throw new IngestModuleException(Bundle.ALeappAnalyzerIngestModule_requires_windows());
+ }
+
+ try {
+ aLeappFileProcessor = new LeappFileProcessor(XMLFILE);
+ } catch (IOException | IngestModuleException | NoCurrentCaseException ex) {
+ throw new IngestModuleException(Bundle.ALeappAnalyzerIngestModule_error_ileapp_file_processor_init(), ex);
+ }
+
+ try {
+ aLeappExecutable = locateExecutable(ALEAPP_EXECUTABLE);
+ } catch (FileNotFoundException exception) {
+ logger.log(Level.WARNING, "aLeapp executable not found.", exception); //NON-NLS
+ throw new IngestModuleException(Bundle.ALeappAnalyzerIngestModule_executable_not_found(), exception);
+ }
+
+ }
+
+ @NbBundle.Messages({
+ "ALeappAnalyzerIngestModule.error.running.aLeapp=Error running aLeapp, see log file.",
+ "ALeappAnalyzerIngestModule.error.creating.output.dir=Error creating aLeapp module output directory.",
+ "ALeappAnalyzerIngestModule.starting.aLeapp=Starting aLeapp",
+ "ALeappAnalyzerIngestModule.running.aLeapp=Running aLeapp",
+ "ALeappAnalyzerIngestModule.has.run=aLeapp",
+ "ALeappAnalyzerIngestModule.aLeapp.cancelled=aLeapp run was canceled",
+ "ALeappAnalyzerIngestModule.completed=aLeapp Processing Completed",
+ "ALeappAnalyzerIngestModule.report.name=aLeapp Html Report"})
+ @Override
+ public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper) {
+
+ Case currentCase = Case.getCurrentCase();
+ Path tempOutputPath = Paths.get(currentCase.getTempDirectory(), ALEAPP, ALEAPP_FS + dataSource.getId());
+ try {
+ Files.createDirectories(tempOutputPath);
+ } catch (IOException ex) {
+ logger.log(Level.SEVERE, String.format("Error creating aLeapp output directory %s", tempOutputPath.toString()), ex);
+ return ProcessResult.ERROR;
+ }
+
+ List aLeappPathsToProcess = new ArrayList<>();
+ ProcessBuilder aLeappCommand = buildaLeappListCommand(tempOutputPath);
+ try {
+ int result = ExecUtil.execute(aLeappCommand, new DataSourceIngestModuleProcessTerminator(context, true));
+ if (result != 0) {
+ logger.log(Level.SEVERE, String.format("Error when trying to execute aLeapp program getting file paths to search for result is %d", result));
+ return ProcessResult.ERROR;
+ }
+ aLeappPathsToProcess = loadIleappPathFile(tempOutputPath);
+ } catch (IOException ex) {
+ logger.log(Level.SEVERE, String.format("Error when trying to execute aLeapp program getting file paths to search"), ex);
+ return ProcessResult.ERROR;
+ }
+
+ statusHelper.progress(Bundle.ALeappAnalyzerIngestModule_starting_aLeapp(), 0);
+
+ List aLeappFilesToProcess = new ArrayList<>();
+
+ if (!(context.getDataSource() instanceof LocalFilesDataSource)) {
+ extractFilesFromImage(dataSource, aLeappPathsToProcess, tempOutputPath);
+ statusHelper.switchToDeterminate(aLeappFilesToProcess.size());
+ processALeappFs(dataSource, currentCase, statusHelper, tempOutputPath.toString());
+ } else {
+ aLeappFilesToProcess = findaLeappFilesToProcess(dataSource);
+ statusHelper.switchToDeterminate(aLeappFilesToProcess.size());
+
+ Integer filesProcessedCount = 0;
+ for (AbstractFile aLeappFile : aLeappFilesToProcess) {
+ processALeappFile(dataSource, currentCase, statusHelper, filesProcessedCount, aLeappFile);
+ filesProcessedCount++;
+ }
+ // Process the logical image as a fs in aLeapp to make sure this is not a logical fs that was added
+ extractFilesFromImage(dataSource, aLeappPathsToProcess, tempOutputPath);
+ processALeappFs(dataSource, currentCase, statusHelper, tempOutputPath.toString());
+ }
+
+ IngestMessage message = IngestMessage.createMessage(IngestMessage.MessageType.DATA,
+ Bundle.ALeappAnalyzerIngestModule_has_run(),
+ Bundle.ALeappAnalyzerIngestModule_completed());
+ IngestServices.getInstance().postMessage(message);
+ return ProcessResult.OK;
+ }
+
+ /**
+ * Process a file from a logical image using the aLeapp program
+ * @param dataSource datasource to process
+ * @param currentCase current case that is being worked on
+ * @param statusHelper show progress and update what is being processed
+ * @param filesProcessedCount number of files that have been processed
+ * @param aLeappFile the abstract file to process
+ */
+ private void processALeappFile(Content dataSource, Case currentCase, DataSourceIngestModuleProgress statusHelper, int filesProcessedCount,
+ AbstractFile aLeappFile) {
+ String currentTime = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss z", Locale.US).format(System.currentTimeMillis());//NON-NLS
+ Path moduleOutputPath = Paths.get(currentCase.getModuleDirectory(), ALEAPP, currentTime);
+ try {
+ Files.createDirectories(moduleOutputPath);
+ } catch (IOException ex) {
+ logger.log(Level.SEVERE, String.format("Error creating aLeapp output directory %s", moduleOutputPath.toString()), ex);
+ return;
+ }
+
+ statusHelper.progress(NbBundle.getMessage(this.getClass(), "ALeappAnalyzerIngestModule.processing.file", aLeappFile.getName()), filesProcessedCount);
+ ProcessBuilder aLeappCommand = buildaLeappCommand(moduleOutputPath, aLeappFile.getLocalAbsPath(), aLeappFile.getNameExtension());
+ try {
+ int result = ExecUtil.execute(aLeappCommand, new DataSourceIngestModuleProcessTerminator(context, true));
+ if (result != 0) {
+ logger.log(Level.WARNING, String.format("Error when trying to execute aLeapp program getting file paths to search for result is %d", result));
+ return;
+ }
+
+ addILeappReportToReports(moduleOutputPath, currentCase);
+
+ } catch (IOException ex) {
+ logger.log(Level.SEVERE, String.format("Error when trying to execute aLeapp program against file %s", aLeappFile.getLocalAbsPath()), ex);
+ return;
+ }
+
+ if (context.dataSourceIngestIsCancelled()) {
+ logger.log(Level.INFO, "ILeapp Analyser ingest module run was canceled"); //NON-NLS
+ return;
+ }
+
+ ProcessResult fileProcessorResult = aLeappFileProcessor.processFiles(dataSource, moduleOutputPath, aLeappFile);
+
+ if (fileProcessorResult == ProcessResult.ERROR) {
+ return;
+ }
+ }
+
+ /**
+ * Process a image/directory using the aLeapp program
+ * @param dataSource datasource to process
+ * @param currentCase current case being procesed
+ * @param statusHelper show progress and update what is being processed
+ * @param directoryToProcess directory to run aLeapp against
+ */
+ private void processALeappFs(Content dataSource, Case currentCase, DataSourceIngestModuleProgress statusHelper, String directoryToProcess) {
+ String currentTime = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss z", Locale.US).format(System.currentTimeMillis());//NON-NLS
+ Path moduleOutputPath = Paths.get(currentCase.getModuleDirectory(), ALEAPP, currentTime);
+ try {
+ Files.createDirectories(moduleOutputPath);
+ } catch (IOException ex) {
+ logger.log(Level.SEVERE, String.format("Error creating aLeapp output directory %s", moduleOutputPath.toString()), ex);
+ return;
+ }
+
+ statusHelper.progress(NbBundle.getMessage(this.getClass(), "ALeappAnalyzerIngestModule.processing.filesystem"));
+ ProcessBuilder aLeappCommand = buildaLeappCommand(moduleOutputPath, directoryToProcess, "fs");
+ try {
+ int result = ExecUtil.execute(aLeappCommand, new DataSourceIngestModuleProcessTerminator(context, true));
+ if (result != 0) {
+ logger.log(Level.WARNING, String.format("Error when trying to execute aLeapp program getting file paths to search for result is %d", result));
+ return;
+ }
+
+ addILeappReportToReports(moduleOutputPath, currentCase);
+
+ } catch (IOException ex) {
+ logger.log(Level.SEVERE, String.format("Error when trying to execute aLeapp program against file system"), ex);
+ return;
+ }
+
+ if (context.dataSourceIngestIsCancelled()) {
+ logger.log(Level.INFO, "ILeapp Analyser ingest module run was canceled"); //NON-NLS
+ return;
+ }
+
+ ProcessResult fileProcessorResult = aLeappFileProcessor.processFileSystem(dataSource, moduleOutputPath);
+
+ if (fileProcessorResult == ProcessResult.ERROR) {
+ return;
+ }
+
+ }
+
+ /**
+ * Find the files that will be processed by the aLeapp program
+ *
+ * @param dataSource
+ *
+ * @return List of abstract files to process.
+ */
+ private List findaLeappFilesToProcess(Content dataSource) {
+
+ List aLeappFiles = new ArrayList<>();
+
+ FileManager fileManager = getCurrentCase().getServices().getFileManager();
+
+ // findFiles use the SQL wildcard % in the file name
+ try {
+ aLeappFiles = fileManager.findFiles(dataSource, "%", "/"); //NON-NLS
+ } catch (TskCoreException ex) {
+ logger.log(Level.WARNING, "No files found to process"); //NON-NLS
+ return aLeappFiles;
+ }
+
+ List aLeappFilesToProcess = new ArrayList<>();
+ for (AbstractFile aLeappFile : aLeappFiles) {
+ if (((aLeappFile.getLocalAbsPath() != null)
+ && (!aLeappFile.getNameExtension().isEmpty() && (!aLeappFile.isVirtual())))
+ && ((aLeappFile.getName().toLowerCase().contains(".zip") || (aLeappFile.getName().toLowerCase().contains(".tar")))
+ || aLeappFile.getName().toLowerCase().contains(".tgz"))) {
+ aLeappFilesToProcess.add(aLeappFile);
+
+ }
+ }
+
+ return aLeappFilesToProcess;
+ }
+
+ /**
+ * Build the aLeapp command to run
+ *
+ * @param moduleOutputPath output path for the aLeapp program.
+ * @param sourceFilePath where the source files to process reside.
+ * @param aLeappFileSystemType the filesystem type to process
+ *
+ * @return the command to execute
+ */
+ private ProcessBuilder buildaLeappCommand(Path moduleOutputPath, String sourceFilePath, String aLeappFileSystemType) {
+
+ ProcessBuilder processBuilder = buildProcessWithRunAsInvoker(
+ "\"" + aLeappExecutable + "\"", //NON-NLS
+ "-t", aLeappFileSystemType, //NON-NLS
+ "-i", sourceFilePath, //NON-NLS
+ "-o", moduleOutputPath.toString()
+ );
+ processBuilder.redirectError(moduleOutputPath.resolve("aLeapp_err.txt").toFile()); //NON-NLS
+ processBuilder.redirectOutput(moduleOutputPath.resolve("aLeapp_out.txt").toFile()); //NON-NLS
+ return processBuilder;
+ }
+
+ private ProcessBuilder buildaLeappListCommand(Path moduleOutputPath) {
+
+ ProcessBuilder processBuilder = buildProcessWithRunAsInvoker(
+ "\"" + aLeappExecutable + "\"", //NON-NLS
+ "-p"
+ );
+ processBuilder.redirectError(moduleOutputPath.resolve("aLeapp_paths_error.txt").toFile()); //NON-NLS
+ processBuilder.redirectOutput(moduleOutputPath.resolve("aLeapp_paths.txt").toFile()); //NON-NLS
+ return processBuilder;
+ }
+
+ static private ProcessBuilder buildProcessWithRunAsInvoker(String... commandLine) {
+ ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
+ /*
+ * Add an environment variable to force aLeapp to run with
+ * the same permissions Autopsy uses.
+ */
+ processBuilder.environment().put("__COMPAT_LAYER", "RunAsInvoker"); //NON-NLS
+ return processBuilder;
+ }
+
+ private static File locateExecutable(String executableName) throws FileNotFoundException {
+ String executableToFindName = Paths.get(ALEAPP, executableName).toString();
+
+ File exeFile = InstalledFileLocator.getDefault().locate(executableToFindName, ALeappAnalyzerIngestModule.class.getPackage().getName(), false);
+ if (null == exeFile || exeFile.canExecute() == false) {
+ throw new FileNotFoundException(executableName + " executable not found.");
+ }
+ return exeFile;
+ }
+
+ /**
+ * Find the index.html file in the aLeapp output directory so it can be
+ * added to reports
+ */
+ private void addILeappReportToReports(Path aLeappOutputDir, Case currentCase) {
+ List allIndexFiles = new ArrayList<>();
+
+ try (Stream walk = Files.walk(aLeappOutputDir)) {
+
+ allIndexFiles = walk.map(x -> x.toString())
+ .filter(f -> f.toLowerCase().endsWith("index.html")).collect(Collectors.toList());
+
+ if (!allIndexFiles.isEmpty()) {
+ // Check for existance of directory that holds report data if does not exist then report contains no data
+ String filePath = FilenameUtils.getFullPathNoEndSeparator(allIndexFiles.get(0));
+ File dataFilesDir = new File(Paths.get(filePath, "_TSV Exports").toString());
+ if (dataFilesDir.exists()) {
+ currentCase.addReport(allIndexFiles.get(0), MODULE_NAME, Bundle.ALeappAnalyzerIngestModule_report_name());
+ }
+ }
+
+ } catch (IOException | UncheckedIOException | TskCoreException ex) {
+ // catch the error and continue on as report is not added
+ logger.log(Level.WARNING, String.format("Error finding index file in path %s", aLeappOutputDir.toString()), ex);
+ }
+
+ }
+
+ /*
+ * Reads the aLeapp paths file to get the paths that we want to extract
+ *
+ */
+ private List loadIleappPathFile(Path moduleOutputPath) throws FileNotFoundException, IOException {
+ List aLeappPathsToProcess = new ArrayList<>();
+
+ Path filePath = Paths.get(moduleOutputPath.toString(), ALEAPP_PATHS_FILE);
+
+ try (BufferedReader reader = new BufferedReader(new FileReader(filePath.toString()))) {
+ String line = reader.readLine();
+ while (line != null) {
+ if (line.contains("path list generation") || line.length() < 2) {
+ line = reader.readLine();
+ continue;
+ }
+ aLeappPathsToProcess.add(line.trim());
+ line = reader.readLine();
+ }
+ }
+
+ return aLeappPathsToProcess;
+ }
+
+ private void extractFilesFromImage(Content dataSource, List aLeappPathsToProcess, Path moduleOutputPath) {
+ FileManager fileManager = getCurrentCase().getServices().getFileManager();
+
+ for (String fullFilePath : aLeappPathsToProcess) {
+
+ if (context.dataSourceIngestIsCancelled()) {
+ logger.log(Level.INFO, "aLeapp Analyser ingest module run was canceled"); //NON-NLS
+ break;
+ }
+
+ String ffp = fullFilePath.replaceAll("\\*", "%");
+ ffp = FilenameUtils.normalize(ffp, true);
+ String fileName = FilenameUtils.getName(ffp);
+ String filePath = FilenameUtils.getPath(ffp);
+
+ List aLeappFiles = new ArrayList<>();
+ try {
+ if (filePath.isEmpty()) {
+ aLeappFiles = fileManager.findFiles(dataSource, fileName); //NON-NLS
+ } else {
+ aLeappFiles = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS
+ }
+ } catch (TskCoreException ex) {
+ logger.log(Level.WARNING, "No files found to process"); //NON-NLS
+ return;
+ }
+
+ for (AbstractFile aLeappFile : aLeappFiles) {
+ Path parentPath = Paths.get(moduleOutputPath.toString(), aLeappFile.getParentPath());
+ File fileParentPath = new File(parentPath.toString());
+
+ extractFileToOutput(dataSource, aLeappFile, fileParentPath, parentPath);
+ }
+ }
+ }
+
+ private void extractFileToOutput(Content dataSource, AbstractFile aLeappFile, File fileParentPath, Path parentPath) {
+ if (fileParentPath.exists()) {
+ if (!aLeappFile.isDir()) {
+ writeaLeappFile(dataSource, aLeappFile, fileParentPath.toString());
+ } else {
+ try {
+ Files.createDirectories(Paths.get(parentPath.toString(), aLeappFile.getName()));
+ } catch (IOException ex) {
+ logger.log(Level.INFO, String.format("Error creating aLeapp output directory %s", parentPath.toString()), ex);
+ }
+ }
+ } else {
+ try {
+ Files.createDirectories(parentPath);
+ } catch (IOException ex) {
+ logger.log(Level.INFO, String.format("Error creating aLeapp output directory %s", parentPath.toString()), ex);
+ }
+ if (!aLeappFile.isDir()) {
+ writeaLeappFile(dataSource, aLeappFile, fileParentPath.toString());
+ } else {
+ try {
+ Files.createDirectories(Paths.get(parentPath.toString(), aLeappFile.getName()));
+ } catch (IOException ex) {
+ logger.log(Level.INFO, String.format("Error creating aLeapp output directory %s", parentPath.toString()), ex);
+ }
+ }
+ }
+ }
+
+ private void writeaLeappFile(Content dataSource, AbstractFile aLeappFile, String parentPath) {
+ String fileName = aLeappFile.getName().replace(":", "-");
+ if (!fileName.matches(".") && !fileName.matches("..") && !fileName.toLowerCase().endsWith("-slack")) {
+ Path filePath = Paths.get(parentPath, fileName);
+ File localFile = new File(filePath.toString());
+ try {
+ ContentUtils.writeToFile(aLeappFile, localFile, context::dataSourceIngestIsCancelled);
+ } catch (ReadContentInputStream.ReadContentInputStreamException ex) {
+ logger.log(Level.WARNING, String.format("Error reading file '%s' (id=%d).",
+ aLeappFile.getName(), aLeappFile.getId()), ex); //NON-NLS
+ } catch (IOException ex) {
+ logger.log(Level.WARNING, String.format("Error writing file local file '%s' (id=%d).",
+ filePath.toString(), aLeappFile.getId()), ex); //NON-NLS
+ }
+ }
+ }
+}
diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ALeappAnalyzerModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ALeappAnalyzerModuleFactory.java
new file mode 100644
index 0000000000..2e4066d874
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ALeappAnalyzerModuleFactory.java
@@ -0,0 +1,67 @@
+/*
+ * Autopsy Forensic Browser
+ *
+ * Copyright 2020 Basis Technology Corp.
+ * Contact: carrier sleuthkit org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.sleuthkit.autopsy.modules.leappanalyzers;
+
+import org.openide.util.NbBundle;
+import org.openide.util.lookup.ServiceProvider;
+import org.sleuthkit.autopsy.coreutils.Version;
+import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
+import org.sleuthkit.autopsy.ingest.IngestModuleFactory;
+import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter;
+import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
+
+/**
+ * A factory that creates data source ingest modules that will run aLeapp
+ * against logical files and saves the output to module output.
+ */
+@ServiceProvider(service = IngestModuleFactory.class)
+public class ALeappAnalyzerModuleFactory extends IngestModuleFactoryAdapter {
+
+ @NbBundle.Messages({"ALeappAnalyzerModuleFactory_moduleName=Android Analyzer (aLEAPP)"})
+ static String getModuleName() {
+ return Bundle.ALeappAnalyzerModuleFactory_moduleName();
+ }
+
+ @Override
+ public String getModuleDisplayName() {
+ return getModuleName();
+ }
+
+ @NbBundle.Messages({"ALeappAnalyzerModuleFactory_moduleDesc=Uses aLEAPP to analyze logical acquisitions of Android devices."})
+ @Override
+ public String getModuleDescription() {
+ return Bundle.ALeappAnalyzerModuleFactory_moduleDesc();
+ }
+
+ @Override
+ public String getModuleVersionNumber() {
+ return Version.getVersion();
+ }
+
+ @Override
+ public boolean isDataSourceIngestModuleFactory() {
+ return true;
+ }
+
+ @Override
+ public DataSourceIngestModule createDataSourceIngestModule(IngestModuleIngestJobSettings ingestJobOptions) {
+ return new ALeappAnalyzerIngestModule();
+ }
+
+}
diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle.properties
new file mode 100644
index 0000000000..4236fad631
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle.properties
@@ -0,0 +1,8 @@
+ILeappAnalyzerIngestModule.init.exception.msg=Unable to find {0}.
+ILeappAnalyzerIngestModule.processing.file=Processing file {0}
+ILeappAnalyzerIngestModule.parsing.file=Parsing file {0}
+ILeappAnalyzerIngestModule.processing.filesystem=Processing filesystem
+ALeappAnalyzerIngestModule.init.exception.msg=Unable to find {0}.
+ALeappAnalyzerIngestModule.processing.file=Processing file {0}
+ALeappAnalyzerIngestModule.parsing.file=Parsing file {0}
+ALeappAnalyzerIngestModule.processing.filesystem=Processing filesystem
\ No newline at end of file
diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle.properties-MERGED
new file mode 100644
index 0000000000..b23a428107
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/Bundle.properties-MERGED
@@ -0,0 +1,47 @@
+ALeappAnalyzerIngestModule.aLeapp.cancelled=aLeapp run was canceled
+ALeappAnalyzerIngestModule.completed=aLeapp Processing Completed
+ALeappAnalyzerIngestModule.error.creating.output.dir=Error creating aLeapp module output directory.
+ALeappAnalyzerIngestModule.error.ileapp.file.processor.init=Failure to initialize aLeappProcessFile
+ALeappAnalyzerIngestModule.error.running.aLeapp=Error running aLeapp, see log file.
+ALeappAnalyzerIngestModule.executable.not.found=aLeapp Executable Not Found.
+ALeappAnalyzerIngestModule.has.run=aLeapp
+ALeappAnalyzerIngestModule.report.name=aLeapp Html Report
+ALeappAnalyzerIngestModule.requires.windows=aLeapp module requires windows.
+ALeappAnalyzerIngestModule.running.aLeapp=Running aLeapp
+ALeappAnalyzerIngestModule.starting.aLeapp=Starting aLeapp
+ALeappAnalyzerModuleFactory_moduleDesc=Uses aLEAPP to analyze logical acquisitions of Android devices.
+ALeappAnalyzerModuleFactory_moduleName=Android Analyzer (aLEAPP)
+ILeappAnalyzerIngestModule.completed=iLeapp Processing Completed
+ILeappAnalyzerIngestModule.error.creating.output.dir=Error creating iLeapp module output directory.
+ILeappAnalyzerIngestModule.error.ileapp.file.processor.init=Failure to initialize ILeappProcessFile
+ILeappAnalyzerIngestModule.error.running.iLeapp=Error running iLeapp, see log file.
+ILeappAnalyzerIngestModule.executable.not.found=iLeapp Executable Not Found.
+ILeappAnalyzerIngestModule.has.run=iLeapp
+ILeappAnalyzerIngestModule.iLeapp.cancelled=iLeapp run was canceled
+ILeappAnalyzerIngestModule.init.exception.msg=Unable to find {0}.
+ILeappAnalyzerIngestModule.processing.file=Processing file {0}
+ILeappAnalyzerIngestModule.parsing.file=Parsing file {0}
+ILeappAnalyzerIngestModule.processing.filesystem=Processing filesystem
+ALeappAnalyzerIngestModule.init.exception.msg=Unable to find {0}.
+ALeappAnalyzerIngestModule.processing.file=Processing file {0}
+ALeappAnalyzerIngestModule.parsing.file=Parsing file {0}
+ALeappAnalyzerIngestModule.processing.filesystem=Processing filesystem
+ILeappAnalyzerIngestModule.report.name=iLeapp Html Report
+ILeappAnalyzerIngestModule.requires.windows=iLeapp module requires windows.
+ILeappAnalyzerIngestModule.running.iLeapp=Running iLeapp
+ILeappAnalyzerIngestModule.starting.iLeapp=Starting iLeapp
+ILeappAnalyzerModuleFactory_moduleDesc=Uses iLEAPP to analyze logical acquisitions of iOS devices.
+ILeappAnalyzerModuleFactory_moduleName=iOS Analyzer (iLEAPP)
+LeappFileProcessor.cannot.load.artifact.xml=Cannor load xml artifact file.
+LeappFileProcessor.cannotBuildXmlParser=Cannot buld an XML parser.
+LeappFileProcessor.completed=Leapp Processing Completed
+LeappFileProcessor.error.creating.new.artifacts=Error creating new artifacts.
+LeappFileProcessor.error.creating.output.dir=Error creating Leapp module output directory.
+LeappFileProcessor.error.reading.Leapp.directory=Error reading Leapp Output Directory
+LeappFileProcessor.error.running.Leapp=Error running Leapp, see log file.
+LeappFileProcessor.has.run=Leapp
+LeappFileProcessor.Leapp.cancelled=Leapp run was canceled
+LeappFileProcessor.postartifacts_error=Error posting Blackboard Artifact
+LeappFileProcessor.running.Leapp=Running Leapp
+LeappFileProcessor.starting.Leapp=Starting Leapp
+LeappFileProcessor_cannotParseXml=Cannot Parse XML file.
diff --git a/Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/ILeappAnalyzerIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ILeappAnalyzerIngestModule.java
similarity index 98%
rename from Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/ILeappAnalyzerIngestModule.java
rename to Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ILeappAnalyzerIngestModule.java
index abec90e6c0..e583064978 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/ILeappAnalyzerIngestModule.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ILeappAnalyzerIngestModule.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.modules.ileappanalyzer;
+package org.sleuthkit.autopsy.modules.leappanalyzers;
import java.io.BufferedReader;
import java.io.File;
@@ -71,11 +71,14 @@ public class ILeappAnalyzerIngestModule implements DataSourceIngestModule {
private static final String ILEAPP_EXECUTABLE = "ileapp.exe";//NON-NLS
private static final String ILEAPP_PATHS_FILE = "iLeapp_paths.txt"; //NON-NLS
+ private static final String XMLFILE = "ileap-artifact-attribute-reference.xml"; //NON-NLS
+
+
private File iLeappExecutable;
private IngestJobContext context;
- private ILeappFileProcessor iLeappFileProcessor;
+ private LeappFileProcessor iLeappFileProcessor;
ILeappAnalyzerIngestModule() {
// This constructor is intentionally empty. Nothing special is needed here.
@@ -94,7 +97,7 @@ public class ILeappAnalyzerIngestModule implements DataSourceIngestModule {
}
try {
- iLeappFileProcessor = new ILeappFileProcessor();
+ iLeappFileProcessor = new LeappFileProcessor(XMLFILE);
} catch (IOException | IngestModuleException | NoCurrentCaseException ex) {
throw new IngestModuleException(Bundle.ILeappAnalyzerIngestModule_error_ileapp_file_processor_init(), ex);
}
diff --git a/Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/ILeappAnalyzerModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ILeappAnalyzerModuleFactory.java
similarity index 97%
rename from Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/ILeappAnalyzerModuleFactory.java
rename to Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ILeappAnalyzerModuleFactory.java
index 166c455d55..167afee3a0 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/ILeappAnalyzerModuleFactory.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ILeappAnalyzerModuleFactory.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.modules.ileappanalyzer;
+package org.sleuthkit.autopsy.modules.leappanalyzers;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;
diff --git a/Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/ILeappFileProcessor.java b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/LeappFileProcessor.java
similarity index 79%
rename from Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/ILeappFileProcessor.java
rename to Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/LeappFileProcessor.java
index 058b0aa28d..93e99edba3 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/ILeappFileProcessor.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/LeappFileProcessor.java
@@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.sleuthkit.autopsy.modules.ileappanalyzer;
+package org.sleuthkit.autopsy.modules.leappanalyzers;
import java.io.BufferedReader;
import java.io.File;
@@ -63,14 +63,14 @@ import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
- * Find and process output from iLeapp program and bring into Autopsy
+ * Find and process output from Leapp program and bring into Autopsy
*/
-public final class ILeappFileProcessor {
+public final class LeappFileProcessor {
- private static final Logger logger = Logger.getLogger(ILeappFileProcessor.class.getName());
+ private static final Logger logger = Logger.getLogger(LeappFileProcessor.class.getName());
private static final String MODULE_NAME = ILeappAnalyzerModuleFactory.getModuleName();
- private static final String XMLFILE = "ileap-artifact-attribute-reference.xml"; //NON-NLS
+ private final String xmlFile; //NON-NLS
private final Map tsvFiles;
private final Map tsvFileArtifacts;
@@ -79,11 +79,12 @@ public final class ILeappFileProcessor {
Blackboard blkBoard;
- public ILeappFileProcessor() throws IOException, IngestModuleException, NoCurrentCaseException {
+ public LeappFileProcessor(String xmlFile) throws IOException, IngestModuleException, NoCurrentCaseException {
this.tsvFiles = new HashMap<>();
this.tsvFileArtifacts = new HashMap<>();
this.tsvFileArtifactComments = new HashMap<>();
this.tsvFileAttributes = new HashMap<>();
+ this.xmlFile = xmlFile;
blkBoard = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard();
@@ -93,22 +94,22 @@ public final class ILeappFileProcessor {
}
@NbBundle.Messages({
- "ILeappFileProcessor.error.running.iLeapp=Error running iLeapp, see log file.",
- "ILeappFileProcessor.error.creating.output.dir=Error creating iLeapp module output directory.",
- "ILeappFileProcessor.starting.iLeapp=Starting iLeapp",
- "ILeappFileProcessor.running.iLeapp=Running iLeapp",
- "ILeappFileProcessor.has.run=iLeapp",
- "ILeappFileProcessor.iLeapp.cancelled=iLeapp run was canceled",
- "ILeappFileProcessor.completed=iLeapp Processing Completed",
- "ILeappFileProcessor.error.reading.iLeapp.directory=Error reading iLeapp Output Directory"})
+ "LeappFileProcessor.error.running.Leapp=Error running Leapp, see log file.",
+ "LeappFileProcessor.error.creating.output.dir=Error creating Leapp module output directory.",
+ "LeappFileProcessor.starting.Leapp=Starting Leapp",
+ "LeappFileProcessor.running.Leapp=Running Leapp",
+ "LeappFileProcessor.has.run=Leapp",
+ "LeappFileProcessor.Leapp.cancelled=Leapp run was canceled",
+ "LeappFileProcessor.completed=Leapp Processing Completed",
+ "LeappFileProcessor.error.reading.Leapp.directory=Error reading Leapp Output Directory"})
- public ProcessResult processFiles(Content dataSource, Path moduleOutputPath, AbstractFile iLeappFile) {
+ public ProcessResult processFiles(Content dataSource, Path moduleOutputPath, AbstractFile LeappFile) {
try {
- List iLeappTsvOutputFiles = findTsvFiles(moduleOutputPath);
- processiLeappFiles(iLeappTsvOutputFiles, iLeappFile);
+ List LeappTsvOutputFiles = findTsvFiles(moduleOutputPath);
+ processLeappFiles(LeappTsvOutputFiles, LeappFile);
} catch (IOException | IngestModuleException ex) {
- logger.log(Level.SEVERE, String.format("Error trying to process iLeapp output files in directory %s. ", moduleOutputPath.toString()), ex); //NON-NLS
+ logger.log(Level.SEVERE, String.format("Error trying to process Leapp output files in directory %s. ", moduleOutputPath.toString()), ex); //NON-NLS
return ProcessResult.ERROR;
}
@@ -118,10 +119,10 @@ public final class ILeappFileProcessor {
public ProcessResult processFileSystem(Content dataSource, Path moduleOutputPath) {
try {
- List iLeappTsvOutputFiles = findTsvFiles(moduleOutputPath);
- processiLeappFiles(iLeappTsvOutputFiles, dataSource);
+ List LeappTsvOutputFiles = findTsvFiles(moduleOutputPath);
+ processLeappFiles(LeappTsvOutputFiles, dataSource);
} catch (IOException | IngestModuleException ex) {
- logger.log(Level.SEVERE, String.format("Error trying to process iLeapp output files in directory %s. ", moduleOutputPath.toString()), ex); //NON-NLS
+ logger.log(Level.SEVERE, String.format("Error trying to process Leapp output files in directory %s. ", moduleOutputPath.toString()), ex); //NON-NLS
return ProcessResult.ERROR;
}
@@ -129,14 +130,14 @@ public final class ILeappFileProcessor {
}
/**
- * Find the tsv files in the iLeapp output directory and match them to files
+ * Find the tsv files in the Leapp output directory and match them to files
* we know we want to process and return the list to process those files.
*/
- private List findTsvFiles(Path iLeappOutputDir) throws IngestModuleException {
+ private List findTsvFiles(Path LeappOutputDir) throws IngestModuleException {
List allTsvFiles = new ArrayList<>();
List foundTsvFiles = new ArrayList<>();
- try (Stream walk = Files.walk(iLeappOutputDir)) {
+ try (Stream walk = Files.walk(LeappOutputDir)) {
allTsvFiles = walk.map(x -> x.toString())
.filter(f -> f.toLowerCase().endsWith(".tsv")).collect(Collectors.toList());
@@ -148,7 +149,7 @@ public final class ILeappFileProcessor {
}
} catch (IOException | UncheckedIOException e) {
- throw new IngestModuleException(Bundle.ILeappFileProcessor_error_reading_iLeapp_directory() + iLeappOutputDir.toString(), e);
+ throw new IngestModuleException(Bundle.LeappFileProcessor_error_reading_Leapp_directory() + LeappOutputDir.toString(), e);
}
return foundTsvFiles;
@@ -156,26 +157,26 @@ public final class ILeappFileProcessor {
}
/**
- * Process the iLeapp files that were found that match the xml mapping file
+ * Process the Leapp files that were found that match the xml mapping file
*
- * @param iLeappFilesToProcess List of files to process
- * @param iLeappImageFile Abstract file to create artifact for
+ * @param LeappFilesToProcess List of files to process
+ * @param LeappImageFile Abstract file to create artifact for
*
* @throws FileNotFoundException
* @throws IOException
*/
- private void processiLeappFiles(List iLeappFilesToProcess, AbstractFile iLeappImageFile) throws FileNotFoundException, IOException, IngestModuleException {
+ private void processLeappFiles(List LeappFilesToProcess, AbstractFile LeappImageFile) throws FileNotFoundException, IOException, IngestModuleException {
List bbartifacts = new ArrayList<>();
- for (String iLeappFileName : iLeappFilesToProcess) {
- String fileName = FilenameUtils.getName(iLeappFileName);
- File iLeappFile = new File(iLeappFileName);
+ for (String LeappFileName : LeappFilesToProcess) {
+ String fileName = FilenameUtils.getName(LeappFileName);
+ File LeappFile = new File(LeappFileName);
if (tsvFileAttributes.containsKey(fileName)) {
List> attrList = tsvFileAttributes.get(fileName);
try {
BlackboardArtifact.Type artifactType = Case.getCurrentCase().getSleuthkitCase().getArtifactType(tsvFileArtifacts.get(fileName));
- processFile(iLeappFile, attrList, fileName, artifactType, bbartifacts, iLeappImageFile);
+ processFile(LeappFile, attrList, fileName, artifactType, bbartifacts, LeappImageFile);
} catch (TskCoreException ex) {
throw new IngestModuleException(String.format("Error getting Blackboard Artifact Type for %s", tsvFileArtifacts.get(fileName)), ex);
@@ -191,26 +192,26 @@ public final class ILeappFileProcessor {
}
/**
- * Process the iLeapp files that were found that match the xml mapping file
+ * Process the Leapp files that were found that match the xml mapping file
*
- * @param iLeappFilesToProcess List of files to process
- * @param iLeappImageFile Abstract file to create artifact for
+ * @param LeappFilesToProcess List of files to process
+ * @param LeappImageFile Abstract file to create artifact for
*
* @throws FileNotFoundException
* @throws IOException
*/
- private void processiLeappFiles(List iLeappFilesToProcess, Content dataSource) throws FileNotFoundException, IOException, IngestModuleException {
+ private void processLeappFiles(List LeappFilesToProcess, Content dataSource) throws FileNotFoundException, IOException, IngestModuleException {
List bbartifacts = new ArrayList<>();
- for (String iLeappFileName : iLeappFilesToProcess) {
- String fileName = FilenameUtils.getName(iLeappFileName);
- File iLeappFile = new File(iLeappFileName);
+ for (String LeappFileName : LeappFilesToProcess) {
+ String fileName = FilenameUtils.getName(LeappFileName);
+ File LeappFile = new File(LeappFileName);
if (tsvFileAttributes.containsKey(fileName)) {
List> attrList = tsvFileAttributes.get(fileName);
try {
BlackboardArtifact.Type artifactType = Case.getCurrentCase().getSleuthkitCase().getArtifactType(tsvFileArtifacts.get(fileName));
- processFile(iLeappFile, attrList, fileName, artifactType, bbartifacts, dataSource);
+ processFile(LeappFile, attrList, fileName, artifactType, bbartifacts, dataSource);
} catch (TskCoreException ex) {
throw new IngestModuleException(String.format("Error getting Blackboard Artifact Type for %s", tsvFileArtifacts.get(fileName)), ex);
@@ -225,10 +226,10 @@ public final class ILeappFileProcessor {
}
- private void processFile(File iLeappFile, List> attrList, String fileName, BlackboardArtifact.Type artifactType,
+ private void processFile(File LeappFile, List> attrList, String fileName, BlackboardArtifact.Type artifactType,
List bbartifacts, Content dataSource) throws FileNotFoundException, IOException, IngestModuleException,
TskCoreException {
- try (BufferedReader reader = new BufferedReader(new FileReader(iLeappFile))) {
+ try (BufferedReader reader = new BufferedReader(new FileReader(LeappFile))) {
String line = reader.readLine();
// Check first line, if it is null then no heading so nothing to match to, close and go to next file.
if (line != null) {
@@ -236,6 +237,10 @@ public final class ILeappFileProcessor {
line = reader.readLine();
while (line != null) {
Collection bbattributes = processReadLine(line, columnNumberToProcess, fileName);
+ if (artifactType == null) {
+ logger.log(Level.SEVERE, "Error trying to process Leapp output files in directory . "); //NON-NLS
+
+ }
if (!bbattributes.isEmpty() && !blkBoard.artifactExists(dataSource, BlackboardArtifact.ARTIFACT_TYPE.fromID(artifactType.getTypeID()), bbattributes)) {
BlackboardArtifact bbartifact = createArtifactWithAttributes(artifactType.getTypeID(), dataSource, bbattributes);
if (bbartifact != null) {
@@ -354,11 +359,11 @@ public final class ILeappFileProcessor {
}
@NbBundle.Messages({
- "ILeappFileProcessor.cannot.load.artifact.xml=Cannor load xml artifact file.",
- "ILeappFileProcessor.cannotBuildXmlParser=Cannot buld an XML parser.",
- "ILeappFileProcessor_cannotParseXml=Cannot Parse XML file.",
- "ILeappFileProcessor.postartifacts_error=Error posting Blackboard Artifact",
- "ILeappFileProcessor.error.creating.new.artifacts=Error creating new artifacts."
+ "LeappFileProcessor.cannot.load.artifact.xml=Cannor load xml artifact file.",
+ "LeappFileProcessor.cannotBuildXmlParser=Cannot buld an XML parser.",
+ "LeappFileProcessor_cannotParseXml=Cannot Parse XML file.",
+ "LeappFileProcessor.postartifacts_error=Error posting Blackboard Artifact",
+ "LeappFileProcessor.error.creating.new.artifacts=Error creating new artifacts."
})
/**
@@ -367,18 +372,18 @@ public final class ILeappFileProcessor {
private void loadConfigFile() throws IngestModuleException {
Document xmlinput;
try {
- String path = PlatformUtil.getUserConfigDirectory() + File.separator + XMLFILE;
+ String path = PlatformUtil.getUserConfigDirectory() + File.separator + xmlFile;
File f = new File(path);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
xmlinput = db.parse(f);
} catch (IOException e) {
- throw new IngestModuleException(Bundle.ILeappFileProcessor_cannot_load_artifact_xml() + e.getLocalizedMessage(), e); //NON-NLS
+ throw new IngestModuleException(Bundle.LeappFileProcessor_cannot_load_artifact_xml() + e.getLocalizedMessage(), e); //NON-NLS
} catch (ParserConfigurationException pce) {
- throw new IngestModuleException(Bundle.ILeappFileProcessor_cannotBuildXmlParser() + pce.getLocalizedMessage(), pce); //NON-NLS
+ throw new IngestModuleException(Bundle.LeappFileProcessor_cannotBuildXmlParser() + pce.getLocalizedMessage(), pce); //NON-NLS
} catch (SAXException sxe) {
- throw new IngestModuleException(Bundle.ILeappFileProcessor_cannotParseXml() + sxe.getLocalizedMessage(), sxe); //NON-NLS
+ throw new IngestModuleException(Bundle.LeappFileProcessor_cannotParseXml() + sxe.getLocalizedMessage(), sxe); //NON-NLS
}
getFileNode(xmlinput);
@@ -466,7 +471,7 @@ public final class ILeappFileProcessor {
bbart.addAttributes(bbattributes);
return bbart;
} catch (TskException ex) {
- logger.log(Level.WARNING, Bundle.ILeappFileProcessor_error_creating_new_artifacts(), ex); //NON-NLS
+ logger.log(Level.WARNING, Bundle.LeappFileProcessor_error_creating_new_artifacts(), ex); //NON-NLS
}
return null;
}
@@ -490,7 +495,7 @@ public final class ILeappFileProcessor {
bbart.addAttributes(bbattributes);
return bbart;
} catch (TskException ex) {
- logger.log(Level.WARNING, Bundle.ILeappFileProcessor_error_creating_new_artifacts(), ex); //NON-NLS
+ logger.log(Level.WARNING, Bundle.LeappFileProcessor_error_creating_new_artifacts(), ex); //NON-NLS
}
return null;
}
@@ -509,17 +514,17 @@ public final class ILeappFileProcessor {
try {
Case.getCurrentCase().getSleuthkitCase().getBlackboard().postArtifacts(artifacts, MODULE_NAME);
} catch (Blackboard.BlackboardException ex) {
- logger.log(Level.SEVERE, Bundle.ILeappFileProcessor_postartifacts_error(), ex); //NON-NLS
+ logger.log(Level.SEVERE, Bundle.LeappFileProcessor_postartifacts_error(), ex); //NON-NLS
}
}
/**
- * Extract the iLeapp config xml file to the user directory to process
+ * Extract the Leapp config xml file to the user directory to process
*
* @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException
*/
private void configExtractor() throws IOException {
- PlatformUtil.extractResourceToUserConfigDir(ILeappFileProcessor.class, XMLFILE, true);
+ PlatformUtil.extractResourceToUserConfigDir(LeappFileProcessor.class, xmlFile, true);
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/aleap-artifact-attribute-reference.xml b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/aleap-artifact-attribute-reference.xml
new file mode 100644
index 0000000000..b11fbd3714
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/aleap-artifact-attribute-reference.xml
@@ -0,0 +1,307 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/ileap-artifact-attribute-reference.xml b/Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ileap-artifact-attribute-reference.xml
similarity index 100%
rename from Core/src/org/sleuthkit/autopsy/modules/ileappanalyzer/ileap-artifact-attribute-reference.xml
rename to Core/src/org/sleuthkit/autopsy/modules/leappanalyzers/ileap-artifact-attribute-reference.xml
diff --git a/thirdparty/aLeapp/LICENSE b/thirdparty/aLeapp/LICENSE
new file mode 100644
index 0000000000..ae8fc549fc
--- /dev/null
+++ b/thirdparty/aLeapp/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Brigs
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/thirdparty/aLeapp/aleapp.exe b/thirdparty/aLeapp/aleapp.exe
new file mode 100644
index 0000000000..7ed46c4689
Binary files /dev/null and b/thirdparty/aLeapp/aleapp.exe differ