Autopsy  4.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExternalResultsXMLParser.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2016 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.externalresults;
20 
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.logging.Level;
24 import org.openide.util.NbBundle;
28 import org.sleuthkit.datamodel.Content;
29 import org.w3c.dom.Document;
30 import org.w3c.dom.Element;
31 import org.w3c.dom.NodeList;
32 
37 public final class ExternalResultsXMLParser implements ExternalResultsParser {
38 
39  private static final Logger logger = Logger.getLogger(ExternalResultsXMLParser.class.getName());
40  private static final String XSD_FILE = "autopsy_external_results.xsd"; //NON-NLS
41  private final Content dataSource;
42  private final String resultsFilePath;
44  private List<ErrorInfo> errors = new ArrayList<>();
45 
49  public enum TagNames {
50 
51  ROOT_ELEM("autopsy_results"), //NON-NLS
52  DERIVED_FILES_LIST_ELEM("derived_files"), //NON-NLS
53  DERIVED_FILE_ELEM("derived_file"), //NON-NLS
54  LOCAL_PATH_ELEM("local_path"), //NON-NLS
55  PARENT_FILE_ELEM("parent_file"), //NON-NLS
56  ARTIFACTS_LIST_ELEM("artifacts"), //NON-NLS
57  ARTIFACT_ELEM("artifact"), //NON-NLS
58  SOURCE_FILE_ELEM("source_file"), //NON-NLS
59  ATTRIBUTE_ELEM("attribute"), //NON-NLS
60  VALUE_ELEM("value"), //NON-NLS
61  SOURCE_MODULE_ELEM("source_module"), //NON-NLS
62  REPORTS_LIST_ELEM("reports"), //NON-NLS
63  REPORT_ELEM("report"), //NON-NLS
64  REPORT_NAME_ELEM("report_name"); //NON-NLS
65  private final String text;
66 
67  private TagNames(final String text) {
68  this.text = text;
69  }
70 
71  @Override
72  public String toString() {
73  return this.text;
74  }
75  }
76 
80  public enum AttributeNames {
81 
82  TYPE_ATTR("type"); //NON-NLS
83  private final String text;
84 
85  private AttributeNames(final String text) {
86  this.text = text;
87  }
88 
89  @Override
90  public String toString() {
91  return this.text;
92  }
93  }
94 
98  public enum AttributeValues {
99 
100  VALUE_TYPE_TEXT("text"), //NON-NLS
101  VALUE_TYPE_INT32("int32"), //NON-NLS
102  VALUE_TYPE_INT64("int64"), //NON-NLS
103  VALUE_TYPE_DOUBLE("double"), //NON-NLS
104  VALUE_TYPE_DATETIME("datetime"); //NON-NLS
105  private final String text;
106 
107  private AttributeValues(final String text) {
108  this.text = text;
109  }
110 
111  @Override
112  public String toString() {
113  return this.text;
114  }
115  }
116 
123  public ExternalResultsXMLParser(Content dataSource, String resultsFilePath) {
124  this.dataSource = dataSource;
125  this.resultsFilePath = resultsFilePath;
126  }
127 
128  @Override
130  this.errors.clear();
131  this.resultsData = new ExternalResults(dataSource);
132  try {
133  // Note that XMLUtil.loadDoc() logs a warning if the file does not
134  // conform to the XSD, but still returns a Document object. Until
135  // this behavior is improved, validation is still required. If
136  // XMLUtil.loadDoc() does return null, it failed to load the
137  // document and it logged the error.
138  final Document doc = XMLUtil.loadDoc(ExternalResultsXMLParser.class, this.resultsFilePath, XSD_FILE);
139  if (doc != null) {
140  final Element rootElem = doc.getDocumentElement();
141  if (rootElem != null && rootElem.getNodeName().equals(TagNames.ROOT_ELEM.toString())) {
142  parseDerivedFiles(rootElem);
143  parseArtifacts(rootElem);
144  parseReports(rootElem);
145  } else {
146  String errorMessage = NbBundle.getMessage(this.getClass(),
147  "ExternalResultsXMLParser.parse.errMsg1.text",
148  TagNames.ROOT_ELEM.toString(), this.resultsFilePath);
149  recordError(errorMessage);
150  }
151  }
152  } catch (Exception ex) {
153  String errorMessage = NbBundle.getMessage(this.getClass(), "ExternalResultsXMLParser.parse.errMsg2.text", this.resultsFilePath);
154  recordError(errorMessage, ex);
155  }
156  return this.resultsData;
157  }
158 
159  @Override
160  public List<ErrorInfo> getErrorInfo() {
161  return new ArrayList<>(this.errors);
162  }
163 
164  private void parseDerivedFiles(Element rootElement) {
165  // Get the derived file lists.
166  NodeList derivedFilesListNodes = rootElement.getElementsByTagName(TagNames.DERIVED_FILES_LIST_ELEM.toString());
167  for (int i = 0; i < derivedFilesListNodes.getLength(); ++i) {
168  Element derivedFilesListElem = (Element) derivedFilesListNodes.item(i);
169  // Get the derived files.
170  NodeList derivedFileNodes = derivedFilesListElem.getElementsByTagName(TagNames.DERIVED_FILE_ELEM.toString());
171  for (int j = 0; j < derivedFileNodes.getLength(); ++j) {
172  Element derivedFileElem = (Element) derivedFileNodes.item(j);
173  // Get the local path of the derived file.
174  String path = getChildElementContent(derivedFileElem, TagNames.LOCAL_PATH_ELEM.toString(), true);
175  if (path.isEmpty()) {
176  continue;
177  }
178  // Get the parent file of the derived file.
179  String parentFile = getChildElementContent((Element) derivedFileNodes.item(j), TagNames.PARENT_FILE_ELEM.toString(), true);
180  if (parentFile.isEmpty()) {
181  continue;
182  }
183  this.resultsData.addDerivedFile(path, parentFile);
184  }
185  }
186  }
187 
188  private void parseArtifacts(final Element root) {
189  // Get the artifact lists.
190  NodeList artifactsListNodes = root.getElementsByTagName(TagNames.ARTIFACTS_LIST_ELEM.toString());
191  for (int i = 0; i < artifactsListNodes.getLength(); ++i) {
192  Element artifactsListElem = (Element) artifactsListNodes.item(i);
193  // Get the artifacts.
194  NodeList artifactNodes = artifactsListElem.getElementsByTagName(TagNames.ARTIFACT_ELEM.toString());
195  for (int j = 0; j < artifactNodes.getLength(); ++j) {
196  Element artifactElem = (Element) artifactNodes.item(j);
197  // Get the artifact type.
198  final String type = getElementAttributeValue(artifactElem, AttributeNames.TYPE_ATTR.toString());
199  if (!type.isEmpty()) {
200  // Get the source file of the artifact and the attributes,
201  // if any.
202  final String sourceFilePath = this.getChildElementContent(artifactElem, TagNames.SOURCE_FILE_ELEM.toString(), true);
203  if (!sourceFilePath.isEmpty()) {
204  ExternalResults.Artifact artifact = this.resultsData.addArtifact(type, sourceFilePath);
205  parseArtifactAttributes(artifactElem, artifact);
206  }
207  }
208  }
209  }
210  }
211 
212  private void parseArtifactAttributes(final Element artifactElem, ExternalResults.Artifact artifact) {
213  // Get the artifact attributes.
214  NodeList attributeNodesList = artifactElem.getElementsByTagName(TagNames.ATTRIBUTE_ELEM.toString());
215  for (int i = 0; i < attributeNodesList.getLength(); ++i) {
216  Element attributeElem = (Element) attributeNodesList.item(i);
217  final String type = getElementAttributeValue(attributeElem, AttributeNames.TYPE_ATTR.toString());
218  if (type.isEmpty()) {
219  continue;
220  }
221  // Get the value of the artifact attribute.
222  Element valueElem = this.getChildElement(attributeElem, TagNames.VALUE_ELEM.toString());
223  if (valueElem == null) {
224  continue;
225  }
226  final String value = valueElem.getTextContent();
227  if (value.isEmpty()) {
228  String errorMessage = NbBundle.getMessage(this.getClass(),
229  "ExternalResultsXMLParser.parseArtifactAttributes.errMsg1.text",
230  TagNames.VALUE_ELEM.toString(), this.resultsFilePath);
231  recordError(errorMessage);
232  continue;
233  }
234  // Get the value type.
235  String valueType = parseArtifactAttributeValueType(valueElem);
236  if (valueType.isEmpty()) {
237  continue;
238  }
239  // Get the optional source module.
240  String sourceModule = this.getChildElementContent(attributeElem, TagNames.SOURCE_MODULE_ELEM.toString(), false);
241  // Add the attribute to the artifact.
242  artifact.addAttribute(type, value, valueType, sourceModule);
243  }
244  }
245 
246  private String parseArtifactAttributeValueType(Element valueElem) {
247  String valueType = valueElem.getAttribute(AttributeNames.TYPE_ATTR.toString());
248  if (valueType.isEmpty()) {
249  // Default to text.
250  valueType = AttributeValues.VALUE_TYPE_TEXT.toString();
251  } else if (!valueType.equals(AttributeValues.VALUE_TYPE_TEXT.toString())
252  && !valueType.equals(AttributeValues.VALUE_TYPE_DOUBLE.toString())
253  && !valueType.equals(AttributeValues.VALUE_TYPE_INT32.toString())
254  && !valueType.equals(AttributeValues.VALUE_TYPE_INT64.toString())
255  && !valueType.equals(AttributeValues.VALUE_TYPE_DATETIME.toString())) {
256  String errorMessage = NbBundle.getMessage(this.getClass(),
257  "ExternalResultsXMLParser.parseAttributeValueType.errMsg1.text",
258  valueType,
259  AttributeNames.TYPE_ATTR.toString(),
260  TagNames.VALUE_ELEM.toString());
261  this.recordError(errorMessage);
262  valueType = "";
263  }
264  return valueType;
265  }
266 
267  private void parseReports(Element root) {
268  // Get the report lists.
269  NodeList reportsListNodes = root.getElementsByTagName(TagNames.REPORTS_LIST_ELEM.toString());
270  for (int i = 0; i < reportsListNodes.getLength(); ++i) {
271  Element reportsListElem = (Element) reportsListNodes.item(i);
272  // Get the reports.
273  NodeList reportNodes = reportsListElem.getElementsByTagName(TagNames.REPORT_ELEM.toString());
274  for (int j = 0; j < reportNodes.getLength(); ++j) {
275  Element reportElem = (Element) reportNodes.item(j);
276  // Get the local path.
277  String path = getChildElementContent(reportElem, TagNames.LOCAL_PATH_ELEM.toString(), true);
278  if (path.isEmpty()) {
279  continue;
280  }
281  // Get the source module.
282  String sourceModule = getChildElementContent(reportElem, TagNames.SOURCE_MODULE_ELEM.toString(), true);
283  if (path.isEmpty()) {
284  continue;
285  }
286  // Get the optional report name.
287  String reportName = getChildElementContent(reportElem, TagNames.REPORT_NAME_ELEM.toString(), false);
288  this.resultsData.addReport(path, sourceModule, reportName);
289  }
290  }
291  }
292 
293  private String getElementAttributeValue(Element element, String attributeName) {
294  final String attributeValue = element.getAttribute(attributeName);
295  if (attributeValue.isEmpty()) {
296  logger.log(Level.SEVERE, "Found {0} element missing {1} attribute in {2}", new Object[]{ //NON-NLS
297  element.getTagName(),
298  attributeName,
299  this.resultsFilePath});
300  }
301  return attributeValue;
302  }
303 
304  private String getChildElementContent(Element parentElement, String childElementTagName, boolean required) {
305  String content = "";
306  Element childElement = this.getChildElement(parentElement, childElementTagName);
307  if (childElement != null) {
308  content = childElement.getTextContent();
309  if (content.isEmpty()) {
310  String errorMessage = NbBundle.getMessage(this.getClass(),
311  "ExternalResultsXMLParser.getChildElementContent.errMsg1.text",
312  parentElement.getTagName(),
313  childElementTagName,
314  this.resultsFilePath);
315  this.recordError(errorMessage);
316  }
317  } else if (required) {
318  String errorMessage = NbBundle.getMessage(this.getClass(), "ExternalResultsXMLParser.getChildElementContent.errMsg2.text",
319  parentElement.getTagName(),
320  childElementTagName,
321  this.resultsFilePath);
322  this.recordError(errorMessage);
323  }
324  return content;
325  }
326 
327  private Element getChildElement(Element parentElement, String childElementTagName) {
328  Element childElem = null;
329  NodeList childNodes = parentElement.getElementsByTagName(childElementTagName);
330  if (childNodes.getLength() > 0) {
331  childElem = (Element) childNodes.item(0);
332  if (childNodes.getLength() > 1) {
333  String errorMessage = NbBundle.getMessage(this.getClass(), "ExternalResultsXMLParser.getChildElement.errMsg1.text",
334  childElementTagName,
335  parentElement.getTagName(),
336  this.resultsFilePath);
337  this.recordError(errorMessage);
338  }
339  }
340  return childElem;
341  }
342 
343  private void recordError(String errorMessage) {
344  ExternalResultsXMLParser.logger.log(Level.SEVERE, errorMessage);
345  this.errors.add(new ErrorInfo(this.getClass().getSimpleName(), errorMessage));
346  }
347 
348  private void recordError(String errorMessage, Exception ex) {
349  ExternalResultsXMLParser.logger.log(Level.SEVERE, errorMessage, ex);
350  this.errors.add(new ErrorInfo(this.getClass().getSimpleName(), errorMessage, ex));
351  }
352 }
static< T > Document loadDoc(Class< T > clazz, String xmlPath)
Definition: XMLUtil.java:228
String getElementAttributeValue(Element element, String attributeName)
Element getChildElement(Element parentElement, String childElementTagName)
void parseArtifactAttributes(final Element artifactElem, ExternalResults.Artifact artifact)
ExternalResultsXMLParser(Content dataSource, String resultsFilePath)
String getChildElementContent(Element parentElement, String childElementTagName, boolean required)
synchronized static Logger getLogger(String name)
Definition: Logger.java:161

Copyright © 2012-2016 Basis Technology. Generated on: Tue Oct 25 2016
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.