Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
PhotoRecCarverOutputParser.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2011-2018 Basis Technology Corp.
5 * Contact: carrier <at> sleuthkit <dot> org
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19package org.sleuthkit.autopsy.modules.photoreccarver;
20
21import java.io.File;
22import java.io.FileNotFoundException;
23import java.io.IOException;
24import java.nio.file.Path;
25import java.nio.file.Paths;
26import java.util.ArrayList;
27import java.util.Collections;
28import java.util.List;
29import java.util.logging.Level;
30import org.openide.util.NbBundle;
31import org.sleuthkit.autopsy.casemodule.Case;
32import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
33import org.sleuthkit.autopsy.casemodule.services.FileManager;
34import org.sleuthkit.autopsy.coreutils.Logger;
35import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
36import org.sleuthkit.autopsy.coreutils.XMLUtil;
37import org.sleuthkit.autopsy.ingest.IngestJobContext;
38import org.sleuthkit.datamodel.AbstractFile;
39import org.sleuthkit.datamodel.CarvingResult;
40import org.sleuthkit.datamodel.LayoutFile;
41import org.sleuthkit.datamodel.TskCoreException;
42import org.sleuthkit.datamodel.TskFileRange;
43import org.w3c.dom.Document;
44import org.w3c.dom.Element;
45import org.w3c.dom.NodeList;
46import org.w3c.dom.Node;
47
52class PhotoRecCarverOutputParser {
53
54 private final Path basePath;
55 private static final Logger logger = Logger.getLogger(PhotoRecCarverFileIngestModule.class.getName());
56
57 PhotoRecCarverOutputParser(Path base) {
58 basePath = base;
59 }
60
77 List<LayoutFile> parse(File xmlInputFile, AbstractFile af, IngestJobContext context) throws FileNotFoundException, IOException {
78 try {
79 final Document doc = XMLUtil.loadDoc(PhotoRecCarverOutputParser.class, xmlInputFile.toString());
80 if (doc == null) {
81 return new ArrayList<>();
82 }
83
84 Element root = doc.getDocumentElement();
85 if (root == null) {
86 logger.log(Level.SEVERE, "Error loading config file: invalid file format (bad root)."); //NON-NLS
87 return new ArrayList<>();
88 }
89
90 NodeList fileObjects = root.getElementsByTagName("fileobject"); //NON-NLS
91 final int numberOfFiles = fileObjects.getLength();
92
93 if (numberOfFiles == 0) {
94 return new ArrayList<>();
95 }
96 String fileName;
97 Long fileSize;
98 NodeList fileNames;
99 NodeList fileSizes;
100 NodeList fileRanges;
101 Element entry;
102 Path filePath;
103 FileManager fileManager = Case.getCurrentCaseThrows().getServices().getFileManager();
104
105 // create and initialize the list to put into the database
106 List<CarvingResult.CarvedFile> carvedFiles = new ArrayList<>();
107 for (int fileIndex = 0; fileIndex < numberOfFiles; ++fileIndex) {
108 if (context.fileIngestIsCancelled() == true) {
109 // if it was cancelled by the user, result is OK
110 logger.log(Level.INFO, "PhotoRec cancelled by user"); // NON-NLS
111 MessageNotifyUtil.Notify.info(PhotoRecCarverIngestModuleFactory.getModuleName(), NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "PhotoRecIngestModule.cancelledByUser"));
112 break;
113 }
114 entry = (Element) fileObjects.item(fileIndex);
115 fileNames = entry.getElementsByTagName("filename"); //NON-NLS
116 fileSizes = entry.getElementsByTagName("filesize"); //NON-NLS
117 fileRanges = entry.getElementsByTagName("byte_run"); //NON-NLS
118
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();
124 }
125
126 List<TskFileRange> tskRanges = new ArrayList<>();
127 for (int rangeIndex = 0; rangeIndex < fileRanges.getLength(); ++rangeIndex) {
128
129 Long unallocFileOffset = null;
130 Long len = null;
131
132 // attempt to parse a range for a file. on error, log.
133 Node rangeNode = fileRanges.item(rangeIndex);
134 if (rangeNode instanceof Element) {
135 Element rangeElement = (Element) rangeNode;
136 String imgOffsetStr = rangeElement.getAttribute("img_offset");
137 String lenStr = rangeElement.getAttribute("len");
138
139 try {
140 unallocFileOffset = Long.parseLong(imgOffsetStr);
141 len = Long.parseLong(lenStr);
142 } catch (NumberFormatException ex) {
143 logger.log(Level.SEVERE,
144 String.format("There was an error parsing ranges in %s with file index: %d and range index: %d.",
145 xmlInputFile.getPath(), fileIndex, rangeIndex), ex);
146 }
147 } else {
148 logger.log(Level.SEVERE,
149 String.format("Malformed node in %s with file index: %d and range index: %d.",
150 xmlInputFile.getPath(), fileIndex, rangeIndex));
151 }
152
153 // if we have a valid file offset and length, get the ranges relative to the image for the carved file.
154 if (unallocFileOffset != null && unallocFileOffset >= 0 && len != null && len > 0) {
155 for (TskFileRange rangeToAdd : af.convertToImgRanges(unallocFileOffset, len)) {
156 tskRanges.add(new TskFileRange(rangeToAdd.getByteStart(), rangeToAdd.getByteLen(), tskRanges.size()));
157 }
158 }
159
160 }
161
162 if (!tskRanges.isEmpty()) {
163 carvedFiles.add(new CarvingResult.CarvedFile(fileName, fileSize, tskRanges));
164 }
165 }
166 return fileManager.addCarvedFiles(new CarvingResult(af, carvedFiles));
167 } catch (NumberFormatException | TskCoreException | NoCurrentCaseException ex) {
168 logger.log(Level.SEVERE, "Error parsing PhotoRec output and inserting it into the database", ex); //NON-NLS
169 }
170
171 List<LayoutFile> empty = Collections.emptyList();
172 return empty;
173 }
174}

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.