Autopsy  3.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 2014 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  private final String text;
105 
106  private AttributeValues(final String text) {
107  this.text = text;
108  }
109 
110  @Override
111  public String toString() {
112  return this.text;
113  }
114  }
115 
121  public ExternalResultsXMLParser(Content dataSource, String resultsFilePath) {
122  this.dataSource = dataSource;
123  this.resultsFilePath = resultsFilePath;
124  }
125 
126  @Override
128  this.errors.clear();
129  this.resultsData = new ExternalResults(dataSource);
130  try {
131  // Note that XMLUtil.loadDoc() logs a warning if the file does not
132  // conform to the XSD, but still returns a Document object. Until
133  // this behavior is improved, validation is still required. If
134  // XMLUtil.loadDoc() does return null, it failed to load the
135  // document and it logged the error.
136  final Document doc = XMLUtil.loadDoc(ExternalResultsXMLParser.class, this.resultsFilePath, XSD_FILE);
137  if (doc != null) {
138  final Element rootElem = doc.getDocumentElement();
139  if (rootElem != null && rootElem.getNodeName().equals(TagNames.ROOT_ELEM.toString())) {
140  parseDerivedFiles(rootElem);
141  parseArtifacts(rootElem);
142  parseReports(rootElem);
143  } else {
144  String errorMessage = NbBundle.getMessage(this.getClass(),
145  "ExternalResultsXMLParser.parse.errMsg1.text",
146  TagNames.ROOT_ELEM.toString(), this.resultsFilePath);
147  recordError(errorMessage);
148  }
149  }
150  } catch (Exception ex) {
151  String errorMessage = NbBundle.getMessage(this.getClass(), "ExternalResultsXMLParser.parse.errMsg2.text", this.resultsFilePath);
152  recordError(errorMessage, ex);
153  }
154  return this.resultsData;
155  }
156 
157  @Override
158  public List<ErrorInfo> getErrorInfo() {
159  return new ArrayList<>(this.errors);
160  }
161 
162  private void parseDerivedFiles(Element rootElement) {
163  // Get the derived file lists.
164  NodeList derivedFilesListNodes = rootElement.getElementsByTagName(TagNames.DERIVED_FILES_LIST_ELEM.toString());
165  for (int i = 0; i < derivedFilesListNodes.getLength(); ++i) {
166  Element derivedFilesListElem = (Element) derivedFilesListNodes.item(i);
167  // Get the derived files.
168  NodeList derivedFileNodes = derivedFilesListElem.getElementsByTagName(TagNames.DERIVED_FILE_ELEM.toString());
169  for (int j = 0; j < derivedFileNodes.getLength(); ++j) {
170  Element derivedFileElem = (Element) derivedFileNodes.item(j);
171  // Get the local path of the derived file.
172  String path = getChildElementContent(derivedFileElem, TagNames.LOCAL_PATH_ELEM.toString(), true);
173  if (path.isEmpty()) {
174  continue;
175  }
176  // Get the parent file of the derived file.
177  String parentFile = getChildElementContent((Element) derivedFileNodes.item(j), TagNames.PARENT_FILE_ELEM.toString(), true);
178  if (parentFile.isEmpty()) {
179  continue;
180  }
181  this.resultsData.addDerivedFile(path, parentFile);
182  }
183  }
184  }
185 
186  private void parseArtifacts(final Element root) {
187  // Get the artifact lists.
188  NodeList artifactsListNodes = root.getElementsByTagName(TagNames.ARTIFACTS_LIST_ELEM.toString());
189  for (int i = 0; i < artifactsListNodes.getLength(); ++i) {
190  Element artifactsListElem = (Element) artifactsListNodes.item(i);
191  // Get the artifacts.
192  NodeList artifactNodes = artifactsListElem.getElementsByTagName(TagNames.ARTIFACT_ELEM.toString());
193  for (int j = 0; j < artifactNodes.getLength(); ++j) {
194  Element artifactElem = (Element) artifactNodes.item(j);
195  // Get the artifact type.
196  final String type = getElementAttributeValue(artifactElem, AttributeNames.TYPE_ATTR.toString());
197  if (!type.isEmpty()) {
198  // Get the source file of the artifact and the attributes,
199  // if any.
200  final String sourceFilePath = this.getChildElementContent( artifactElem, TagNames.SOURCE_FILE_ELEM.toString(), true);
201  if (!sourceFilePath.isEmpty()) {
202  ExternalResults.Artifact artifact = this.resultsData.addArtifact(type, sourceFilePath);
203  parseArtifactAttributes(artifactElem, artifact);
204  }
205  }
206  }
207  }
208  }
209 
210  private void parseArtifactAttributes(final Element artifactElem, ExternalResults.Artifact artifact) {
211  // Get the artifact attributes.
212  NodeList attributeNodesList = artifactElem.getElementsByTagName(TagNames.ATTRIBUTE_ELEM.toString());
213  for (int i = 0; i < attributeNodesList.getLength(); ++i) {
214  Element attributeElem = (Element) attributeNodesList.item(i);
215  final String type = getElementAttributeValue(attributeElem, AttributeNames.TYPE_ATTR.toString());
216  if (type.isEmpty()) {
217  continue;
218  }
219  // Get the value of the artifact attribute.
220  Element valueElem = this.getChildElement(attributeElem, TagNames.VALUE_ELEM.toString());
221  if (valueElem == null) {
222  continue;
223  }
224  final String value = valueElem.getTextContent();
225  if (value.isEmpty()) {
226  String errorMessage = NbBundle.getMessage(this.getClass(),
227  "ExternalResultsXMLParser.parseArtifactAttributes.errMsg1.text",
228  TagNames.VALUE_ELEM.toString(), this.resultsFilePath);
229  recordError(errorMessage);
230  continue;
231  }
232  // Get the value type.
233  String valueType = parseArtifactAttributeValueType(valueElem);
234  if (valueType.isEmpty()) {
235  continue;
236  }
237  // Get the optional source module.
238  String sourceModule = this.getChildElementContent(attributeElem, TagNames.SOURCE_MODULE_ELEM.toString(), false);
239  // Add the attribute to the artifact.
240  artifact.addAttribute(type, value, valueType, sourceModule);
241  }
242  }
243 
244  private String parseArtifactAttributeValueType(Element valueElem) {
245  String valueType = valueElem.getAttribute(AttributeNames.TYPE_ATTR.toString());
246  if (valueType.isEmpty()) {
247  // Default to text.
248  valueType = AttributeValues.VALUE_TYPE_TEXT.toString();
249  } else if (!valueType.equals(AttributeValues.VALUE_TYPE_TEXT.toString())
250  && !valueType.equals(AttributeValues.VALUE_TYPE_DOUBLE.toString())
251  && !valueType.equals(AttributeValues.VALUE_TYPE_INT32.toString())
252  && !valueType.equals(AttributeValues.VALUE_TYPE_INT64.toString())) {
253  String errorMessage = NbBundle.getMessage(this.getClass(),
254  "ExternalResultsXMLParser.parseAttributeValueType.errMsg1.text",
255  valueType,
256  AttributeNames.TYPE_ATTR.toString(),
257  TagNames.VALUE_ELEM.toString());
258  this.recordError(errorMessage);
259  valueType = "";
260  }
261  return valueType;
262  }
263 
264  private void parseReports(Element root) {
265  // Get the report lists.
266  NodeList reportsListNodes = root.getElementsByTagName(TagNames.REPORTS_LIST_ELEM.toString());
267  for (int i = 0; i < reportsListNodes.getLength(); ++i) {
268  Element reportsListElem = (Element) reportsListNodes.item(i);
269  // Get the reports.
270  NodeList reportNodes = reportsListElem.getElementsByTagName(TagNames.REPORT_ELEM.toString());
271  for (int j = 0; j < reportNodes.getLength(); ++j) {
272  Element reportElem = (Element) reportNodes.item(j);
273  // Get the local path.
274  String path = getChildElementContent(reportElem, TagNames.LOCAL_PATH_ELEM.toString(), true);
275  if (path.isEmpty()) {
276  continue;
277  }
278  // Get the source module.
279  String sourceModule = getChildElementContent(reportElem, TagNames.SOURCE_MODULE_ELEM.toString(), true);
280  if (path.isEmpty()) {
281  continue;
282  }
283  // Get the optional report name.
284  String reportName = getChildElementContent(reportElem, TagNames.REPORT_NAME_ELEM.toString(), false);
285  this.resultsData.addReport(path, sourceModule, reportName);
286  }
287  }
288  }
289 
290  private String getElementAttributeValue(Element element, String attributeName) {
291  final String attributeValue = element.getAttribute(attributeName);
292  if (attributeValue.isEmpty()) {
293  logger.log(Level.SEVERE, "Found {0} element missing {1} attribute in {2}", new Object[]{ //NON-NLS
294  element.getTagName(),
295  attributeName,
296  this.resultsFilePath});
297  }
298  return attributeValue;
299  }
300 
301  private String getChildElementContent(Element parentElement, String childElementTagName, boolean required) {
302  String content = "";
303  Element childElement = this.getChildElement(parentElement, childElementTagName);
304  if (childElement != null) {
305  content = childElement.getTextContent();
306  if (content.isEmpty()) {
307  String errorMessage = NbBundle.getMessage(this.getClass(),
308  "ExternalResultsXMLParser.getChildElementContent.errMsg1.text",
309  parentElement.getTagName(),
310  childElementTagName,
311  this.resultsFilePath);
312  this.recordError(errorMessage);
313  }
314  } else if (required) {
315  String errorMessage = NbBundle.getMessage(this.getClass(), "ExternalResultsXMLParser.getChildElementContent.errMsg2.text",
316  parentElement.getTagName(),
317  childElementTagName,
318  this.resultsFilePath);
319  this.recordError(errorMessage);
320  }
321  return content;
322  }
323 
324  private Element getChildElement(Element parentElement, String childElementTagName) {
325  Element childElem = null;
326  NodeList childNodes = parentElement.getElementsByTagName(childElementTagName);
327  if (childNodes.getLength() > 0) {
328  childElem = (Element) childNodes.item(0);
329  if (childNodes.getLength() > 1) {
330  String errorMessage = NbBundle.getMessage(this.getClass(), "ExternalResultsXMLParser.getChildElement.errMsg1.text",
331  childElementTagName,
332  parentElement.getTagName(),
333  this.resultsFilePath);
334  this.recordError(errorMessage);
335  }
336  }
337  return childElem;
338  }
339 
340  private void recordError(String errorMessage) {
341  ExternalResultsXMLParser.logger.log(Level.SEVERE, errorMessage);
342  this.errors.add(new ErrorInfo(this.getClass().getSimpleName(), errorMessage));
343  }
344 
345  private void recordError(String errorMessage, Exception ex) {
346  ExternalResultsXMLParser.logger.log(Level.SEVERE, errorMessage, ex);
347  this.errors.add(new ErrorInfo(this.getClass().getSimpleName(), errorMessage, ex));
348  }
349 }
static< T > Document loadDoc(Class< T > clazz, String xmlPath)
Definition: XMLUtil.java:221
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)
static Logger getLogger(String name)
Definition: Logger.java:131

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