19 package org.sleuthkit.autopsy.modules.photoreccarver;
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.nio.file.Path;
25 import java.nio.file.Paths;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.List;
29 import java.util.logging.Level;
30 import org.openide.util.NbBundle;
43 import org.w3c.dom.Document;
44 import org.w3c.dom.Element;
45 import org.w3c.dom.NodeList;
51 class PhotoRecCarverOutputParser {
53 private final Path basePath;
54 private static final Logger logger = Logger.getLogger(PhotoRecCarverFileIngestModule.class.getName());
56 PhotoRecCarverOutputParser(Path base) {
77 List<LayoutFile> parse(File xmlInputFile, AbstractFile af, IngestJobContext context)
throws FileNotFoundException, IOException {
79 final Document doc = XMLUtil.loadDoc(PhotoRecCarverOutputParser.class, xmlInputFile.toString());
81 return new ArrayList<>();
84 Element root = doc.getDocumentElement();
86 logger.log(Level.SEVERE,
"Error loading config file: invalid file format (bad root).");
87 return new ArrayList<>();
90 NodeList fileObjects = root.getElementsByTagName(
"fileobject");
91 final int numberOfFiles = fileObjects.getLength();
93 if (numberOfFiles == 0) {
94 return new ArrayList<>();
103 FileManager fileManager = Case.getCurrentCaseThrows().getServices().getFileManager();
106 List<CarvingResult.CarvedFile> carvedFiles =
new ArrayList<>();
107 for (
int fileIndex = 0; fileIndex < numberOfFiles; ++fileIndex) {
108 if (context.fileIngestIsCancelled() ==
true) {
110 logger.log(Level.INFO,
"PhotoRec cancelled by user");
111 MessageNotifyUtil.Notify.info(PhotoRecCarverIngestModuleFactory.getModuleName(), NbBundle.getMessage(PhotoRecCarverFileIngestModule.class,
"PhotoRecIngestModule.cancelledByUser"));
114 entry = (Element) fileObjects.item(fileIndex);
115 fileNames = entry.getElementsByTagName(
"filename");
116 fileSizes = entry.getElementsByTagName(
"filesize");
117 fileRanges = entry.getElementsByTagName(
"byte_run");
119 fileSize = Long.parseLong(fileSizes.item(0).getTextContent());
120 fileName = fileNames.item(0).getTextContent();
121 filePath = Paths.get(fileName);
122 if (filePath.startsWith(basePath)) {
123 fileName = filePath.getFileName().toString();
126 List<TskFileRange> tskRanges =
new ArrayList<>();
127 for (
int rangeIndex = 0; rangeIndex < fileRanges.getLength(); ++rangeIndex) {
129 Long img_offset = Long.parseLong(((Element) fileRanges.item(rangeIndex)).getAttribute(
"img_offset"));
130 Long len = Long.parseLong(((Element) fileRanges.item(rangeIndex)).getAttribute(
"len"));
133 long fileByteStart = af.convertToImgOffset(img_offset);
134 if (fileByteStart == -1) {
136 logger.log(Level.INFO,
"Error while parsing PhotoRec output for file {0}", fileName);
141 long fileByteEnd = img_offset + len;
142 if (fileByteEnd > af.getSize()) {
143 long overshoot = fileByteEnd - af.getSize();
144 if (fileSize > overshoot) {
145 fileSize -= overshoot;
152 tskRanges.add(
new TskFileRange(fileByteStart, len, rangeIndex));
155 if (!tskRanges.isEmpty()) {
156 carvedFiles.add(
new CarvingResult.CarvedFile(fileName, fileSize, tskRanges));
159 return fileManager.addCarvedFiles(
new CarvingResult(af, carvedFiles));
160 }
catch (NumberFormatException | TskCoreException | NoCurrentCaseException ex) {
161 logger.log(Level.SEVERE,
"Error parsing PhotoRec output and inserting it into the database", ex);
164 List<LayoutFile> empty = Collections.emptyList();