All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.idsec.sigval.xml.utils.XMLDocumentBuilder Maven / Gradle / Ivy

/*
 * Copyright (c) 2020. IDsec Solutions AB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package se.idsec.sigval.xml.utils;

import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;

/**
 * Safe document builder class for parsing XML data but also providing some function for converting XML documents back to text
 *
 * @author Martin Lindström ([email protected])
 * @author Stefan Santesson ([email protected])
 */
@Slf4j
public class XMLDocumentBuilder {

  private static Transformer trans;
  private static Transformer transformer;
  private static DocumentBuilderFactory safeDocBuilderFactory;

  static {
    /**
     * This document builder factory is created in line with recommendations by OWASP
     * 

https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#JAXP_DocumentBuilderFactory.2C_SAXParserFactory_and_DOM4J

* This Document builder disables the use of DTD and mitigates XEE attack threats */ safeDocBuilderFactory = DocumentBuilderFactory.newInstance(); safeDocBuilderFactory.setNamespaceAware(true); //safeDocBuilderFactory.setValidating(true); try { safeDocBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); safeDocBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false); safeDocBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); safeDocBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); safeDocBuilderFactory.setXIncludeAware(false); safeDocBuilderFactory.setExpandEntityReferences(false); } catch (ParserConfigurationException ex) { log.error("Error setting up safe document builder factory", ex); } TransformerFactory tf = TransformerFactory.newInstance(); try { trans = tf.newTransformer(); transformer = tf.newTransformer(); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); //transformer.setOutputProperty(OutputKeys.STANDALONE, "no"); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); } catch (Exception ex) { log.error("Error setting up transformer", ex); } } /** * Generates a pretty XML print of an XML document based on java.xml * functions. * * @param doc The doc being processed * @return Test representation of the XML document * @throws IOException errors parsing document */ public static String getDocText(Document doc) throws IOException { if (doc == null) { return null; } DOMSource domSource = new DOMSource(doc); try { java.io.StringWriter sw = new java.io.StringWriter(); StreamResult sr = new StreamResult(sw); transformer.transform(domSource, sr); String xml = sw.toString(); return xml; } catch (Exception ex) { throw new IOException("Error parsing XML document", ex); } } /** * Provides a canonical print of the XML document. The purpose of this print * is to try to preserve integrity of an existing signature. * * @param doc The XML document being processed. * @return XML String */ /** * Provides a canonical print of the XML document. The purpose of this print * is to try to preserve integrity of an existing signature. * * @param doc The XML document being processed. * @return The bytes of the xml document * @throws TransformerException transformer error */ public static byte[] getCanonicalDocBytes(Document doc) throws TransformerException { ByteArrayOutputStream os = new ByteArrayOutputStream(); trans.transform(new DOMSource(doc), new StreamResult(os)); byte[] xmlData = os.toByteArray(); return xmlData; } /** * Returns an XML document from a safe document builder process * @param xmlData XML document bytes * @return XML document * @throws IOException On IO errors * @throws SAXException Error parsing XML content * @throws ParserConfigurationException Error in configuration of the parser */ public static Document getDocument(byte[] xmlData) throws IOException, SAXException, ParserConfigurationException { Document doc = safeDocBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(xmlData)); return doc; } /** * Parse an XML file and returns an XML document * * @param xmlFile The XML file being parsed * @return XML Document * @throws IOException On IO errors * @throws SAXException Error parsing XML content * @throws ParserConfigurationException Error in configuration of the parser */ public static Document loadXMLContent(File xmlFile) throws IOException, ParserConfigurationException, SAXException { Document doc; InputStream is = new FileInputStream(xmlFile); doc = safeDocBuilderFactory.newDocumentBuilder().parse(is); doc.getDocumentElement().normalize(); return doc; } /** * Parse an XML file and returns an XML string * * @param xmlFile The XML file being parsed * @return XML String * @throws ParserConfigurationException parser configuration errors * @throws SAXException XML parsing errors * @throws IOException other data parsing errors */ public static String getParsedXMLText(File xmlFile) throws ParserConfigurationException, SAXException, IOException { return getDocText(loadXMLContent(xmlFile)); } /** * Getter for a safe document builder factory * @return safe document builder factory */ public static DocumentBuilderFactory getDbFactory() { return safeDocBuilderFactory; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy