Autopsy  4.20.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 import org.w3c.dom.Node;
47 
52 class 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-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.