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;
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)
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: Mon Apr 24 2017
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.