19 package org.sleuthkit.autopsy.modules.leappanalyzers;
21 import java.io.BufferedReader;
23 import java.io.FileNotFoundException;
24 import java.io.FileReader;
25 import java.io.IOException;
26 import java.io.UncheckedIOException;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.nio.file.Paths;
30 import java.text.SimpleDateFormat;
31 import java.util.List;
32 import java.util.ArrayList;
33 import java.util.Locale;
34 import java.util.logging.Level;
35 import java.util.stream.Collectors;
36 import java.util.stream.Stream;
37 import org.apache.commons.io.FilenameUtils;
38 import org.openide.modules.InstalledFileLocator;
39 import org.openide.util.NbBundle;
69 private static final String
ALEAPP =
"aLeapp";
74 private static final String
XMLFILE =
"aleapp-artifact-attribute-reference.xml";
87 "ALeappAnalyzerIngestModule.executable.not.found=aLeapp Executable Not Found.",
88 "ALeappAnalyzerIngestModule.requires.windows=aLeapp module requires windows.",
89 "ALeappAnalyzerIngestModule.error.aleapp.file.processor.init=Failure to initialize aLeappProcessFile"})
95 throw new IngestModuleException(NbBundle.getMessage(
this.getClass(),
"AleappAnalyzerIngestModule.not.64.bit.os"));
105 throw new IngestModuleException(Bundle.ALeappAnalyzerIngestModule_error_aleapp_file_processor_init(), ex);
110 }
catch (FileNotFoundException exception) {
111 logger.log(Level.WARNING,
"aLeapp executable not found.", exception);
112 throw new IngestModuleException(Bundle.ALeappAnalyzerIngestModule_executable_not_found(), exception);
118 "ALeappAnalyzerIngestModule.error.running.aLeapp=Error running aLeapp, see log file.",
119 "ALeappAnalyzerIngestModule.error.creating.output.dir=Error creating aLeapp module output directory.",
120 "ALeappAnalyzerIngestModule.running.aLeapp=Running aLeapp",
121 "ALeappAnalyzerIngestModule_processing_aLeapp_results=Processing aLeapp results",
122 "ALeappAnalyzerIngestModule.has.run=aLeapp",
123 "ALeappAnalyzerIngestModule.aLeapp.cancelled=aLeapp run was canceled",
124 "ALeappAnalyzerIngestModule.completed=aLeapp Processing Completed",
125 "ALeappAnalyzerIngestModule.report.name=aLeapp Html Report"})
130 statusHelper.
progress(Bundle.ALeappAnalyzerIngestModule_running_aLeapp());
135 Files.createDirectories(tempOutputPath);
136 }
catch (IOException ex) {
137 logger.log(Level.SEVERE, String.format(
"Error creating aLeapp output directory %s", tempOutputPath.toString()), ex);
142 List<String> aLeappPathsToProcess;
147 logger.log(Level.SEVERE, String.format(
"Error when trying to execute aLeapp program getting file paths to search for result is %d", result));
152 if (aLeappPathsToProcess.isEmpty()) {
153 logger.log(Level.SEVERE, String.format(
"Error getting file paths to search, list is empty"));
157 }
catch (IOException ex) {
158 logger.log(Level.SEVERE, String.format(
"Error when trying to execute aLeapp program getting file paths to search"), ex);
163 if ((context.
getDataSource() instanceof LocalFilesDataSource)) {
169 List<AbstractFile> aLeappFilesToProcess =
LeappFileProcessor.findLeappFilesToProcess(dataSource);
170 if (!aLeappFilesToProcess.isEmpty()) {
172 Integer filesProcessedCount = 0;
173 for (AbstractFile aLeappFile : aLeappFilesToProcess) {
174 processALeappFile(dataSource, currentCase, statusHelper, filesProcessedCount, aLeappFile);
175 filesProcessedCount++;
181 statusHelper.
progress(Bundle.ALeappAnalyzerIngestModule_processing_aLeapp_results());
183 processALeappFs(dataSource, currentCase, statusHelper, tempOutputPath.toString());
186 Bundle.ALeappAnalyzerIngestModule_has_run(),
187 Bundle.ALeappAnalyzerIngestModule_completed());
203 AbstractFile aLeappFile) {
204 statusHelper.
progress(NbBundle.getMessage(
this.getClass(),
"ALeappAnalyzerIngestModule.processing.file", aLeappFile.getName()), filesProcessedCount);
205 String currentTime =
new SimpleDateFormat(
"yyyy-MM-dd HH-mm-ss z", Locale.US).format(System.currentTimeMillis());
208 Files.createDirectories(moduleOutputPath);
209 }
catch (IOException ex) {
210 logger.log(Level.SEVERE, String.format(
"Error creating aLeapp output directory %s", moduleOutputPath.toString()), ex);
214 ProcessBuilder aLeappCommand =
buildaLeappCommand(moduleOutputPath, aLeappFile.getLocalAbsPath(), aLeappFile.getNameExtension());
218 logger.log(Level.WARNING, String.format(
"Error when trying to execute aLeapp program getting file paths to search for result is %d", result));
224 }
catch (IOException ex) {
225 logger.log(Level.SEVERE, String.format(
"Error when trying to execute aLeapp program against file %s", aLeappFile.getLocalAbsPath()), ex);
230 logger.log(Level.INFO,
"aLeapp Analyser ingest module run was canceled");
234 aLeappFileProcessor.
processFiles(dataSource, moduleOutputPath, aLeappFile, statusHelper);
247 statusHelper.
progress(NbBundle.getMessage(
this.getClass(),
"ALeappAnalyzerIngestModule.processing.filesystem"));
248 String currentTime =
new SimpleDateFormat(
"yyyy-MM-dd HH-mm-ss z", Locale.US).format(System.currentTimeMillis());
251 Files.createDirectories(moduleOutputPath);
252 }
catch (IOException ex) {
253 logger.log(Level.SEVERE, String.format(
"Error creating aLeapp output directory %s", moduleOutputPath.toString()), ex);
257 ProcessBuilder aLeappCommand =
buildaLeappCommand(moduleOutputPath, directoryToProcess,
"fs");
261 logger.log(Level.WARNING, String.format(
"Error when trying to execute aLeapp program getting file paths to search for result is %d", result));
267 }
catch (IOException ex) {
268 logger.log(Level.SEVERE, String.format(
"Error when trying to execute aLeapp program against file system"), ex);
273 logger.log(Level.INFO,
"aLeapp Analyser ingest module run was canceled");
277 aLeappFileProcessor.
processFileSystem(dataSource, moduleOutputPath, statusHelper);
289 private ProcessBuilder
buildaLeappCommand(Path moduleOutputPath, String sourceFilePath, String aLeappFileSystemType) {
292 aLeappExecutable.getAbsolutePath(),
293 "-t", aLeappFileSystemType,
294 "-i", sourceFilePath,
295 "-o", moduleOutputPath.toString(),
298 processBuilder.directory(moduleOutputPath.toFile());
299 processBuilder.redirectError(moduleOutputPath.resolve(
"aLeapp_err.txt").toFile());
300 processBuilder.redirectOutput(moduleOutputPath.resolve(
"aLeapp_out.txt").toFile());
301 return processBuilder;
307 aLeappExecutable.getAbsolutePath(),
311 processBuilder.directory(moduleOutputPath.toFile());
312 processBuilder.redirectError(moduleOutputPath.resolve(
"aLeapp_paths_error.txt").toFile());
313 processBuilder.redirectOutput(moduleOutputPath.resolve(
"aLeapp_paths.txt").toFile());
314 return processBuilder;
318 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
323 processBuilder.environment().put(
"__COMPAT_LAYER",
"RunAsInvoker");
324 return processBuilder;
328 String executableToFindName = Paths.get(ALEAPP, executableName).toString();
330 File exeFile = InstalledFileLocator.getDefault().locate(executableToFindName,
ALeappAnalyzerIngestModule.class.getPackage().getName(),
false);
331 if (null == exeFile || exeFile.canExecute() ==
false) {
332 throw new FileNotFoundException(executableName +
" executable not found.");
342 List<String> allIndexFiles =
new ArrayList<>();
344 try (Stream<Path> walk = Files.walk(aLeappOutputDir)) {
346 allIndexFiles = walk.map(x -> x.toString())
347 .filter(f -> f.toLowerCase().endsWith(
"index.html")).collect(Collectors.toList());
349 if (!allIndexFiles.isEmpty()) {
351 String filePath = FilenameUtils.getFullPathNoEndSeparator(allIndexFiles.get(0));
352 File dataFilesDir =
new File(Paths.get(filePath,
"_TSV Exports").toString());
353 if (dataFilesDir.exists()) {
354 currentCase.
addReport(allIndexFiles.get(0),
MODULE_NAME, Bundle.ALeappAnalyzerIngestModule_report_name());
358 }
catch (IOException | UncheckedIOException | TskCoreException ex) {
360 logger.log(Level.WARNING, String.format(
"Error finding index file in path %s", aLeappOutputDir.toString()), ex);
369 private List<String>
loadAleappPathFile(Path moduleOutputPath)
throws FileNotFoundException, IOException {
370 List<String> aLeappPathsToProcess =
new ArrayList<>();
374 try (BufferedReader reader =
new BufferedReader(
new FileReader(filePath.toString()))) {
375 String line = reader.readLine();
376 while (line != null) {
377 if (line.contains(
"path list generation") || line.length() < 2) {
378 line = reader.readLine();
381 aLeappPathsToProcess.add(line.trim());
382 line = reader.readLine();
386 return aLeappPathsToProcess;
390 FileManager fileManager = getCurrentCase().getServices().getFileManager();
392 for (String fullFilePath : aLeappPathsToProcess) {
395 logger.log(Level.INFO,
"aLeapp Analyser ingest module run was canceled");
399 String ffp = fullFilePath.replaceAll(
"\\*",
"%");
400 ffp = FilenameUtils.normalize(ffp,
true);
401 String fileName = FilenameUtils.getName(ffp);
402 String filePath = FilenameUtils.getPath(ffp);
404 List<AbstractFile> aLeappFiles =
new ArrayList<>();
406 if (filePath.isEmpty()) {
407 aLeappFiles = fileManager.
findFiles(dataSource, fileName);
409 aLeappFiles = fileManager.
findFiles(dataSource, fileName, filePath);
411 }
catch (TskCoreException ex) {
412 logger.log(Level.WARNING,
"No files found to process");
416 for (AbstractFile aLeappFile : aLeappFiles) {
417 Path parentPath = Paths.get(moduleOutputPath.toString(), aLeappFile.getParentPath());
418 File fileParentPath =
new File(parentPath.toString());
425 private void extractFileToOutput(Content dataSource, AbstractFile aLeappFile, File fileParentPath, Path parentPath) {
426 if (fileParentPath.exists()) {
427 if (!aLeappFile.isDir()) {
431 Files.createDirectories(Paths.get(parentPath.toString(), aLeappFile.getName()));
432 }
catch (IOException ex) {
433 logger.log(Level.INFO, String.format(
"Error creating aLeapp output directory %s", parentPath.toString()), ex);
438 Files.createDirectories(parentPath);
439 }
catch (IOException ex) {
440 logger.log(Level.INFO, String.format(
"Error creating aLeapp output directory %s", parentPath.toString()), ex);
442 if (!aLeappFile.isDir()) {
446 Files.createDirectories(Paths.get(parentPath.toString(), aLeappFile.getName()));
447 }
catch (IOException ex) {
448 logger.log(Level.INFO, String.format(
"Error creating aLeapp output directory %s", parentPath.toString()), ex);
454 private void writeaLeappFile(Content dataSource, AbstractFile aLeappFile, String parentPath) {
455 String fileName = aLeappFile.getName().replace(
":",
"-");
456 if (!fileName.matches(
".") && !fileName.matches(
"..") && !fileName.toLowerCase().endsWith(
"-slack")) {
457 Path filePath = Paths.get(parentPath, fileName);
458 File localFile =
new File(filePath.toString());
461 }
catch (ReadContentInputStream.ReadContentInputStreamException ex) {
462 logger.log(Level.WARNING, String.format(
"Error reading file '%s' (id=%d).",
463 aLeappFile.getName(), aLeappFile.getId()), ex);
464 }
catch (IOException ex) {
465 logger.log(Level.WARNING, String.format(
"Error writing file local file '%s' (id=%d).",
466 filePath.toString(), aLeappFile.getId()), ex);
478 Bundle.ALeappAnalyzerIngestModule_error_running_aLeapp());
LeappFileProcessor aLeappFileProcessor
void addALeappReportToReports(Path aLeappOutputDir, Case currentCase)
static final Logger logger
static int execute(ProcessBuilder processBuilder)
void processALeappFile(Content dataSource, Case currentCase, DataSourceIngestModuleProgress statusHelper, int filesProcessedCount, AbstractFile aLeappFile)
String getTempDirectory()
List< AbstractFile > findFiles(String fileName)
static final String ALEAPP
void startUp(IngestJobContext context)
void extractFilesFromDataSource(Content dataSource, List< String > aLeappPathsToProcess, Path moduleOutputPath)
static IngestMessage createMessage(MessageType messageType, String source, String subject, String detailsHtml)
static< T > long writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, Future< T > worker, boolean source)
ProcessBuilder buildaLeappCommand(Path moduleOutputPath, String sourceFilePath, String aLeappFileSystemType)
void addReport(String localPath, String srcModuleName, String reportName)
void processALeappFs(Content dataSource, Case currentCase, DataSourceIngestModuleProgress statusHelper, String directoryToProcess)
void writeaLeappFile(Content dataSource, AbstractFile aLeappFile, String parentPath)
static final String ALEAPP_PATHS_FILE
static final String MODULE_NAME
static final String XMLFILE
void switchToIndeterminate()
void writeErrorMsgToIngestInbox()
List< String > loadAleappPathFile(Path moduleOutputPath)
ProcessBuilder buildaLeappListCommand(Path moduleOutputPath)
void postMessage(final IngestMessage message)
static final String ALEAPP_EXECUTABLE
static final String ALEAPP_FS
String getModuleDirectory()
ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper)
boolean dataSourceIngestIsCancelled()
ProcessResult processFileSystem(Content dataSource, Path moduleOutputPath, DataSourceIngestModuleProgress progress)
void switchToDeterminate(int workUnits)
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
static File locateExecutable(String executableName)
void extractFileToOutput(Content dataSource, AbstractFile aLeappFile, File fileParentPath, Path parentPath)
static ProcessBuilder buildProcessWithRunAsInvoker(String...commandLine)
void progress(int workUnits)
ProcessResult processFiles(Content dataSource, Path moduleOutputPath, AbstractFile LeappFile, DataSourceIngestModuleProgress progress)
static synchronized IngestServices getInstance()