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);
 
  169             List<AbstractFile> aLeappFilesToProcess = 
LeappFileProcessor.findLeappFilesToProcess(dataSource);
 
  170             if (!aLeappFilesToProcess.isEmpty()) {
 
  172                 Integer filesProcessedCount = 0;
 
  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());
 
  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);
 
  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());
 
  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); 
 
  412                 logger.log(Level.WARNING, 
"No files found to process"); 
 
  417                 Path parentPath = Paths.get(moduleOutputPath.toString(), aLeappFile.getParentPath());
 
  418                 File fileParentPath = 
new File(parentPath.toString());
 
  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);
 
  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());
 
  462                 logger.log(Level.WARNING, String.format(
"Error reading file '%s' (id=%d).",
 
  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)
String getNameExtension()
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
String toString(boolean preserveState)
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()