Autopsy  4.14.0
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  */
19 package org.sleuthkit.autopsy.modules.photoreccarver;
20 
21 import java.io.File;
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;
38 import org.sleuthkit.datamodel.AbstractFile;
39 import org.sleuthkit.datamodel.CarvingResult;
40 import org.sleuthkit.datamodel.LayoutFile;
41 import org.sleuthkit.datamodel.TskCoreException;
42 import org.sleuthkit.datamodel.TskFileRange;
43 import org.w3c.dom.Document;
44 import org.w3c.dom.Element;
45 import org.w3c.dom.NodeList;
46 
51 class PhotoRecCarverOutputParser {
52 
53  private final Path basePath;
54  private static final Logger logger = Logger.getLogger(PhotoRecCarverFileIngestModule.class.getName());
55 
56  PhotoRecCarverOutputParser(Path base) {
57  basePath = base;
58  }
59 
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 img_offset = Long.parseLong(((Element) fileRanges.item(rangeIndex)).getAttribute("img_offset")); //NON-NLS
130  Long len = Long.parseLong(((Element) fileRanges.item(rangeIndex)).getAttribute("len")); //NON-NLS
131 
132  // Verify PhotoRec's output
133  long fileByteStart = af.convertToImgOffset(img_offset);
134  if (fileByteStart == -1) {
135  // This better never happen... Data for this file is corrupted. Skip it.
136  logger.log(Level.INFO, "Error while parsing PhotoRec output for file {0}", fileName); //NON-NLS
137  continue;
138  }
139 
140  // check that carved file is within unalloc block
141  long fileByteEnd = img_offset + len;
142  if (fileByteEnd > af.getSize()) {
143  long overshoot = fileByteEnd - af.getSize();
144  if (fileSize > overshoot) {
145  fileSize -= overshoot;
146  } else {
147  // This better never happen... Data for this file is corrupted. Skip it.
148  continue;
149  }
150  }
151 
152  tskRanges.add(new TskFileRange(fileByteStart, len, rangeIndex));
153  }
154 
155  if (!tskRanges.isEmpty()) {
156  carvedFiles.add(new CarvingResult.CarvedFile(fileName, fileSize, tskRanges));
157  }
158  }
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); //NON-NLS
162  }
163 
164  List<LayoutFile> empty = Collections.emptyList();
165  return empty;
166  }
167 }

Copyright © 2012-2020 Basis Technology. Generated on: Wed Apr 8 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.