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;
42 import org.w3c.dom.Document;
43 import org.w3c.dom.Element;
44 import org.w3c.dom.NodeList;
50 class PhotoRecCarverOutputParser {
52 private final Path basePath;
53 private static final Logger logger = Logger.getLogger(PhotoRecCarverFileIngestModule.class.getName());
55 PhotoRecCarverOutputParser(Path base) {
76 List<LayoutFile> parse(File xmlInputFile, AbstractFile af, IngestJobContext context)
throws FileNotFoundException, IOException {
78 final Document doc = XMLUtil.loadDoc(PhotoRecCarverOutputParser.class, xmlInputFile.toString());
80 return new ArrayList<>();
83 Element root = doc.getDocumentElement();
85 logger.log(Level.SEVERE,
"Error loading config file: invalid file format (bad root).");
86 return new ArrayList<>();
89 NodeList fileObjects = root.getElementsByTagName(
"fileobject");
90 final int numberOfFiles = fileObjects.getLength();
92 if (numberOfFiles == 0) {
93 return new ArrayList<>();
102 FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
105 List<CarvingResult.CarvedFile> carvedFiles =
new ArrayList<>();
106 for (
int fileIndex = 0; fileIndex < numberOfFiles; ++fileIndex) {
107 if (context.fileIngestIsCancelled() ==
true) {
109 logger.log(Level.INFO,
"PhotoRec cancelled by user");
110 MessageNotifyUtil.Notify.info(PhotoRecCarverIngestModuleFactory.getModuleName(), NbBundle.getMessage(PhotoRecCarverFileIngestModule.class,
"PhotoRecIngestModule.cancelledByUser"));
113 entry = (Element) fileObjects.item(fileIndex);
114 fileNames = entry.getElementsByTagName(
"filename");
115 fileSizes = entry.getElementsByTagName(
"filesize");
116 fileRanges = entry.getElementsByTagName(
"byte_run");
118 fileSize = Long.parseLong(fileSizes.item(0).getTextContent());
119 fileName = fileNames.item(0).getTextContent();
120 filePath = Paths.get(fileName);
121 if (filePath.startsWith(basePath)) {
122 fileName = filePath.getFileName().toString();
125 List<TskFileRange> tskRanges =
new ArrayList<>();
126 for (
int rangeIndex = 0; rangeIndex < fileRanges.getLength(); ++rangeIndex) {
128 Long img_offset = Long.parseLong(((Element) fileRanges.item(rangeIndex)).getAttribute(
"img_offset"));
129 Long len = Long.parseLong(((Element) fileRanges.item(rangeIndex)).getAttribute(
"len"));
132 long fileByteStart = af.convertToImgOffset(img_offset);
133 if (fileByteStart == -1) {
135 logger.log(Level.INFO,
"Error while parsing PhotoRec output for file {0}", fileName);
140 long fileByteEnd = img_offset + len;
141 if (fileByteEnd > af.getSize()) {
142 long overshoot = fileByteEnd - af.getSize();
143 if (fileSize > overshoot) {
144 fileSize -= overshoot;
151 tskRanges.add(
new TskFileRange(fileByteStart, len, rangeIndex));
154 if (!tskRanges.isEmpty()) {
155 carvedFiles.add(
new CarvingResult.CarvedFile(fileName, fileSize, tskRanges));
158 return fileManager.addCarvedFiles(
new CarvingResult(af, carvedFiles));
159 }
catch (NumberFormatException | TskCoreException ex) {
160 logger.log(Level.SEVERE,
"Error parsing PhotoRec output and inserting it into the database", ex);
163 List<LayoutFile> empty = Collections.emptyList();