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 = 
"aleap-artifact-attribute-reference.xml"; 
 
   88         "ALeappAnalyzerIngestModule.executable.not.found=aLeapp Executable Not Found.",
 
   89         "ALeappAnalyzerIngestModule.requires.windows=aLeapp module requires windows.",
 
   90         "ALeappAnalyzerIngestModule.error.ileapp.file.processor.init=Failure to initialize aLeappProcessFile"})
 
   96             throw new IngestModuleException(NbBundle.getMessage(
this.getClass(), 
"AleappAnalyzerIngestModule.not.64.bit.os"));
 
  106             throw new IngestModuleException(Bundle.ALeappAnalyzerIngestModule_error_ileapp_file_processor_init(), ex);
 
  111         } 
catch (FileNotFoundException exception) {
 
  112             logger.log(Level.WARNING, 
"aLeapp executable not found.", exception); 
 
  113             throw new IngestModuleException(Bundle.ALeappAnalyzerIngestModule_executable_not_found(), exception);
 
  119         "ALeappAnalyzerIngestModule.error.running.aLeapp=Error running aLeapp, see log file.",
 
  120         "ALeappAnalyzerIngestModule.error.creating.output.dir=Error creating aLeapp module output directory.",
 
  121         "ALeappAnalyzerIngestModule.starting.aLeapp=Starting aLeapp",
 
  122         "ALeappAnalyzerIngestModule.running.aLeapp=Running aLeapp",
 
  123         "ALeappAnalyzerIngestModule.has.run=aLeapp",
 
  124         "ALeappAnalyzerIngestModule.aLeapp.cancelled=aLeapp run was canceled",
 
  125         "ALeappAnalyzerIngestModule.completed=aLeapp Processing Completed",
 
  126         "ALeappAnalyzerIngestModule.report.name=aLeapp Html Report"})
 
  133             Files.createDirectories(tempOutputPath);
 
  134         } 
catch (IOException ex) {
 
  135             logger.log(Level.SEVERE, String.format(
"Error creating aLeapp output directory %s", tempOutputPath.toString()), ex);
 
  139         List<String> aLeappPathsToProcess = 
new ArrayList<>();
 
  144                 logger.log(Level.SEVERE, String.format(
"Error when trying to execute aLeapp program getting file paths to search for result is %d", result));
 
  148         } 
catch (IOException ex) {
 
  149             logger.log(Level.SEVERE, String.format(
"Error when trying to execute aLeapp program getting file paths to search"), ex);
 
  153         statusHelper.
progress(Bundle.ALeappAnalyzerIngestModule_starting_aLeapp(), 0);
 
  155         List<AbstractFile> aLeappFilesToProcess = 
new ArrayList<>();
 
  157         if (!(context.
getDataSource() instanceof LocalFilesDataSource)) {
 
  160             processALeappFs(dataSource, currentCase, statusHelper, tempOutputPath.toString());
 
  165             Integer filesProcessedCount = 0;
 
  166             for (AbstractFile aLeappFile : aLeappFilesToProcess) {
 
  167                 processALeappFile(dataSource, currentCase, statusHelper, filesProcessedCount, aLeappFile);
 
  168                 filesProcessedCount++;
 
  172             processALeappFs(dataSource, currentCase, statusHelper, tempOutputPath.toString());
 
  176                 Bundle.ALeappAnalyzerIngestModule_has_run(),
 
  177                 Bundle.ALeappAnalyzerIngestModule_completed());
 
  191             AbstractFile aLeappFile) {
 
  192         String currentTime = 
new SimpleDateFormat(
"yyyy-MM-dd HH-mm-ss z", Locale.US).format(System.currentTimeMillis());
 
  195             Files.createDirectories(moduleOutputPath);
 
  196         } 
catch (IOException ex) {
 
  197             logger.log(Level.SEVERE, String.format(
"Error creating aLeapp output directory %s", moduleOutputPath.toString()), ex);
 
  201         statusHelper.
progress(NbBundle.getMessage(
this.getClass(), 
"ALeappAnalyzerIngestModule.processing.file", aLeappFile.getName()), filesProcessedCount);
 
  202         ProcessBuilder aLeappCommand = 
buildaLeappCommand(moduleOutputPath, aLeappFile.getLocalAbsPath(), aLeappFile.getNameExtension());
 
  206                 logger.log(Level.WARNING, String.format(
"Error when trying to execute aLeapp program getting file paths to search for result is %d", result));
 
  212         } 
catch (IOException ex) {
 
  213             logger.log(Level.SEVERE, String.format(
"Error when trying to execute aLeapp program against file %s", aLeappFile.getLocalAbsPath()), ex);
 
  218             logger.log(Level.INFO, 
"ILeapp Analyser ingest module run was canceled"); 
 
  237         String currentTime = 
new SimpleDateFormat(
"yyyy-MM-dd HH-mm-ss z", Locale.US).format(System.currentTimeMillis());
 
  240             Files.createDirectories(moduleOutputPath);
 
  241         } 
catch (IOException ex) {
 
  242             logger.log(Level.SEVERE, String.format(
"Error creating aLeapp output directory %s", moduleOutputPath.toString()), ex);
 
  246         statusHelper.
progress(NbBundle.getMessage(
this.getClass(), 
"ALeappAnalyzerIngestModule.processing.filesystem"));
 
  247         ProcessBuilder aLeappCommand = 
buildaLeappCommand(moduleOutputPath, directoryToProcess, 
"fs");
 
  251                 logger.log(Level.WARNING, String.format(
"Error when trying to execute aLeapp program getting file paths to search for result is %d", result));
 
  257         } 
catch (IOException ex) {
 
  258             logger.log(Level.SEVERE, String.format(
"Error when trying to execute aLeapp program against file system"), ex);
 
  263             logger.log(Level.INFO, 
"ILeapp Analyser ingest module run was canceled"); 
 
  286     private ProcessBuilder 
buildaLeappCommand(Path moduleOutputPath, String sourceFilePath, String aLeappFileSystemType) {
 
  289                 "\"" + aLeappExecutable + 
"\"", 
 
  290                 "-t", aLeappFileSystemType, 
 
  291                 "-i", sourceFilePath, 
 
  292                 "-o", moduleOutputPath.toString(),
 
  295         processBuilder.redirectError(moduleOutputPath.resolve(
"aLeapp_err.txt").toFile());  
 
  296         processBuilder.redirectOutput(moduleOutputPath.resolve(
"aLeapp_out.txt").toFile());  
 
  297         return processBuilder;
 
  303                 "\"" + aLeappExecutable + 
"\"", 
 
  306         processBuilder.redirectError(moduleOutputPath.resolve(
"aLeapp_paths_error.txt").toFile());  
 
  307         processBuilder.redirectOutput(moduleOutputPath.resolve(
"aLeapp_paths.txt").toFile());  
 
  308         return processBuilder;
 
  312         ProcessBuilder processBuilder = 
new ProcessBuilder(commandLine);
 
  317         processBuilder.environment().put(
"__COMPAT_LAYER", 
"RunAsInvoker"); 
 
  318         return processBuilder;
 
  322         String executableToFindName = Paths.get(ALEAPP, executableName).toString();
 
  324         File exeFile = InstalledFileLocator.getDefault().locate(executableToFindName, 
ALeappAnalyzerIngestModule.class.getPackage().getName(), 
false);
 
  325         if (null == exeFile || exeFile.canExecute() == 
false) {
 
  326             throw new FileNotFoundException(executableName + 
" executable not found.");
 
  336         List<String> allIndexFiles = 
new ArrayList<>();
 
  338         try (Stream<Path> walk = Files.walk(aLeappOutputDir)) { 
 
  340             allIndexFiles = walk.map(x -> x.toString())
 
  341                     .filter(f -> f.toLowerCase().endsWith(
"index.html")).collect(Collectors.toList());
 
  343             if (!allIndexFiles.isEmpty()) {
 
  345                 String filePath = FilenameUtils.getFullPathNoEndSeparator(allIndexFiles.get(0));
 
  346                 File dataFilesDir = 
new File(Paths.get(filePath, 
"_TSV Exports").toString());
 
  347                 if (dataFilesDir.exists()) {
 
  348                     currentCase.
addReport(allIndexFiles.get(0), 
MODULE_NAME, Bundle.ALeappAnalyzerIngestModule_report_name());
 
  352         } 
catch (IOException | UncheckedIOException | TskCoreException ex) {
 
  354             logger.log(Level.WARNING, String.format(
"Error finding index file in path %s", aLeappOutputDir.toString()), ex);
 
  363     private List<String> 
loadIleappPathFile(Path moduleOutputPath) 
throws FileNotFoundException, IOException {
 
  364         List<String> aLeappPathsToProcess = 
new ArrayList<>();
 
  368         try (BufferedReader reader = 
new BufferedReader(
new FileReader(filePath.toString()))) {
 
  369             String line = reader.readLine();
 
  370             while (line != null) {
 
  371                 if (line.contains(
"path list generation") || line.length() < 2) {
 
  372                     line = reader.readLine();
 
  375                 aLeappPathsToProcess.add(line.trim());
 
  376                 line = reader.readLine();
 
  380         return aLeappPathsToProcess;
 
  384         FileManager fileManager = getCurrentCase().getServices().getFileManager();
 
  386         for (String fullFilePath : aLeappPathsToProcess) {
 
  389                 logger.log(Level.INFO, 
"aLeapp Analyser ingest module run was canceled"); 
 
  393             String ffp = fullFilePath.replaceAll(
"\\*", 
"%");
 
  394             ffp = FilenameUtils.normalize(ffp, 
true);
 
  395             String fileName = FilenameUtils.getName(ffp);
 
  396             String filePath = FilenameUtils.getPath(ffp);
 
  398             List<AbstractFile> aLeappFiles = 
new ArrayList<>();
 
  400                 if (filePath.isEmpty()) {
 
  401                     aLeappFiles = fileManager.
findFiles(dataSource, fileName); 
 
  403                     aLeappFiles = fileManager.
findFiles(dataSource, fileName, filePath); 
 
  405             } 
catch (TskCoreException ex) {
 
  406                 logger.log(Level.WARNING, 
"No files found to process"); 
 
  410             for (AbstractFile aLeappFile : aLeappFiles) {
 
  411                 Path parentPath = Paths.get(moduleOutputPath.toString(), aLeappFile.getParentPath());
 
  412                 File fileParentPath = 
new File(parentPath.toString());
 
  419     private void extractFileToOutput(Content dataSource, AbstractFile aLeappFile, File fileParentPath, Path parentPath) {
 
  420         if (fileParentPath.exists()) {
 
  421                     if (!aLeappFile.isDir()) {
 
  425                             Files.createDirectories(Paths.get(parentPath.toString(), aLeappFile.getName()));
 
  426                         } 
catch (IOException ex) {
 
  427                             logger.log(Level.INFO, String.format(
"Error creating aLeapp output directory %s", parentPath.toString()), ex);
 
  432                         Files.createDirectories(parentPath);
 
  433                     } 
catch (IOException ex) {
 
  434                         logger.log(Level.INFO, String.format(
"Error creating aLeapp output directory %s", parentPath.toString()), ex);
 
  436                     if (!aLeappFile.isDir()) {
 
  440                             Files.createDirectories(Paths.get(parentPath.toString(), aLeappFile.getName()));
 
  441                         } 
catch (IOException ex) {
 
  442                             logger.log(Level.INFO, String.format(
"Error creating aLeapp output directory %s", parentPath.toString()), ex);
 
  448     private void writeaLeappFile(Content dataSource, AbstractFile aLeappFile, String parentPath) {
 
  449         String fileName = aLeappFile.getName().replace(
":", 
"-");
 
  450         if (!fileName.matches(
".") && !fileName.matches(
"..") && !fileName.toLowerCase().endsWith(
"-slack")) {
 
  451             Path filePath = Paths.get(parentPath, fileName);
 
  452             File localFile = 
new File(filePath.toString());
 
  455             } 
catch (ReadContentInputStream.ReadContentInputStreamException ex) {
 
  456                 logger.log(Level.WARNING, String.format(
"Error reading file '%s' (id=%d).",
 
  457                         aLeappFile.getName(), aLeappFile.getId()), ex); 
 
  458             } 
catch (IOException ex) {
 
  459                 logger.log(Level.WARNING, String.format(
"Error writing file local file '%s' (id=%d).",
 
  460                         filePath.toString(), aLeappFile.getId()), ex); 
 
LeappFileProcessor aLeappFileProcessor
 
void addILeappReportToReports(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)
 
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
 
ProcessResult processFileSystem(Content dataSource, Path moduleOutputPath)
 
ProcessBuilder buildaLeappListCommand(Path moduleOutputPath)
 
ProcessResult processFiles(Content dataSource, Path moduleOutputPath, AbstractFile LeappFile)
 
void postMessage(final IngestMessage message)
 
static final String ALEAPP_EXECUTABLE
 
static final String ALEAPP_FS
 
String getModuleDirectory()
 
ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper)
 
List< String > loadIleappPathFile(Path moduleOutputPath)
 
boolean dataSourceIngestIsCancelled()
 
void extractFilesFromImage(Content dataSource, List< String > aLeappPathsToProcess, Path moduleOutputPath)
 
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)
 
static synchronized IngestServices getInstance()