diff --git a/validator/src/main/java/org/mustangproject/validator/ZUGFeRDValidator.java b/validator/src/main/java/org/mustangproject/validator/ZUGFeRDValidator.java index 0c7f99ae..6214139a 100644 --- a/validator/src/main/java/org/mustangproject/validator/ZUGFeRDValidator.java +++ b/validator/src/main/java/org/mustangproject/validator/ZUGFeRDValidator.java @@ -7,10 +7,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.io.StringWriter; +import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; @@ -26,15 +25,15 @@ import org.dom4j.DocumentHelper; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import org.mustangproject.XMLTools; -import org.riversun.bigdoc.bin.BigFileSearcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.InputSource; +import com.helger.commons.io.stream.StreamHelper; + import jakarta.xml.bind.DatatypeConverter; -import jakarta.xml.bind.annotation.adapters.HexBinaryAdapter; //abstract class public class ZUGFeRDValidator { @@ -75,153 +74,21 @@ public class ZUGFeRDValidator { return wasCompletelyValid; } - - /*** - * performs a validation on the file filename - * - * @param filename the complete absolute filename of a PDF or XML - * @return a xml string with the validation result - */ - public String validate(String filename) { - context.clear(); - StringBuilder finalStringResult = new StringBuilder(); - SimpleDateFormat isoDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - Date date = new Date(); - startTime = Calendar.getInstance().getTimeInMillis(); - Path path = Paths.get(filename); - Path pathFilename = path.getFileName (); - if (pathFilename != null) - context.setFilename(pathFilename.toString());// set filename without path - else - context.setFilename(filename);// fallback to provided name - finalStringResult.append(""); - - boolean isPDF = false; - byte[] content = null; - try { - - if (filename == null) { - optionsRecognized = false; - context.addResultItem(new ValidationResultItem(ESeverity.fatal, "Filename not specified").setSection(10) - .setPart(EPart.pdf)); - } - - PDFValidator pdfv = new PDFValidator(context); - File file = new File(filename); - if (!file.isFile()) { - context.addResultItem( - new ValidationResultItem(ESeverity.fatal, "File not found").setSection(1).setPart(EPart.pdf)); - } else if (file.length() < 32) { - // with less than 32 bytes it can not even be a proper XML file - // Except it is "" LOL - context.addResultItem( - new ValidationResultItem(ESeverity.fatal, "File too small").setSection(5).setPart(EPart.pdf)); - } else { - content = Files.readAllBytes(file.toPath()); - XMLValidator xv = new XMLValidator(context); - if (disableNotices) { - xv.disableNotices(); - } - isPDF = ByteArraySearcher.indexOf(content, new byte[] {'%', 'P', 'D', 'F'}) == 0; - if (isPDF) { - pdfv.setFilename(filename); - pdfv.setFileContents(content); - - optionsRecognized = true; - finalStringResult.append(""); - try { - pdfv.validate(); - - sha1Checksum = calcSHA1(content); - - // Validate PDF - - getPdfValidationResults(finalStringResult, pdfv, xv); - } catch (IrrecoverableValidationError irx) { - LOGGER.info(irx.getMessage()); - } - - finalStringResult.append("\n"); - - context.clearCustomXML(); - } else { - boolean isXML = false; - try { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = dbf.newDocumentBuilder(); - - content = XMLTools.removeBOM(content); - String s = new String(content, StandardCharsets.UTF_8); - InputSource is = new InputSource(new StringReader(s)); - Document doc = db.parse(is); - - Element root = doc.getDocumentElement(); - isXML = true;//no exception so far - - } catch (Exception ex) { - // probably no xml file, sth like SAXParseException content not allowed in prolog - // ignore isXML is already false - // in the tests, this may error-out anyway - LOGGER.info("No XML part provided"); - } - if (isXML) { - pdfValidity = true; - optionsRecognized = true; - xv.setFilename(filename); - sha1Checksum = calcSHA1(content); - - displayXMLValidationOutput = true; - - } else { - optionsRecognized = false; - context.addResultItem(new ValidationResultItem(ESeverity.exception, - "File does not look like PDF nor XML (contains neither %PDF nor "); - try { - xv.validate(); - } catch (IrrecoverableValidationError irx) { - LOGGER.info("The hell"); - } - finalStringResult.append(xv.getXMLResult()); - finalStringResult.append(""); - context.clearCustomXML(); - } - - if ((isPDF) && (!pdfValidity)) { - context.setInvalid(); - } - - } - } catch (IrrecoverableValidationError | IOException irx) { - LOGGER.info(irx.getMessage()); - context.setInvalid (); - } finally { - finalStringResult.append(context.getXMLResult()); - finalStringResult.append(""); - - } - - return formatOutput(finalStringResult, isPDF); - } - - public String validate(InputStream inputStream, String fileNameOfInputStream) { + + private String internalValidate (String contextFilename, InputStream inputStream, long inputLength) { context.clear(); StringBuilder finalStringResult = new StringBuilder(); SimpleDateFormat isoDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = new Date(); startTime = Calendar.getInstance().getTimeInMillis(); - context.setFilename(fileNameOfInputStream);// set filename without path - finalStringResult.append(""); + context.setFilename(contextFilename);// fallback to provided name + finalStringResult.append(""); boolean isPDF = false; byte[] content = null; try { - if (fileNameOfInputStream == null) { + if (contextFilename == null || contextFilename.isEmpty ()) { optionsRecognized = false; context.addResultItem(new ValidationResultItem(ESeverity.fatal, "Filename not specified").setSection(10) .setPart(EPart.pdf)); @@ -231,7 +98,7 @@ public class ZUGFeRDValidator { if (inputStream == null) { context.addResultItem( new ValidationResultItem(ESeverity.fatal, "File not found").setSection(1).setPart(EPart.pdf)); - } else if (inputStream.available() < 32) { + } else if (inputLength < 32) { // with less than 32 bytes it can not even be a proper XML file // Except it is "" LOL context.addResultItem( @@ -245,7 +112,7 @@ public class ZUGFeRDValidator { isPDF = ByteArraySearcher.indexOf(content, new byte[] {'%', 'P', 'D', 'F'}) == 0; if (isPDF) { // Avoid reading again from file - pdfv.setFilenameAndContents(fileNameOfInputStream, content); + pdfv.setFilenameAndContents(contextFilename, content); optionsRecognized = true; finalStringResult.append(""); @@ -278,6 +145,7 @@ public class ZUGFeRDValidator { Element root = doc.getDocumentElement(); isXML = true;//no exception so far + } catch (Exception ex) { // probably no xml file, sth like SAXParseException content not allowed in prolog // ignore isXML is already false @@ -289,7 +157,7 @@ public class ZUGFeRDValidator { optionsRecognized = true; xv.setStringContent (xmlAsString); xv.disableAutoload(); - xv.setFilename(fileNameOfInputStream); + xv.setFilename(contextFilename); sha1Checksum = calcSHA1(content); displayXMLValidationOutput = true; @@ -328,6 +196,60 @@ public class ZUGFeRDValidator { } return formatOutput(finalStringResult, isPDF); + } + + /*** + * performs a validation on the file filename + * + * @param filename the complete absolute filename of a PDF or XML + * @return a xml string with the validation result + */ + public String validate(String filename) { + String contextFilename; + InputStream inputStream; + long inputLength; + if (filename == null) { + // No filename provided + contextFilename = ""; + inputStream = null; + inputLength = 0; + } else { + File file = new File(filename); + // set filename without path + contextFilename = file.getName (); + if (file.isFile ()) { + try { + inputStream = new FileInputStream (file); + inputLength = Files.size (file.toPath ()); + } catch (IOException ex) { + throw new UncheckedIOException (ex); + } + } else { + // Non-existing or Directory + inputStream = null; + inputLength = 0; + } + } + try { + return internalValidate (contextFilename, inputStream, inputLength); + } finally { + StreamHelper.close (inputStream); + } + } + + public String validate(InputStream inputStream, String fileNameOfInputStream) { + long inputLength; + try { + inputLength = inputStream == null ? 0 : inputStream.available (); + } + catch (IOException ex) { + throw new UncheckedIOException (ex); + } + try { + return internalValidate (fileNameOfInputStream, inputStream, inputLength); + } finally { + StreamHelper.close (inputStream); + } } private void getPdfValidationResults(StringBuilder finalStringResult, PDFValidator pdfv, XMLValidator xv) throws IrrecoverableValidationError { diff --git a/validator/src/test/java/org/mustangproject/validator/MiscValidatorTest.java b/validator/src/test/java/org/mustangproject/validator/MiscValidatorTest.java index b333ce25..1243ca83 100644 --- a/validator/src/test/java/org/mustangproject/validator/MiscValidatorTest.java +++ b/validator/src/test/java/org/mustangproject/validator/MiscValidatorTest.java @@ -13,15 +13,15 @@ public class MiscValidatorTest extends ResourceCase { ZUGFeRDValidator zfv=new ZUGFeRDValidator(); String res=zfv.validate(null); - assertTrue(res.matches("<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>\n" + - "\n" + - "\n" + - " \n" + - " Filename not specified \n" + - " \n" + - " \n" + - "\n" + - "")); + assertTrue(res.matches("<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>\n" + + "\n" + + "\n" + + " \n" + + " Filename not specified \n" + + " \n" + + " \n" + + "\n" + + "")); res=zfv.validate("/dhfkbv/sfjkh"); assertTrue(res.matches("<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>\n" +