Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
XMLUtil.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2012-2020 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 */
19package org.sleuthkit.autopsy.coreutils;
20
21import java.io.File;
22import java.io.FileInputStream;
23import java.io.FileNotFoundException;
24import java.io.FileOutputStream;
25import java.io.IOException;
26import java.io.OutputStreamWriter;
27import java.io.UnsupportedEncodingException;
28import java.nio.file.Paths;
29import java.util.logging.Level;
30import javax.xml.XMLConstants;
31import javax.xml.parsers.DocumentBuilder;
32import javax.xml.parsers.DocumentBuilderFactory;
33import javax.xml.parsers.ParserConfigurationException;
34import javax.xml.transform.OutputKeys;
35import javax.xml.transform.Result;
36import javax.xml.transform.Transformer;
37import javax.xml.transform.TransformerConfigurationException;
38import javax.xml.transform.TransformerException;
39import javax.xml.transform.TransformerFactory;
40import javax.xml.transform.dom.DOMResult;
41import javax.xml.transform.dom.DOMSource;
42import javax.xml.transform.stream.StreamResult;
43import javax.xml.validation.Schema;
44import javax.xml.validation.SchemaFactory;
45import javax.xml.validation.Validator;
46import org.w3c.dom.Document;
47import org.xml.sax.SAXException;
48
56public class XMLUtil {
57
58 static {
59 // this is to ensure using xalan for the transformer factory: https://stackoverflow.com/a/64364531/2375948
60 System.setProperty("javax.xml.transform.TransformerFactory","com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
61 }
62
63 public static DocumentBuilder getDocumentBuilder() throws ParserConfigurationException {
64 // See JIRA-6958 for details about class loading and jaxb.
65 ClassLoader original = Thread.currentThread().getContextClassLoader();
66 try {
67 Thread.currentThread().setContextClassLoader(XMLUtil.class.getClassLoader());
68 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
69 // Explicitly disable external entity loading and DOCTYPE to prevent XXE injection.
70 builderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); //NON-NLS
71 builderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
72 builderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false); //NON-NLS
73 builderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); //NON-NLS
74 builderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); //NON-NLS
75 builderFactory.setXIncludeAware(false);
76 builderFactory.setExpandEntityReferences(false);
77 return builderFactory.newDocumentBuilder();
78 } finally {
79 Thread.currentThread().setContextClassLoader(original);
80 }
81 }
82
83 private static SchemaFactory getSchemaFactory(String schemaLanguage) {
84 return SchemaFactory.newInstance(schemaLanguage);
85 }
86
87 private static TransformerFactory getTransformerFactory() {
88 // See JIRA-6958 for details about class loading and jaxb.
89 ClassLoader original = Thread.currentThread().getContextClassLoader();
90 try {
91 Thread.currentThread().setContextClassLoader(XMLUtil.class.getClassLoader());
92 return TransformerFactory.newInstance();
93 } finally {
94 Thread.currentThread().setContextClassLoader(original);
95 }
96 }
97
105 public static Document createDocument() throws ParserConfigurationException {
106 return getDocumentBuilder().newDocument();
107 }
108
123 public static <T> Document loadDocument(String docPath, Class<T> clazz, String schemaResourceName) throws IOException, ParserConfigurationException, SAXException {
124 Document doc = loadDocument(docPath);
125 validateDocument(doc, clazz, schemaResourceName);
126 return doc;
127 }
128
140 public static Document loadDocument(String docPath) throws ParserConfigurationException, SAXException, IOException {
141 DocumentBuilder builder = getDocumentBuilder();
142 Document doc = builder.parse(new FileInputStream(docPath));
143 return doc;
144 }
145
156 public static <T> void validateDocument(final Document doc, Class<T> clazz, String schemaResourceName) throws SAXException, IOException {
157 PlatformUtil.extractResourceToUserConfigDir(clazz, schemaResourceName, false);
158 File schemaFile = new File(Paths.get(PlatformUtil.getUserConfigDirectory(), schemaResourceName).toAbsolutePath().toString());
159 SchemaFactory schemaFactory = getSchemaFactory(XMLConstants.W3C_XML_SCHEMA_NS_URI);
160 Schema schema = schemaFactory.newSchema(schemaFile);
161 Validator validator = schema.newValidator();
162 validator.validate(new DOMSource(doc), new DOMResult());
163 }
164
179 public static void saveDocument(final Document doc, String encoding, String docPath) throws TransformerConfigurationException, FileNotFoundException, UnsupportedEncodingException, TransformerException, IOException {
180 TransformerFactory xf = getTransformerFactory();
181 xf.setAttribute("indent-number", 1); //NON-NLS
182 Transformer xformer = xf.newTransformer();
183 xformer.setOutputProperty(OutputKeys.METHOD, "xml"); //NON-NLS
184 xformer.setOutputProperty(OutputKeys.INDENT, "yes"); //NON-NLS
185 xformer.setOutputProperty(OutputKeys.ENCODING, encoding);
186 xformer.setOutputProperty(OutputKeys.STANDALONE, "yes"); //NON-NLS
187 xformer.setOutputProperty(OutputKeys.VERSION, "1.0");
188 File file = new File(docPath);
189 try (FileOutputStream stream = new FileOutputStream(file)) {
190 Result out = new StreamResult(new OutputStreamWriter(stream, encoding));
191 xformer.transform(new DOMSource(doc), out);
192 stream.flush();
193 }
194 }
195
213 // TODO: Deprecate.
214 public static <T> boolean xmlIsValid(DOMSource xmlfile, Class<T> clazz, String schemaFile) {
215 try {
216 PlatformUtil.extractResourceToUserConfigDir(clazz, schemaFile, false);
217 File schemaLoc = new File(PlatformUtil.getUserConfigDirectory() + File.separator + schemaFile);
218 SchemaFactory schm = getSchemaFactory(XMLConstants.W3C_XML_SCHEMA_NS_URI);
219 try {
220 Schema schema = schm.newSchema(schemaLoc);
221 Validator validator = schema.newValidator();
222 DOMResult result = new DOMResult();
223 validator.validate(xmlfile, result);
224 return true;
225 } catch (SAXException e) {
226 Logger.getLogger(clazz.getName()).log(Level.WARNING, "Unable to validate XML file.", e); //NON-NLS
227 return false;
228 }
229 } catch (IOException e) {
230 Logger.getLogger(clazz.getName()).log(Level.WARNING, "Unable to load XML file [" + xmlfile.toString() + "] of type [" + schemaFile + "]", e); //NON-NLS
231 return false;
232 }
233 }
234
252 // TODO: Deprecate.
253 public static <T> boolean xmlIsValid(Document doc, Class<T> clazz, String type) {
254 DOMSource dms = new DOMSource(doc);
255 return xmlIsValid(dms, clazz, type);
256 }
257
264 // TODO: Deprecate.
265 public static <T> Document loadDoc(Class<T> clazz, String xmlPath) {
266 Document ret = null;
267 try {
268 DocumentBuilder builder = getDocumentBuilder();
269 ret = builder.parse(new FileInputStream(xmlPath));
270 } catch (ParserConfigurationException e) {
271 Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error loading XML file " + xmlPath + " : can't initialize parser.", e); //NON-NLS
272 } catch (SAXException e) {
273 Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error loading XML file " + xmlPath + " : can't parse XML.", e); //NON-NLS
274 } catch (IOException e) {
275 //error reading file
276 Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error loading XML file " + xmlPath + " : can't read file.", e); //NON-NLS
277 }
278 return ret;
279 }
280
288 // TODO: Deprecate
289 public static <T> Document loadDoc(Class<T> clazz, String xmlPath, String xsdPath) {
290 Document ret = loadDoc(clazz, xmlPath);
291 if (!XMLUtil.xmlIsValid(ret, clazz, xsdPath)) {
292 Logger.getLogger(clazz.getName()).log(Level.WARNING, "Error loading XML file: could not validate against [{0}], results may not be accurate", xsdPath); //NON-NLS
293 }
294 return ret;
295 }
296
305 // TODO: Deprecate.
306 public static <T> boolean saveDoc(Class<T> clazz, String xmlPath, String encoding, final Document doc) {
307 TransformerFactory xf = getTransformerFactory();
308 xf.setAttribute("indent-number", 1); //NON-NLS
309 boolean success = false;
310 try {
311 Transformer xformer = xf.newTransformer();
312 xformer.setOutputProperty(OutputKeys.METHOD, "xml"); //NON-NLS
313 xformer.setOutputProperty(OutputKeys.INDENT, "yes"); //NON-NLS
314 xformer.setOutputProperty(OutputKeys.ENCODING, encoding);
315 xformer.setOutputProperty(OutputKeys.STANDALONE, "yes"); //NON-NLS
316 xformer.setOutputProperty(OutputKeys.VERSION, "1.0");
317 File file = new File(xmlPath);
318 try (FileOutputStream stream = new FileOutputStream(file)) {
319 Result out = new StreamResult(new OutputStreamWriter(stream, encoding));
320 xformer.transform(new DOMSource(doc), out);
321 stream.flush();
322 }
323 success = true;
324
325 } catch (UnsupportedEncodingException e) {
326 Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Should not happen", e); //NON-NLS
327 } catch (TransformerConfigurationException e) {
328 Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error writing XML file", e); //NON-NLS
329 } catch (TransformerException e) {
330 Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error writing XML file", e); //NON-NLS
331 } catch (FileNotFoundException e) {
332 Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error writing XML file: cannot write to file: " + xmlPath, e); //NON-NLS
333 } catch (IOException e) {
334 Logger.getLogger(clazz.getName()).log(Level.SEVERE, "Error writing XML file: cannot write to file: " + xmlPath, e); //NON-NLS
335 }
336 return success;
337 }
338
339}
synchronized static Logger getLogger(String name)
Definition Logger.java:124
static< T > boolean extractResourceToUserConfigDir(final Class< T > resourceClass, final String resourceFileName, boolean overWrite)
static< T > Document loadDocument(String docPath, Class< T > clazz, String schemaResourceName)
Definition XMLUtil.java:123
static Document loadDocument(String docPath)
Definition XMLUtil.java:140
static< T > void validateDocument(final Document doc, Class< T > clazz, String schemaResourceName)
Definition XMLUtil.java:156
static< T > Document loadDoc(Class< T > clazz, String xmlPath, String xsdPath)
Definition XMLUtil.java:289
static TransformerFactory getTransformerFactory()
Definition XMLUtil.java:87
static SchemaFactory getSchemaFactory(String schemaLanguage)
Definition XMLUtil.java:83
static< T > Document loadDoc(Class< T > clazz, String xmlPath)
Definition XMLUtil.java:265
static< T > boolean xmlIsValid(DOMSource xmlfile, Class< T > clazz, String schemaFile)
Definition XMLUtil.java:214
static DocumentBuilder getDocumentBuilder()
Definition XMLUtil.java:63
static void saveDocument(final Document doc, String encoding, String docPath)
Definition XMLUtil.java:179
static< T > boolean xmlIsValid(Document doc, Class< T > clazz, String type)
Definition XMLUtil.java:253
static< T > boolean saveDoc(Class< T > clazz, String xmlPath, String encoding, final Document doc)
Definition XMLUtil.java:306

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.