parse xml only if xml parseable in invoiceimporter (affecting metrics)

This commit is contained in:
Jochen Stärk
2026-03-24 13:31:24 +01:00
parent 87c5723104
commit 01c99d2d58
3 changed files with 84 additions and 51 deletions

View File

@@ -12,6 +12,11 @@ import org.dom4j.io.XMLWriter;
import org.mustangproject.ZUGFeRD.ZUGFeRDDateFormat;
import org.w3c.dom.Node;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
public class XMLTools extends XMLWriter {
@Override
public String escapeAttributeEntities(String s) {
@@ -23,6 +28,30 @@ public class XMLTools extends XMLWriter {
return super.escapeElementEntities(s);
}
public static DocumentBuilder getDocumentBuilder() throws ParserConfigurationException {
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//REDHAT
//https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
//OWASP
//https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
// Disable external DTDs as well
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
// and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks"
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);
dbf.setNamespaceAware(true);
return dbf.newDocumentBuilder();
}
public static String nDigitFormat(BigDecimal value, int scale) {
/*
* I needed 123.45, locale independent.I tried

View File

@@ -19,6 +19,8 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
@@ -29,6 +31,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class ZUGFeRDImporter extends ZUGFeRDInvoiceImporter {
private static final Logger LOGGER = LoggerFactory.getLogger(ZUGFeRDImporter.class);
@@ -472,17 +475,6 @@ public class ZUGFeRDImporter extends ZUGFeRDInvoiceImporter {
}
/**
* @return raw XML of the invoice
*/
public String getMeta() {
if (rawXML == null) {
return null;
}
return new String(rawXML, StandardCharsets.UTF_8);
}
public int getVersion() throws Exception {
if (!containsMeta) {
@@ -517,20 +509,6 @@ public class ZUGFeRDImporter extends ZUGFeRDInvoiceImporter {
}
/**
* will return true if the metadata (just extract-ed or set with setMeta) contains ZUGFeRD XML
*
* @return true if the invoice contains ZUGFeRD XML
*/
public boolean canParse() {
// SpecifiedExchangedDocumentContext is in the schema, so a relatively good
// indication if zugferd is present - better than just invoice
final String meta = getMeta();
return (meta != null) && (meta.length() > 0) && ((meta.contains("SpecifiedExchangedDocumentContext")
/* ZF1 */ || meta.contains("ExchangedDocumentContext") /* ZF2 */));
}
/**
* returns an instance of PostalTradeAddress for SellerTradeParty section

View File

@@ -311,28 +311,52 @@ public class ZUGFeRDInvoiceImporter {
setRawXML(rawXML, true);
}
private void setDocument() throws ParserConfigurationException, IOException, SAXException, ParseException {
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//REDHAT
//https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
dbf.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
//OWASP
//https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
// Disable external DTDs as well
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
// and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks"
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);
dbf.setNamespaceAware(true);
final DocumentBuilder builder = dbf.newDocumentBuilder();
/**
* @return raw XML of the invoice
*/
public String getMeta() {
if (rawXML == null) {
return null;
}
return new String(rawXML, StandardCharsets.UTF_8);
}
/**
* will return true if the metadata (just extract-ed or set with setMeta) contains ZUGFeRD XML
*
* @return true if the invoice contains ZUGFeRD XML
*/
public boolean canParse() {
// SpecifiedExchangedDocumentContext is in the schema, so a relatively good
// indication if zugferd is present - better than just invoice
final String meta = getMeta();
if ((meta == null) || (meta.length() == 0)) {
return false;
}
final ByteArrayInputStream is = new ByteArrayInputStream(rawXML);
/// is.skip(guessBOMSize(is));
try {
DocumentBuilder builder = XMLTools.getDocumentBuilder();
document = builder.parse(is);
} catch (Exception e) {
return false;
}
return ((meta.contains("SpecifiedExchangedDocumentContext")
/* ZF1 */ || meta.contains("ExchangedDocumentContext") /* ZF2 */));
}
private void setDocument() throws ParserConfigurationException, IOException, SAXException, ParseException {
final ByteArrayInputStream is = new ByteArrayInputStream(rawXML);
/// is.skip(guessBOMSize(is));
DocumentBuilder builder = XMLTools.getDocumentBuilder();
if (canParse()) {
document = builder.parse(is);
if (parseAutomatically) {
try {
@@ -342,6 +366,8 @@ public class ZUGFeRDInvoiceImporter {
throw new RuntimeException(e);
}
}
}
}
public void setID(String id) {