Merge branch 'master' into merge-to-master
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
- #722
|
||||
- #774
|
||||
|
||||
2.16.3
|
||||
=======
|
||||
2025-03-03
|
||||
|
||||
@@ -307,12 +307,13 @@ public class Main {
|
||||
// Plain Java
|
||||
// based on https://mkyong.com/java/how-to-convert-inputstream-to-string-in-java/
|
||||
private static String convertInputStreamToString(InputStream is) {
|
||||
try (InputStream inputStream = is) {
|
||||
int DEFAULT_BUFFER_SIZE = 8192;
|
||||
ByteArrayOutputStream result = new ByteArrayOutputStream();
|
||||
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
|
||||
int length;
|
||||
try {
|
||||
while ((length = is.read(buffer)) != -1) {
|
||||
|
||||
while ((length = inputStream.read(buffer)) != -1) {
|
||||
result.write(buffer, 0, length);
|
||||
}
|
||||
|
||||
@@ -320,11 +321,10 @@ public class Main {
|
||||
return result.toString(StandardCharsets.UTF_8.name());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
// Java 10
|
||||
// return result.toString(StandardCharsets.UTF_8);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
|
||||
29
SECURITY.md
Normal file
29
SECURITY.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
The following versions are currently being supported with security updates.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 2.x.x | :white_check_mark: |
|
||||
| < 2.0 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Feel free to submit issues to info at mustangproject.org with [security] indicated in the subject.
|
||||
We may ask back questions but we usually open (or communicate about) an issue (potentially in a private location you would be provided with access to) and decide on the severity within two working days.
|
||||
|
||||
Please indicate
|
||||
* a proof of concept, if possible
|
||||
* If any of the information you submit, e.g. an invoice which can not be [anonymized](https://github.com/ZUGFeRD/einvoice-anonymizer), is confidential
|
||||
* A quick justification why you require a fix in a older version than he most up to date one, if you can not update to the most recent version
|
||||
* If you require encrypted communication (our GPG fingerprint will likely be 68F4 2269 8165 F0F5 63CA A13B 7CB7 1548 B596 66A3)
|
||||
|
||||
|
||||
## After your Report
|
||||
|
||||
We try to fix critical issues in less than a week, and release a fixed version in less than two weeks.
|
||||
|
||||
Thank you for keeping our software safe!
|
||||
|
||||
@@ -158,7 +158,6 @@ public class Invoice implements IExportableTransaction {
|
||||
*/
|
||||
public Invoice setCorrection(String number) {
|
||||
setInvoiceReferencedDocumentID(number);
|
||||
addInvoiceReferencedDocument(new ReferencedDocument(number));
|
||||
documentCode = DocumentCodeTypeConstants.CORRECTEDINVOICE;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -220,7 +220,8 @@ public class XMLTools extends XMLWriter {
|
||||
}
|
||||
|
||||
public static byte[] getBytesFromStream(InputStream fileinput) throws IOException {
|
||||
return IOUtils.toByteArray (fileinput);
|
||||
// Stream closing responsibility is with the caller
|
||||
return IOUtils.toByteArray(fileinput);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import java.util.Map;
|
||||
|
||||
import org.mustangproject.EStandard;
|
||||
import org.mustangproject.FileAttachment;
|
||||
import org.mustangproject.ReferencedDocument;
|
||||
import org.mustangproject.XMLTools;
|
||||
|
||||
public class OXPullProvider extends ZUGFeRD2PullProvider {
|
||||
@@ -460,7 +461,7 @@ public class OXPullProvider extends ZUGFeRD2PullProvider {
|
||||
xml += "</ram:InvoiceReferencedDocument>";
|
||||
}
|
||||
if (trans.getInvoiceReferencedDocuments() != null) {
|
||||
for (var doc : trans.getInvoiceReferencedDocuments()) {
|
||||
for (ReferencedDocument doc : trans.getInvoiceReferencedDocuments()) {
|
||||
xml += "<ram:InvoiceReferencedDocument>"
|
||||
+ "<ram:IssuerAssignedID>"
|
||||
+ XMLTools.encodeXML(doc.getIssuerAssignedID()) + "</ram:IssuerAssignedID>";
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
package org.mustangproject.ZUGFeRD;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.StringReader;
|
||||
import org.apache.fop.apps.*;
|
||||
import org.apache.fop.apps.io.ResourceResolverFactory;
|
||||
import org.apache.fop.configuration.Configuration;
|
||||
@@ -10,11 +18,12 @@ import org.mustangproject.ClasspathResolverURIAdapter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.transform.*;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.*;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class ValidationLogVisualizer {
|
||||
@@ -70,7 +79,7 @@ public class ValidationLogVisualizer {
|
||||
return baos.toString(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public void toPDF(String xmlLogfileContent, String pdfFilename) {
|
||||
public byte[] createPDFBytes(String xmlLogfileContent) {
|
||||
|
||||
// the writing part
|
||||
|
||||
@@ -111,13 +120,19 @@ public class ValidationLogVisualizer {
|
||||
// Step 2: Set up output stream.
|
||||
// Note: Using BufferedOutputStream for performance reasons (helpful with FileOutputStreams).
|
||||
|
||||
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(pdfFilename))) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (OutputStream out = new BufferedOutputStream(baos)) {
|
||||
|
||||
// Step 3: Construct fop with desired output format
|
||||
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent, out);
|
||||
|
||||
// Step 4: Setup JAXP using identity transformer
|
||||
TransformerFactory factory = TransformerFactory.newInstance();
|
||||
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
Transformer transformer = factory.newTransformer(); // identity transformer
|
||||
|
||||
// Step 5: Setup input and output for XSLT transformation
|
||||
@@ -133,6 +148,20 @@ public class ValidationLogVisualizer {
|
||||
} catch (FOPException | IOException | TransformerException e) {
|
||||
LOGGER.error("Failed to create PDF", e);
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
public byte[] toPDF(String xmlLogfileContent) {
|
||||
return createPDFBytes(xmlLogfileContent);
|
||||
}
|
||||
|
||||
public void toPDF(String xmlLogfileContent, String pdfFilename) {
|
||||
byte[] pdfData = createPDFBytes(xmlLogfileContent);
|
||||
try (FileOutputStream fos = new FileOutputStream(pdfFilename)) {
|
||||
fos.write(pdfData);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Failed to write PDF to file", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ClasspathResourceURIResolver implements URIResolver {
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.mustangproject.FileAttachment;
|
||||
import org.mustangproject.IncludedNote;
|
||||
import org.mustangproject.ReferencedDocument;
|
||||
import org.mustangproject.XMLTools;
|
||||
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
|
||||
import org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants;
|
||||
@@ -343,8 +344,6 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
boolean hasDueDate = trans.getDueDate() != null;
|
||||
final SimpleDateFormat germanDateFormat = new SimpleDateFormat("dd.MM.yyyy");
|
||||
|
||||
String exemptionReason = "";
|
||||
|
||||
if (trans.getPaymentTermDescription() != null) {
|
||||
paymentTermsDescription = XMLTools.encodeXML(trans.getPaymentTermDescription());
|
||||
}
|
||||
@@ -410,9 +409,6 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
if (currentItem.getId() != null) {
|
||||
lineIDStr = currentItem.getId();
|
||||
}
|
||||
if (currentItem.getProduct().getTaxExemptionReason() != null) {
|
||||
exemptionReason = "<ram:ExemptionReason>" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + "</ram:ExemptionReason>";
|
||||
}
|
||||
final LineCalculator lc = new LineCalculator(currentItem);
|
||||
if ((getProfile() != Profiles.getByName("Minimum")) && (getProfile() != Profiles.getByName("BasicWL"))) {
|
||||
xml += "<ram:IncludedSupplyChainTradeLineItem>" +
|
||||
@@ -533,9 +529,11 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
+ "</ram:SpecifiedLineTradeDelivery>"
|
||||
+ "<ram:SpecifiedLineTradeSettlement>"
|
||||
+ "<ram:ApplicableTradeTax>"
|
||||
+ "<ram:TypeCode>VAT</ram:TypeCode>"
|
||||
+ exemptionReason
|
||||
+ "<ram:CategoryCode>" + currentItem.getProduct().getTaxCategoryCode() + "</ram:CategoryCode>";
|
||||
+ "<ram:TypeCode>VAT</ram:TypeCode>";
|
||||
if (currentItem.getProduct().getTaxExemptionReason() != null) {
|
||||
xml += "<ram:ExemptionReason>" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + "</ram:ExemptionReason>";
|
||||
}
|
||||
xml += "<ram:CategoryCode>" + currentItem.getProduct().getTaxCategoryCode() + "</ram:CategoryCode>";
|
||||
if (!currentItem.getProduct().getTaxCategoryCode().equals(TaxCategoryCodeTypeConstants.UNTAXEDSERVICE)) {
|
||||
xml += "<ram:RateApplicablePercent>"
|
||||
+ vatFormat(currentItem.getProduct().getVATPercent()) + "</ram:RateApplicablePercent>";
|
||||
@@ -905,7 +903,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
xml += "</ram:InvoiceReferencedDocument>";
|
||||
}
|
||||
if (trans.getInvoiceReferencedDocuments() != null) {
|
||||
for (var doc : trans.getInvoiceReferencedDocuments()) {
|
||||
for (ReferencedDocument doc : trans.getInvoiceReferencedDocuments()) {
|
||||
xml += "<ram:InvoiceReferencedDocument>"
|
||||
+ "<ram:IssuerAssignedID>"
|
||||
+ XMLTools.encodeXML(doc.getIssuerAssignedID()) + "</ram:IssuerAssignedID>";
|
||||
|
||||
@@ -90,10 +90,11 @@ public class ZUGFeRDExporterFromPDFA implements IZUGFeRDExporter {
|
||||
|
||||
protected byte[] inputstreamToByteArray(InputStream fileInputStream) throws IOException {
|
||||
byte[] bytes = new byte[fileInputStream.available()];
|
||||
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
|
||||
try (DataInputStream dataInputStream = new DataInputStream(fileInputStream)) {
|
||||
dataInputStream.readFully(bytes);
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
*
|
||||
|
||||
@@ -138,9 +138,9 @@ public class ZUGFeRDInvoiceImporter {
|
||||
return;
|
||||
}
|
||||
|
||||
final InputStream XMP = doc.getDocumentCatalog().getMetadata().exportXMPMetadata();
|
||||
|
||||
try (final InputStream XMP = doc.getDocumentCatalog().getMetadata().exportXMPMetadata()) {
|
||||
xmpString = new String(XMLTools.getBytesFromStream(XMP), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
final PDEmbeddedFilesNameTreeNode etn = names.getEmbeddedFiles();
|
||||
if (etn == null) {
|
||||
@@ -260,12 +260,23 @@ public class ZUGFeRDInvoiceImporter {
|
||||
|
||||
private void setDocument() throws ParserConfigurationException, IOException, SAXException, ParseException {
|
||||
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setNamespaceAware(true);
|
||||
dbf.setExpandEntityReferences(false);
|
||||
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
//REDHAT
|
||||
//https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf
|
||||
dbf.setAttribute(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();
|
||||
final ByteArrayInputStream is = new ByteArrayInputStream(rawXML);
|
||||
/// is.skip(guessBOMSize(is));
|
||||
|
||||
@@ -102,12 +102,23 @@ public class ZUGFeRDVisualizer {
|
||||
String cioSignature = "SCRDMCCBDACIOMessageStructure";
|
||||
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setNamespaceAware(true);
|
||||
dbf.setExpandEntityReferences(false);
|
||||
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
//REDHAT
|
||||
//https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf
|
||||
dbf.setAttribute(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);
|
||||
try {
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
Document doc = db.parse(new InputSource(fis));
|
||||
@@ -131,9 +142,10 @@ public class ZUGFeRDVisualizer {
|
||||
|
||||
public String visualize(String xmlFilename, Language lang)
|
||||
throws IOException, TransformerException, ParserConfigurationException {
|
||||
FileInputStream fis = new FileInputStream(xmlFilename);
|
||||
try (FileInputStream fis = new FileInputStream(xmlFilename)) {
|
||||
return visualize(fis, lang);
|
||||
}
|
||||
}
|
||||
|
||||
public String visualize(InputStream inputXml, Language lang)
|
||||
throws IOException, TransformerException, ParserConfigurationException {
|
||||
@@ -222,13 +234,15 @@ public class ZUGFeRDVisualizer {
|
||||
|
||||
protected String toFOP(String xmlFilename)
|
||||
throws IOException, TransformerException, ParserConfigurationException {
|
||||
EStandard theStandard;
|
||||
try (FileInputStream fis = new FileInputStream(xmlFilename)) {
|
||||
theStandard = findOutStandardFromRootNode(fis);
|
||||
}
|
||||
|
||||
FileInputStream fis = new FileInputStream(xmlFilename);
|
||||
EStandard theStandard = findOutStandardFromRootNode(fis);
|
||||
fis = new FileInputStream(xmlFilename);//rewind :-(
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(xmlFilename)) {
|
||||
return toFOP(fis, theStandard);
|
||||
}
|
||||
}
|
||||
|
||||
protected String toFOP(InputStream is, EStandard theStandard)
|
||||
throws TransformerException, IOException {
|
||||
@@ -356,6 +370,10 @@ public class ZUGFeRDVisualizer {
|
||||
|
||||
// Step 4: Setup JAXP using identity transformer
|
||||
TransformerFactory factory = TransformerFactory.newInstance();
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
Transformer transformer = factory.newTransformer(); // identity transformer
|
||||
|
||||
// Step 5: Setup input and output for XSLT transformation
|
||||
|
||||
@@ -398,7 +398,7 @@
|
||||
<nummer>BT-64</nummer>
|
||||
</xsl:when>
|
||||
<xsl:when test="$identifier = 'xr:Tax_representative_address_line_2'">
|
||||
<label>Postfach</label>
|
||||
<label>Adresszusatz</label>
|
||||
<nummer>BT-65</nummer>
|
||||
</xsl:when>
|
||||
<xsl:when test="$identifier = 'xr:Tax_representative_address_line_3'">
|
||||
@@ -486,7 +486,7 @@
|
||||
<nummer>BT-75</nummer>
|
||||
</xsl:when>
|
||||
<xsl:when test="$identifier = 'xr:Deliver_to_address_line_2'">
|
||||
<label>Postfach</label>
|
||||
<label>Adresszusatz</label>
|
||||
<nummer>BT-76</nummer>
|
||||
</xsl:when>
|
||||
<xsl:when test="$identifier = 'xr:Deliver_to_address_line_3'">
|
||||
|
||||
@@ -1193,7 +1193,7 @@ function downloadData (element_id) {
|
||||
<div id="BT-50" title="BT-50" class="boxdaten wert"><xsl:value-of select="xr:BUYER_POSTAL_ADDRESS/xr:Buyer_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach (BT-51):</div>
|
||||
<div class="boxdaten legende">Adresszusatz (BT-51):</div>
|
||||
<div id="BT-51" title="BT-51" class="boxdaten wert"><xsl:value-of select="xr:BUYER_POSTAL_ADDRESS/xr:Buyer_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
@@ -1258,7 +1258,7 @@ function downloadData (element_id) {
|
||||
<div id="BT-35" title="BT-35" class="boxdaten wert"><xsl:value-of select="xr:SELLER_POSTAL_ADDRESS/xr:Seller_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach (BT-36):</div>
|
||||
<div class="boxdaten legende">Adresszusatz (BT-36):</div>
|
||||
<div id="BT-36" title="BT-36" class="boxdaten wert"><xsl:value-of select="xr:SELLER_POSTAL_ADDRESS/xr:Seller_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
@@ -1998,7 +1998,7 @@ function downloadData (element_id) {
|
||||
<div id="BT-64" title="BT-64" class="boxdaten wert"><xsl:value-of select="xr:SELLER_TAX_REPRESENTATIVE_POSTAL_ADDRESS/xr:Tax_representative_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach (BT-65):</div>
|
||||
<div class="boxdaten legende">Adresszusatz (BT-65):</div>
|
||||
<div id="BT-65" title="BT-65" class="boxdaten wert"><xsl:value-of select="xr:SELLER_TAX_REPRESENTATIVE_POSTAL_ADDRESS/xr:Tax_representative_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
@@ -2111,7 +2111,7 @@ function downloadData (element_id) {
|
||||
<div id="BT-75" title="BT-75" class="boxdaten wert"><xsl:value-of select="xr:DELIVER_TO_ADDRESS/xr:Deliver_to_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach (BT-76):</div>
|
||||
<div class="boxdaten legende">Adresszusatz (BT-76):</div>
|
||||
<div id="BT-76" title="BT-76" class="boxdaten wert"><xsl:value-of select="xr:DELIVER_TO_ADDRESS/xr:Deliver_to_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<xsl:variable name="i18n.recipientInfo" select="'Informationen zum Käufer'"/>
|
||||
<xsl:variable name="i18n.dateOf" select="' vom '"/>
|
||||
<xsl:variable name="i18n.bt50" select="'Straße / Haus-Nr.'"/>
|
||||
<xsl:variable name="i18n.bt51" select="'Postfach'"/>
|
||||
<xsl:variable name="i18n.bt51" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt163" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt53" select="'PLZ'"/>
|
||||
<xsl:variable name="i18n.bt52" select="'Ort'"/>
|
||||
@@ -26,7 +26,7 @@
|
||||
<xsl:variable name="i18n.bt58" select="'E-Mail-Adresse'"/>
|
||||
<xsl:variable name="i18n.bt27" select="'Firmenname'"/>
|
||||
<xsl:variable name="i18n.bt35" select="'Straße / Haus-Nr.'"/>
|
||||
<xsl:variable name="i18n.bt36" select="'Postfach'"/>
|
||||
<xsl:variable name="i18n.bt36" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt162" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt38" select="'PLZ'"/>
|
||||
<xsl:variable name="i18n.bt37" select="'Ort'"/>
|
||||
@@ -166,7 +166,7 @@
|
||||
<xsl:variable name="i18n.bg11" select="'Steuervertreter des Verkäufers'"/>
|
||||
<xsl:variable name="i18n.bt62" select="'Name'"/>
|
||||
<xsl:variable name="i18n.bt64" select="'Straße / Hausnummer'"/>
|
||||
<xsl:variable name="i18n.bt65" select="'Postfach'"/>
|
||||
<xsl:variable name="i18n.bt65" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt164" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt67" select="'PLZ'"/>
|
||||
<xsl:variable name="i18n.bt66" select="'Ort'"/>
|
||||
@@ -189,7 +189,7 @@
|
||||
<xsl:variable name="i18n.bt72" select="'Lieferdatum'"/>
|
||||
<xsl:variable name="i18n.bt70" select="'Name des Empfängers'"/>
|
||||
<xsl:variable name="i18n.bt75" select="'Straße / Haus-Nr.'"/>
|
||||
<xsl:variable name="i18n.bt76" select="'Postfach'"/>
|
||||
<xsl:variable name="i18n.bt76" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt165" select="'Adresszusatz'"/>
|
||||
<xsl:variable name="i18n.bt78" select="'PLZ'"/>
|
||||
<xsl:variable name="i18n.bt77" select="'Ort'"/>
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
<div title="BT-50" class="boxdaten wert"><xsl:value-of select="xr:BUYER_POSTAL_ADDRESS/xr:Buyer_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach:</div>
|
||||
<div class="boxdaten legende">Adresszusatz:</div>
|
||||
<div title="BT-51" class="boxdaten wert"><xsl:value-of select="xr:BUYER_POSTAL_ADDRESS/xr:Buyer_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
@@ -179,7 +179,7 @@
|
||||
<div title="BT-35" class="boxdaten wert"><xsl:value-of select="xr:SELLER_POSTAL_ADDRESS/xr:Seller_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach:</div>
|
||||
<div class="boxdaten legende">Adresszusatz:</div>
|
||||
<div title="BT-36" class="boxdaten wert"><xsl:value-of select="xr:SELLER_POSTAL_ADDRESS/xr:Seller_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
@@ -892,7 +892,7 @@
|
||||
<div title="BT-64" class="boxdaten wert"><xsl:value-of select="xr:SELLER_TAX_REPRESENTATIVE_POSTAL_ADDRESS/xr:Tax_representative_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach:</div>
|
||||
<div class="boxdaten legende">Adresszusatz:</div>
|
||||
<div title="BT-65" class="boxdaten wert"><xsl:value-of select="xr:SELLER_TAX_REPRESENTATIVE_POSTAL_ADDRESS/xr:Tax_representative_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
@@ -998,7 +998,7 @@
|
||||
<div title="BT-75" class="boxdaten wert"><xsl:value-of select="xr:DELIVER_TO_ADDRESS/xr:Deliver_to_address_line_1"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach:</div>
|
||||
<div class="boxdaten legende">Adresszusatz:</div>
|
||||
<div title="BT-76" class="boxdaten wert"><xsl:value-of select="xr:DELIVER_TO_ADDRESS/xr:Deliver_to_address_line_2"/></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
|
||||
@@ -181,6 +181,36 @@ public class XRTest extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
public void testTaxExemptionReasonIssue() {
|
||||
String orgname = "Test company";
|
||||
String number = "123";
|
||||
String amountStr = "1.00";
|
||||
BigDecimal amount = new BigDecimal(amountStr);
|
||||
byte[] b = {12, 13};
|
||||
|
||||
Invoice i = new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date())
|
||||
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").setEmail("sender@example.com").addTaxID("DE4711").addVATID("DE0815").setContact(new Contact("Hans Test", "+49123456789", "test@example.org")).addBankDetails(new BankDetails("DE12500105170648489890", "COBADEFXXX").setAccountName("kontoInhaber")))
|
||||
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").setEmail("recipient@sample.org"))
|
||||
.setReferenceNumber("991-01484-64")//leitweg-id
|
||||
// not using any VAT, this is also a test of zero-rated goods:
|
||||
.setNumber(number)
|
||||
.addItem(new Item(new Product("Testprodukt", "", "C62", BigDecimal.ZERO).setTaxCategoryCode("E").setTaxExemptionReason("Kleinunternehmer"), amount, new BigDecimal(1.0)))
|
||||
.addItem(new Item(new Product("Testprodukt2", "", "C62", BigDecimal.ZERO).setTaxCategoryCode("S"), amount, new BigDecimal(1.0)))
|
||||
.setPayee( new TradeParty().setName("VR Factoring GmbH").setID("DE813838785").setLegalOrganisation(new LegalOrganisation("391200LDDFJDMIPPMZ54", "0199")));
|
||||
|
||||
|
||||
|
||||
ZUGFeRD2PullProvider zf2p = new ZUGFeRD2PullProvider();
|
||||
|
||||
zf2p.setProfile(Profiles.getByName("XRechnung"));
|
||||
zf2p.generateXML(i);
|
||||
String theXML = new String(zf2p.getXML(), StandardCharsets.UTF_8);
|
||||
assertThat(theXML).valueByXPath("count(//*[local-name()='ExemptionReason'])")
|
||||
.asInt()
|
||||
.isEqualTo(2);
|
||||
}
|
||||
|
||||
|
||||
public void testApplicablePercentInUntaxedService() {
|
||||
|
||||
// the writing part
|
||||
|
||||
@@ -762,7 +762,7 @@
|
||||
<div id="BT-50" title="BT-50" class="boxdaten wert">KUNDENWEG 88</div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach:</div>
|
||||
<div class="boxdaten legende">Adresszusatz:</div>
|
||||
<div id="BT-51" title="BT-51" class="boxdaten wert"></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
@@ -826,7 +826,7 @@
|
||||
<div id="BT-35" title="BT-35" class="boxdaten wert">BAHNHOFSTRASSE 99</div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach:</div>
|
||||
<div class="boxdaten legende">Adresszusatz:</div>
|
||||
<div id="BT-36" title="BT-36" class="boxdaten wert"></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
@@ -2203,7 +2203,7 @@
|
||||
<div id="BT-75" title="BT-75" class="boxdaten wert">HAUPTSTRASSE 44</div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
<div class="boxdaten legende">Postfach:</div>
|
||||
<div class="boxdaten legende">Adresszusatz:</div>
|
||||
<div id="BT-76" title="BT-76" class="boxdaten wert"></div>
|
||||
</div>
|
||||
<div class="boxzeile">
|
||||
|
||||
@@ -61,6 +61,10 @@ public abstract class Validator {
|
||||
Source xmlData = new StreamSource(new ByteArrayInputStream(xmlRawData));
|
||||
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
||||
try {
|
||||
schemaFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
schemaFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
schemaFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
schemaFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
Schema schema = schemaFactory.newSchema(schemaFile);
|
||||
javax.xml.validation.Validator validator = schema.newValidator();
|
||||
validator.validate(xmlData);
|
||||
|
||||
@@ -150,13 +150,23 @@ public class XMLValidator extends Validator {
|
||||
*/
|
||||
|
||||
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setNamespaceAware(true); // otherwise we can not act namespace independently, i.e. use
|
||||
// document.getElementsByTagNameNS("*",...
|
||||
dbf.setExpandEntityReferences(false);
|
||||
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
//REDHAT
|
||||
//https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf
|
||||
dbf.setAttribute(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 db = dbf.newDocumentBuilder();
|
||||
final InputSource is = new InputSource(new StringReader(zfXML));
|
||||
|
||||
@@ -143,12 +143,23 @@ public class ZUGFeRDValidator {
|
||||
String xmlAsString = null;
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setNamespaceAware(true);
|
||||
dbf.setExpandEntityReferences(false);
|
||||
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
//REDHAT
|
||||
//https://www.blackhat.com/docs/us-15/materials/us-15-Wang-FileCry-The-New-Age-Of-XXE-java-wp.pdf
|
||||
dbf.setAttribute(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);
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
|
||||
content = XMLTools.removeBOM(content);
|
||||
@@ -301,6 +312,7 @@ public class ZUGFeRDValidator {
|
||||
XMLWriter writer = new XMLWriter(sw, format);
|
||||
try {
|
||||
writer.write(document);
|
||||
writer.close();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e.getMessage());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user