From e46888af04d468039985e1340a7b00926a9ec478 Mon Sep 17 00:00:00 2001 From: Carl Wilson Date: Wed, 30 Oct 2024 11:59:58 +0000 Subject: [PATCH] REL: v0.16.0 (#210) * DEV: v0.15.0 dev version. (#202) * FIX: Double validation reporting (#201) - removed the validation report output from profile reporting. * FIX: Policy crash when document unparsable (#203) * Dev/0.15 (#204) * DEV: v0.15.0 dev version. * DEV: v0.15.0 dev version. * FIX: Policy crash when package has no manifest (#205) - added check for null manifest when attempting to list package XML files. Closes #193 * FIX: Crashing policy macro check of unreadable entries. (#206) - null stream entries are no longer checked for macros. * FIX: Version detection issues (#207) * FIX: Version detection issues - using full manifest entry name rather than simply file name; and - use appropriate namespace for detection. * FIX: Version detection fall-through. * FIX: Handling of encrypted entries (#208) - `PackageParser` changes: - parsing of `mimetype` and `META-INF/manifest.xml` are now done up front; - simpleified entry handling; - dedicated methods for mimetype and manifest parsing; - cleaned up handling of bad zip entries prior to moving this to the zip classes; - `OdfPackage` now has an `isEncrypted()` method to check if the package contains encrypted entries; - simplifed message processing in `ValidatingParser`; - addded encryption detection to prevent validation and profiling of encrypted package entries; - CLI reports incomplete validation for packages with encrypted entries, though this is still a little hacky. * REL: v0.16.0 (#209) - bumped maven version -> 0.16.0; - updated version in batch start files; and - updated version in README and other documentation. --- README.md | 2 +- docs/developer/index.md | 2 +- odf-apps/pom.xml | 2 +- .../odf/apps/CliValidator.java | 19 +-- odf-core/pom.xml | 2 +- .../openpreservation/odf/pkg/OdfPackage.java | 7 ++ .../odf/pkg/OdfPackageImpl.java | 19 ++- .../odf/pkg/PackageParserImpl.java | 99 ++++++++------- .../odf/validation/ValidatingParserImpl.java | 29 +++-- .../odf/validation/rules/AbstractRule.java | 7 +- .../odf/validation/rules/MacroRule.java | 17 ++- .../odf/validation/rules/ProfileImpl.java | 11 +- .../odf/validation/rules/SchematronRule.java | 2 +- .../odf/messages/Messages.properties | 1 + .../odf/validation/ValidatingParserTest.java | 115 ++++++++++++------ .../pkg/version/T104/META-INF/manifest.xml | 11 ++ .../pkg/version/T104/Thumbnails/thumbnail.png | Bin 0 -> 15196 bytes .../odf/fmt/pkg/version/T104/content.xml | 2 + .../odf/fmt/pkg/version/T104/manifest.rdf | 18 +++ .../odf/fmt/pkg/version/T104/meta.xml | 2 + .../odf/fmt/pkg/version/T104/mimetype | 1 + .../odf/fmt/pkg/version/T104/settings.xml | 2 + .../odf/fmt/pkg/version/T104/styles.xml | 2 + odf-reporting/pom.xml | 2 +- odf-validator | 2 +- odf-validator.bat | 2 +- pom.xml | 2 +- 27 files changed, 256 insertions(+), 124 deletions(-) create mode 100644 odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/META-INF/manifest.xml create mode 100644 odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/Thumbnails/thumbnail.png create mode 100644 odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/content.xml create mode 100644 odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/manifest.rdf create mode 100644 odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/meta.xml create mode 100644 odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/mimetype create mode 100644 odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/settings.xml create mode 100644 odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/styles.xml diff --git a/README.md b/README.md index ee47fa4d..11756e3e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ODF Validator -Latest version is 0.14.0. +Latest version is 0.16.0. ## About diff --git a/docs/developer/index.md b/docs/developer/index.md index f5ebf668..4e9920c2 100644 --- a/docs/developer/index.md +++ b/docs/developer/index.md @@ -44,7 +44,7 @@ To include the core validation library in your project, add the following depend org.openpreservation.odf odf-core - 0.14.0 + 0.16.0 ``` diff --git a/odf-apps/pom.xml b/odf-apps/pom.xml index 8e248d3c..3ba7861f 100644 --- a/odf-apps/pom.xml +++ b/odf-apps/pom.xml @@ -5,7 +5,7 @@ org.openpreservation.odf odf-validator - 0.14.0 + 0.16.0 ../pom.xml diff --git a/odf-apps/src/main/java/org/openpreservation/odf/apps/CliValidator.java b/odf-apps/src/main/java/org/openpreservation/odf/apps/CliValidator.java index d2911dde..5e29971e 100644 --- a/odf-apps/src/main/java/org/openpreservation/odf/apps/CliValidator.java +++ b/odf-apps/src/main/java/org/openpreservation/odf/apps/CliValidator.java @@ -125,10 +125,14 @@ private static Integer results(final Path path, final ValidationReport report) { ConsoleFormatter.info(FACTORY.getInfo("APP-3").getMessage()); } results(report.documentMessages.getMessages()); - outputSummary(report.documentMessages); + outputSummary(isEncrypted(report), report.documentMessages); return status; } + private static boolean isEncrypted(final ValidationReport report) { + return report.document.isPackage() && report.document.getPackage().isEncrypted(); + } + private static Integer results(final Map> messageMap) { Integer status = 0; for (Map.Entry> entry : messageMap.entrySet()) { @@ -140,9 +144,6 @@ private static Integer results(final Map> messageMap) { private static Integer results(final Path path, final ProfileResult report) { Integer status = 0; ConsoleFormatter.colourise(FACTORY.getInfo("APP-5", report.getName(), path.toString(), "bold")); - if (report.getValidationReport() != null) { - status = results(report.getValidationReport().documentMessages.getMessages()); - } for (Map.Entry> entry : report.getMessageLog().getMessages().entrySet()) { status = Math.max(status, results(entry.getKey(), entry.getValue())); } @@ -153,7 +154,7 @@ private static Integer results(final Path path, final ProfileResult report) { ? report.getValidationReport().documentMessages : Messages.messageLogInstance(); profileMessages.add(report.getMessageLog().getMessages()); - outputSummary(profileMessages); + outputSummary(isEncrypted(report.getValidationReport()), profileMessages); return status; } @@ -168,8 +169,12 @@ private static Integer results(final String path, final List messages) return status; } - private static void outputSummary(final MessageLog messageLog) { - if (messageLog.hasErrors()) { + private static void outputSummary(final boolean isEncrypted, final MessageLog messageLog) { + if (isEncrypted) { + ConsoleFormatter.error(String.format( + "INCOMPLETE encrypted entries are not supported, %d errors, %d warnings and %d info messages.", + messageLog.getErrorCount(), messageLog.getWarningCount(), messageLog.getInfoCount())); + } else if (messageLog.hasErrors()) { ConsoleFormatter.error(String.format("NOT VALID, %d errors, %d warnings and %d info messages.", messageLog.getErrorCount(), messageLog.getWarningCount(), messageLog.getInfoCount())); } else if (messageLog.hasWarnings()) { diff --git a/odf-core/pom.xml b/odf-core/pom.xml index ce375317..1a3e6079 100644 --- a/odf-core/pom.xml +++ b/odf-core/pom.xml @@ -5,7 +5,7 @@ org.openpreservation.odf odf-validator - 0.14.0 + 0.16.0 ../pom.xml diff --git a/odf-core/src/main/java/org/openpreservation/odf/pkg/OdfPackage.java b/odf-core/src/main/java/org/openpreservation/odf/pkg/OdfPackage.java index 892b8c1f..9d418c4e 100644 --- a/odf-core/src/main/java/org/openpreservation/odf/pkg/OdfPackage.java +++ b/odf-core/src/main/java/org/openpreservation/odf/pkg/OdfPackage.java @@ -230,4 +230,11 @@ public interface OdfPackage { * @return true if the file uses any namespaces outside of the ODF */ public boolean isExtended(); + + /** + * Discover if the package had any encrypted entries. + * + * @return true if the package has encrypted entries + */ + public boolean isEncrypted(); } diff --git a/odf-core/src/main/java/org/openpreservation/odf/pkg/OdfPackageImpl.java b/odf-core/src/main/java/org/openpreservation/odf/pkg/OdfPackageImpl.java index 2b4c33dd..f7d2b428 100644 --- a/odf-core/src/main/java/org/openpreservation/odf/pkg/OdfPackageImpl.java +++ b/odf-core/src/main/java/org/openpreservation/odf/pkg/OdfPackageImpl.java @@ -218,8 +218,10 @@ public List getXmlEntryPaths() { @Override public Set getXmlEntries() { Set entries = new HashSet<>(); - for (FileEntry entry : this.manifest.getEntriesByMediaType("text/xml")) { - entries.add(entry); + if (this.manifest != null) { + for (FileEntry entry : this.manifest.getEntriesByMediaType("text/xml")) { + entries.add(entry); + } } return entries; } @@ -338,4 +340,17 @@ public boolean isExtended() { } return false; } + + @Override + public boolean isEncrypted() { + if (this.manifest == null) { + return false; + } + for (FileEntry entry : this.manifest.getEntries()) { + if (entry.isEncrypted()) { + return true; + } + } + return false; + } } diff --git a/odf-core/src/main/java/org/openpreservation/odf/pkg/PackageParserImpl.java b/odf-core/src/main/java/org/openpreservation/odf/pkg/PackageParserImpl.java index 0641e5a0..111151ca 100644 --- a/odf-core/src/main/java/org/openpreservation/odf/pkg/PackageParserImpl.java +++ b/odf-core/src/main/java/org/openpreservation/odf/pkg/PackageParserImpl.java @@ -32,9 +32,11 @@ import org.xml.sax.SAXException; final class PackageParserImpl implements PackageParser { - private static String toParseConst = "toParse"; - private static String badFeature = "Unsupported Zip feature: %s"; - private static String ioException = "IO Exception reading stream: %s"; + private static final String TO_PARSE = "toParse"; + private static final String MESS_BAD_FEATURE = "Unsupported Zip feature: %s"; + private static final String MESS_IO_EXCEPTION = "IO Exception reading stream: %s"; + private static final String[] VERSION_FILE_PATHS = { Constants.PATH_MANIFEST, Constants.NAME_SETTINGS, + Constants.NAME_CONTENT }; static final PackageParser getInstance() { return new PackageParserImpl(); @@ -75,19 +77,19 @@ private PackageParserImpl() { @Override public OdfPackage parsePackage(final Path toParse) throws ParseException, FileNotFoundException { - Objects.requireNonNull(toParse, String.format(Checks.NOT_NULL, toParseConst, "Path")); + Objects.requireNonNull(toParse, String.format(Checks.NOT_NULL, TO_PARSE, "Path")); return this.parsePackage(toParse, toParse.getFileName().toString()); } @Override public OdfPackage parsePackage(final File toParse) throws ParseException, FileNotFoundException { - Objects.requireNonNull(toParse, String.format(Checks.NOT_NULL, toParseConst, "File")); + Objects.requireNonNull(toParse, String.format(Checks.NOT_NULL, TO_PARSE, "File")); return this.parsePackage(toParse.toPath(), toParse.getName()); } @Override public OdfPackage parsePackage(final InputStream toParse, final String name) throws ParseException { - Objects.requireNonNull(toParse, String.format(Checks.NOT_NULL, toParseConst, "InputStream")); + Objects.requireNonNull(toParse, String.format(Checks.NOT_NULL, TO_PARSE, "InputStream")); Objects.requireNonNull(name, String.format(Checks.NOT_NULL, name, "String")); try (BufferedInputStream bis = new BufferedInputStream(toParse)) { final Path temp = Files.createTempFile("odf", ".pkg"); @@ -98,22 +100,22 @@ public OdfPackage parsePackage(final InputStream toParse, final String name) thr } } - private final OdfPackage parsePackage(final Path toParse, final String name) throws ParseException, FileNotFoundException { + private final OdfPackage parsePackage(final Path toParse, final String name) + throws ParseException, FileNotFoundException { Checks.existingFileCheck(toParse); this.initialise(); try { this.format = sniff(toParse); this.cache = Zips.zipArchiveCacheInstance(toParse); - Map badEntries = checkZipEntries(); - if (!badEntries.isEmpty()) { - throw new ParseException(badEntries); - } + checkZipEntries(); this.version = detectVersion(); + this.mimetype = getMimeEntryValue(); } catch (final IOException e) { // Simply catch the exception and return a sparsely populated OdfPackage return OdfPackageImpl.Builder.builder().name(name).format(this.format).build(); } try { + this.manifest = parseManifest(); this.processZipEntries(); return this.makePackage(name); } catch (ParserConfigurationException | SAXException e) { @@ -123,45 +125,47 @@ private final OdfPackage parsePackage(final Path toParse, final String name) thr } } - private final Map checkZipEntries() { + private final String getMimeEntryValue() throws IOException { + return (this.cache.getZipEntry(OdfFormats.MIMETYPE) == null) ? "" + : new String(this.cache.getEntryInputStream(OdfFormats.MIMETYPE).readAllBytes(), + StandardCharsets.UTF_8); + } + + private void checkZipEntries() throws ParseException { final Map badEntries = new HashMap<>(); for (ZipEntry entry : this.cache.getZipEntries()) { try { this.cache.getEntryInputStream(entry.getName()).close(); } catch (UnsupportedZipFeatureException e) { - badEntries.put(entry.getName(), String.format(badFeature, e.getFeature().toString())); + badEntries.put(entry.getName(), String.format(MESS_BAD_FEATURE, e.getFeature().toString())); } catch (IOException e) { - badEntries.put(entry.getName(), String.format(ioException, e.getMessage())); + badEntries.put(entry.getName(), String.format(MESS_IO_EXCEPTION, e.getMessage())); } } - return badEntries; + if (!badEntries.isEmpty()) { + throw new ParseException(badEntries); + } } final Version detectVersion() throws IOException { Version detectedVersion = Version.UNKNOWN; - try (InputStream is = getVersionStreamName()) { - if (is != null) { - ParseResult result = new XmlParser().parse(is); - return Version.fromVersion(result.getRootAttributeValue("office:version")); + for (final String versionPath : VERSION_FILE_PATHS) { + try (InputStream is = this.cache.getEntryInputStream(versionPath)) { + if (is != null) { + ParseResult result = new XmlParser().parse(is); + detectedVersion = Version.fromVersion( + result.getRootAttributeValue(String.format("%s:version", result.getRootPrefix()))); + if (!Version.UNKNOWN.equals(detectedVersion)) { + return detectedVersion; + } + } + } catch (ParserConfigurationException | SAXException e) { + throw new IOException(e); } - } catch (ParserConfigurationException | SAXException e) { - throw new IOException(e); } return detectedVersion; } - private final InputStream getVersionStreamName() throws IOException { - InputStream retVal = null; - retVal = this.cache.getEntryInputStream(Constants.NAME_MANIFEST); - if (retVal == null) { - retVal = this.cache.getEntryInputStream(Constants.NAME_SETTINGS); - } - if (retVal == null) { - retVal = this.cache.getEntryInputStream(Constants.NAME_CONTENT); - } - return retVal; - } - private final void processZipEntries() throws ParserConfigurationException, SAXException, IOException { for (final ZipEntry entry : this.cache.getZipEntries()) { processEntry(entry); @@ -171,30 +175,31 @@ private final void processZipEntries() throws ParserConfigurationException, SAXE private final void processEntry(final ZipEntry entry) throws ParserConfigurationException, SAXException, IOException { final String path = entry.getName(); - if (entry.isDirectory()) { - // No need to process directories - return; - } - if (OdfFormats.MIMETYPE.equals(path)) { - // Grab the mimetype value from the MIMETYPE file - this.mimetype = new String(this.cache.getEntryInputStream(entry.getName()).readAllBytes(), - StandardCharsets.UTF_8); - return; - } - if (!isOdfXml(path) && !isMetaInf(path)) { + if (entry.isDirectory() || (!isOdfXml(path) && !isMetaInf(path))) { return; } try (InputStream is = this.cache.getEntryInputStream(path)) { final OdfXmlDocument xmlDoc = OdfXmlDocuments.xmlDocumentFrom(is); if (xmlDoc != null) { this.xmlDocumentMap.put(path, xmlDoc); - if (xmlDoc.getParseResult().isWellFormed() && Constants.PATH_MANIFEST.equals(path)) { - this.manifest = ManifestImpl.from(this.cache.getEntryInputStream(path)); - } } } } + private final Manifest parseManifest() throws IOException, ParserConfigurationException, SAXException { + final ZipEntry manifestEntry = this.cache.getZipEntry(Constants.PATH_MANIFEST); + if (manifestEntry == null) { + return null; + } + try (InputStream is = this.cache.getEntryInputStream(Constants.PATH_MANIFEST)) { + final OdfXmlDocument xmlDoc = OdfXmlDocuments.xmlDocumentFrom(is); + if (xmlDoc != null && xmlDoc.getParseResult().isWellFormed()) { + return ManifestImpl.from(this.cache.getEntryInputStream(Constants.PATH_MANIFEST)); + } + } + return null; + } + private final void initialise() { this.format = Formats.UNKNOWN; this.mimetype = null; diff --git a/odf-core/src/main/java/org/openpreservation/odf/validation/ValidatingParserImpl.java b/odf-core/src/main/java/org/openpreservation/odf/validation/ValidatingParserImpl.java index 3f6bcd67..23ce9399 100644 --- a/odf-core/src/main/java/org/openpreservation/odf/validation/ValidatingParserImpl.java +++ b/odf-core/src/main/java/org/openpreservation/odf/validation/ValidatingParserImpl.java @@ -6,6 +6,7 @@ import java.io.InputStream; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -104,19 +105,29 @@ private ValidationReport validate(final OdfPackage odfPackage) { private final Map> validateOdfXmlEntries(final OdfPackage odfPackage) { final Map> messages = new HashMap<>(); - for (final String xmlPath : odfPackage.getXmlEntryPaths()) { - ParseResult parseResult = odfPackage.getEntryXmlParseResult(xmlPath); - if (parseResult == null) { - continue; - } - List messageList = (parseResult.isWellFormed()) - ? validateOdfXmlDocument(odfPackage, xmlPath, parseResult) - : parseResult.getMessages(); - messages.put(xmlPath, messageList); + for (final FileEntry xmlEntry : odfPackage.getXmlEntries()) { + messages.put(xmlEntry.getFullPath(), validateXmlEntry(xmlEntry, odfPackage)); } return messages; } + private final List validateXmlEntry(final FileEntry xmlEntry, final OdfPackage odfPackage) { + final String xmlPath = xmlEntry.getFullPath(); + if (xmlPath.equals("/")) { + return new ArrayList<>(); + } + if (xmlEntry.isEncrypted()) { + return Arrays.asList(FACTORY.getWarning("PKG-10", xmlPath)); + } + ParseResult parseResult = odfPackage.getEntryXmlParseResult(xmlPath); + if (parseResult == null) { + return new ArrayList<>(); + } + return (parseResult.isWellFormed()) + ? validateOdfXmlDocument(odfPackage, xmlPath, parseResult) + : parseResult.getMessages(); + } + private final List validateOdfXmlDocument(final OdfPackage odfPackage, final String xmlPath, final ParseResult parseResult) { List messageList = new ArrayList<>(); diff --git a/odf-core/src/main/java/org/openpreservation/odf/validation/rules/AbstractRule.java b/odf-core/src/main/java/org/openpreservation/odf/validation/rules/AbstractRule.java index f6c23675..53304e29 100644 --- a/odf-core/src/main/java/org/openpreservation/odf/validation/rules/AbstractRule.java +++ b/odf-core/src/main/java/org/openpreservation/odf/validation/rules/AbstractRule.java @@ -4,6 +4,7 @@ import org.openpreservation.messages.Message.Severity; import org.openpreservation.messages.MessageLog; +import org.openpreservation.messages.Messages; import org.openpreservation.odf.pkg.PackageParser.ParseException; import org.openpreservation.odf.validation.Rule; import org.openpreservation.odf.validation.ValidationReport; @@ -52,7 +53,11 @@ public boolean isPrerequisite() { @Override public MessageLog check(ValidationReport report) throws ParseException { - return report.document.isPackage() ? check(report.document.getPackage()) : check(report.document.getDocument().getXmlDocument()); + if (report.document == null) { + return Messages.messageLogInstance(); + } + return report.document.isPackage() ? check(report.document.getPackage()) + : check(report.document.getDocument().getXmlDocument()); } @Override diff --git a/odf-core/src/main/java/org/openpreservation/odf/validation/rules/MacroRule.java b/odf-core/src/main/java/org/openpreservation/odf/validation/rules/MacroRule.java index 23474908..82d6b7e9 100644 --- a/odf-core/src/main/java/org/openpreservation/odf/validation/rules/MacroRule.java +++ b/odf-core/src/main/java/org/openpreservation/odf/validation/rules/MacroRule.java @@ -1,6 +1,7 @@ package org.openpreservation.odf.validation.rules; import java.io.IOException; +import java.io.InputStream; import javax.xml.parsers.ParserConfigurationException; @@ -60,11 +61,19 @@ private MessageLog checkOdfScriptXml(final OdfPackage odfPackage) throws IOExcep throw new IllegalStateException(e); } for (FileEntry entry : odfPackage.getXmlEntries()) { - ParseResult result = checker.parse(odfPackage.getEntryStream(entry)); - if (NS_SCRIPTS.equals(result.getRootNamespace().getId().toASCIIString()) - && "module".equals(result.getRootName())) { - messageLog.add(entry.getFullPath(), Messages.getMessageInstance(id, severity, name, description)); + if (entry.isEncrypted()) { + continue; + } + try (final InputStream entryStream = odfPackage.getEntryStream(entry)) { + if (entryStream == null) { + continue; + } + ParseResult result = checker.parse(odfPackage.getEntryStream(entry)); + if (NS_SCRIPTS.equals(result.getRootNamespace().getId().toASCIIString()) + && "module".equals(result.getRootName())) { + messageLog.add(entry.getFullPath(), Messages.getMessageInstance(id, severity, name, description)); + } } } return messageLog; diff --git a/odf-core/src/main/java/org/openpreservation/odf/validation/rules/ProfileImpl.java b/odf-core/src/main/java/org/openpreservation/odf/validation/rules/ProfileImpl.java index fd2a534e..32a11f47 100644 --- a/odf-core/src/main/java/org/openpreservation/odf/validation/rules/ProfileImpl.java +++ b/odf-core/src/main/java/org/openpreservation/odf/validation/rules/ProfileImpl.java @@ -46,20 +46,21 @@ public ProfileResult check(final OdfPackage odfPackage) throws ParseException { @Override public ProfileResult check(final ValidationReport report) throws ParseException { final MessageLog messages = Messages.messageLogInstance(); - messages.add(getRulesetMessages(report.document.getPackage(), + messages.add(getRulesetMessages(report, this.rules.stream().filter(Rule::isPrerequisite).collect(Collectors.toList()))); if (!messages.hasErrors()) { - messages.add(getRulesetMessages(report.document.getPackage(), + messages.add(getRulesetMessages(report, this.rules.stream().filter(rule -> !rule.isPrerequisite()).collect(Collectors.toList()))); } - return ProfileResultImpl.of(report.document.getPackage().getName(), this.name, report, messages); + return ProfileResultImpl.of(report.document == null ? "" : report.document.getPackage().getName(), this.name, + report, messages); } - private final Map> getRulesetMessages(final OdfPackage odfPackage, + private final Map> getRulesetMessages(final ValidationReport report, final Collection rules) throws ParseException { final MessageLog messages = Messages.messageLogInstance(); for (final Rule rule : rules) { - final MessageLog ruleMessages = rule.check(odfPackage); + final MessageLog ruleMessages = rule.check(report); messages.add(ruleMessages.getMessages()); } return messages.getMessages(); diff --git a/odf-core/src/main/java/org/openpreservation/odf/validation/rules/SchematronRule.java b/odf-core/src/main/java/org/openpreservation/odf/validation/rules/SchematronRule.java index 00ccf024..e31e71d9 100644 --- a/odf-core/src/main/java/org/openpreservation/odf/validation/rules/SchematronRule.java +++ b/odf-core/src/main/java/org/openpreservation/odf/validation/rules/SchematronRule.java @@ -46,7 +46,7 @@ public MessageLog check(final OdfPackage odfPackage) throws ParseException { Objects.requireNonNull(odfPackage, "odfPackage must not be null"); final MessageLog messageLog = Messages.messageLogInstance(); for (final FileEntry entry : odfPackage.getXmlEntries()) { - if (!OdfPackages.isOdfXml(entry.getFullPath())) { + if (!OdfPackages.isOdfXml(entry.getFullPath()) || entry.isEncrypted()) { continue; } try (InputStream is = odfPackage.getEntryStream(entry)) { diff --git a/odf-core/src/main/resources/org/openpreservation/odf/messages/Messages.properties b/odf-core/src/main/resources/org/openpreservation/odf/messages/Messages.properties index c02a5728..e9a2c1ad 100644 --- a/odf-core/src/main/resources/org/openpreservation/odf/messages/Messages.properties +++ b/odf-core/src/main/resources/org/openpreservation/odf/messages/Messages.properties @@ -16,6 +16,7 @@ PKG-4 = An OpenDocument Package SHOULD contain a file "mimetype". PKG-5 = An OpenDocument Package SHALL only contain the "META-INF/manifest.xml" and files containg the term "signatures" in their name in the "META-INF" folder. File %s does not meet this criteria. PKG-7 = An OpenDocument Package SHOULD contain a preview image Thumbnails/thumbnail.png. PKG-8 = Encrypted file entries shall be flagged as "STORED" rather than "DEFLATED" in the zip file's central directory. Zip entry %s is encrypted and flagged as "DEFLATED". +PKG-10 = Encrypted file entry detected: %s. MIM-1 = The "mimetype" file SHALL be the first file of the zip file. MIM-2 = The "mimetype" file SHALL NOT be compressed. MIM-3 = The "mimetype" file SHALL NOT use an 'extra field' in its header. diff --git a/odf-core/src/test/java/org/openpreservation/odf/validation/ValidatingParserTest.java b/odf-core/src/test/java/org/openpreservation/odf/validation/ValidatingParserTest.java index bfd0dd40..e9fcd3f7 100644 --- a/odf-core/src/test/java/org/openpreservation/odf/validation/ValidatingParserTest.java +++ b/odf-core/src/test/java/org/openpreservation/odf/validation/ValidatingParserTest.java @@ -35,14 +35,16 @@ public void testParseNullPath() throws ParserConfigurationException, SAXExceptio } @Test - public void testParsePath() throws ParseException, URISyntaxException, IOException, ParserConfigurationException, SAXException { + public void testParsePath() + throws ParseException, URISyntaxException, IOException, ParserConfigurationException, SAXException { ValidatingParser parser = Validators.getValidatingParser(); URL resourceUrl = TestFiles.EMPTY_ODS; Path path = Paths.get(resourceUrl.toURI()); OdfPackage pkg = parser.parsePackage(path); assertNotNull("Parsed package should not be null", pkg); assertTrue("Package should have a mimetype entry", pkg.hasMimeEntry()); - assertEquals("Mimetype should be Spreadsheet", "application/vnd.oasis.opendocument.spreadsheet", pkg.getMimeType()); + assertEquals("Mimetype should be Spreadsheet", "application/vnd.oasis.opendocument.spreadsheet", + pkg.getMimeType()); } @Test @@ -57,12 +59,14 @@ public void testParseNullFile() throws ParserConfigurationException, SAXExceptio } @Test - public void testParseFile() throws ParseException, IOException, URISyntaxException, ParserConfigurationException, SAXException { + public void testParseFile() + throws ParseException, IOException, URISyntaxException, ParserConfigurationException, SAXException { ValidatingParser parser = Validators.getValidatingParser(); OdfPackage pkg = parser.parsePackage(new File(TestFiles.EMPTY_ODS.toURI())); assertNotNull("Parsed package should not be null", pkg); assertTrue("Package should have a mimetype entry", pkg.hasMimeEntry()); - assertEquals("Mimetype should be Spreadsheet", "application/vnd.oasis.opendocument.spreadsheet", pkg.getMimeType()); + assertEquals("Mimetype should be Spreadsheet", "application/vnd.oasis.opendocument.spreadsheet", + pkg.getMimeType()); } @Test @@ -93,7 +97,8 @@ public void testParseStream() throws ParserConfigurationException, SAXException, OdfPackage pkg = parser.parsePackage(TestFiles.EMPTY_ODS.openStream(), TestFiles.EMPTY_ODS.toString()); assertNotNull("Parsed package should not be null", pkg); assertTrue("Package should have a mimetype entry", pkg.hasMimeEntry()); - assertEquals("Mimetype should be Spreadsheet", "application/vnd.oasis.opendocument.spreadsheet", pkg.getMimeType()); + assertEquals("Mimetype should be Spreadsheet", "application/vnd.oasis.opendocument.spreadsheet", + pkg.getMimeType()); } @Test @@ -114,9 +119,11 @@ public void testInValidZip() throws ParserConfigurationException, SAXException, } @Test - public void testBadlyFormedPackage() throws ParserConfigurationException, SAXException, IOException, ParseException { + public void testBadlyFormedPackage() + throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.BADLY_FORMED_PKG.openStream(), TestFiles.BADLY_FORMED_PKG.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.BADLY_FORMED_PKG.openStream(), + TestFiles.BADLY_FORMED_PKG.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("BADLY_FORMED_PKG should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("PKG-4")).count() > 0); @@ -127,52 +134,63 @@ public void testBadlyFormedPackage() throws ParserConfigurationException, SAXExc @Test public void testNoManifest() throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.NO_MANIFEST_ODS.openStream(), TestFiles.NO_MANIFEST_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.NO_MANIFEST_ODS.openStream(), + TestFiles.NO_MANIFEST_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("NO_MANIFEST_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("PKG-3")).count() > 0); } @Test - public void testManifestRootNoMime() throws ParserConfigurationException, SAXException, IOException, ParseException { + public void testManifestRootNoMime() + throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_ROOT_NO_MIME_ODS.openStream(), TestFiles.MANIFEST_ROOT_NO_MIME_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_ROOT_NO_MIME_ODS.openStream(), + TestFiles.MANIFEST_ROOT_NO_MIME_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("MANIFEST_ROOT_NO_MIME_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MIM-4")).count() > 0); } @Test - public void testManifestRootRandMimetype() throws ParserConfigurationException, SAXException, IOException, ParseException { + public void testManifestRootRandMimetype() + throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_RAND_MIMETYPE_ODS.openStream(), TestFiles.MANIFEST_RAND_MIMETYPE_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_RAND_MIMETYPE_ODS.openStream(), + TestFiles.MANIFEST_RAND_MIMETYPE_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("MANIFEST_RAND_MIMETYPE_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MIM-5")).count() > 0); } @Test - public void testManifestRandRootMime() throws ParserConfigurationException, SAXException, IOException, ParseException { + public void testManifestRandRootMime() + throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_RAND_ROOT_MIME_ODS.openStream(), TestFiles.MANIFEST_RAND_ROOT_MIME_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_RAND_ROOT_MIME_ODS.openStream(), + TestFiles.MANIFEST_RAND_ROOT_MIME_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("MANIFEST_RAND_ROOT_MIME_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MIM-5")).count() > 0); } @Test - public void testManifestRootDiffMime() throws ParserConfigurationException, SAXException, IOException, ParseException { + public void testManifestRootDiffMime() + throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_DIFF_MIME_ODS.openStream(), TestFiles.MANIFEST_DIFF_MIME_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_DIFF_MIME_ODS.openStream(), + TestFiles.MANIFEST_DIFF_MIME_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("MANIFEST_DIFF_MIME_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MIM-5")).count() > 0); } @Test - public void testManifestEmptyRootMime() throws ParserConfigurationException, SAXException, IOException, ParseException { + public void testManifestEmptyRootMime() + throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_EMPTY_ROOT_MIME_ODS.openStream(), TestFiles.MANIFEST_EMPTY_ROOT_MIME_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_EMPTY_ROOT_MIME_ODS.openStream(), + TestFiles.MANIFEST_EMPTY_ROOT_MIME_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("MANIFEST_EMPTY_ROOT_MIME_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MIM-5")).count() > 0); @@ -181,7 +199,8 @@ public void testManifestEmptyRootMime() throws ParserConfigurationException, SAX @Test public void testManifestEntry() throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_ENTRY_ODS.openStream(), TestFiles.MANIFEST_ENTRY_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_ENTRY_ODS.openStream(), + TestFiles.MANIFEST_ENTRY_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("MANIFEST_ENTRY_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MAN-2")).count() > 0); @@ -190,7 +209,8 @@ public void testManifestEntry() throws ParserConfigurationException, SAXExceptio @Test public void testMimetypeEntry() throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.MIMETYPE_ENTRY_ODS.openStream(), TestFiles.MIMETYPE_ENTRY_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.MIMETYPE_ENTRY_ODS.openStream(), + TestFiles.MIMETYPE_ENTRY_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("MIMETYPE_ENTRY_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MAN-3")).count() > 0); @@ -199,16 +219,19 @@ public void testMimetypeEntry() throws ParserConfigurationException, SAXExceptio @Test public void testMetainfEntry() throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.METAINF_ENTRY_ODT.openStream(), TestFiles.METAINF_ENTRY_ODT.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.METAINF_ENTRY_ODT.openStream(), + TestFiles.METAINF_ENTRY_ODT.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("METAINF_ENTRY_ODT should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MAN-6")).count() > 0); } @Test - public void testMissingManifestEntry() throws ParserConfigurationException, SAXException, IOException, ParseException { + public void testMissingManifestEntry() + throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_MISSING_ENTRY_ODS.openStream(), TestFiles.MANIFEST_MISSING_ENTRY_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_MISSING_ENTRY_ODS.openStream(), + TestFiles.MANIFEST_MISSING_ENTRY_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("MANIFEST_MISSING_ENTRY_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MAN-1")).count() > 0); @@ -217,7 +240,8 @@ public void testMissingManifestEntry() throws ParserConfigurationException, SAXE @Test public void testMissingXmlEntry() throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_MISSING_XML_ENTRY_ODS.openStream(), TestFiles.MANIFEST_MISSING_XML_ENTRY_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_MISSING_XML_ENTRY_ODS.openStream(), + TestFiles.MANIFEST_MISSING_XML_ENTRY_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("MANIFEST_MISSING_XML_ENTRY_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MAN-1")).count() > 0); @@ -226,7 +250,8 @@ public void testMissingXmlEntry() throws ParserConfigurationException, SAXExcept @Test public void testMissingFile() throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.MISSING_FILE_ODS.openStream(), TestFiles.MISSING_FILE_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.MISSING_FILE_ODS.openStream(), + TestFiles.MISSING_FILE_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("MISSING_FILE_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MAN-4")).count() > 0); @@ -235,7 +260,8 @@ public void testMissingFile() throws ParserConfigurationException, SAXException, @Test public void testNoMimeWithRoot() throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.NO_MIME_ROOT_ODS.openStream(), TestFiles.NO_MIME_ROOT_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.NO_MIME_ROOT_ODS.openStream(), + TestFiles.NO_MIME_ROOT_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("NO_MIME_ROOT_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MIM-4")).count() > 0); @@ -244,7 +270,8 @@ public void testNoMimeWithRoot() throws ParserConfigurationException, SAXExcepti @Test public void testNoRootMimeTyoe() throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_NO_ROOT_MIMETYPE_ODS.openStream(), TestFiles.MANIFEST_NO_ROOT_MIMETYPE_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.MANIFEST_NO_ROOT_MIMETYPE_ODS.openStream(), + TestFiles.MANIFEST_NO_ROOT_MIMETYPE_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("MANIFEST_NO_ROOT_MIMETYPE_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MAN-5")).count() > 0); @@ -253,7 +280,8 @@ public void testNoRootMimeTyoe() throws ParserConfigurationException, SAXExcepti @Test public void testNoMimeNoRoot() throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.NO_MIME_NO_ROOT_ODS.openStream(), TestFiles.NO_MIME_NO_ROOT_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.NO_MIME_NO_ROOT_ODS.openStream(), + TestFiles.NO_MIME_NO_ROOT_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertTrue("NO_MIME_NO_ROOT_ODS should be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("PKG-4")).count() > 0); @@ -272,16 +300,19 @@ public void testMimeLast() throws ParserConfigurationException, SAXException, IO @Test public void testMimeCompressed() throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.MIME_COMPRESSED_ODS.openStream(), TestFiles.MIME_COMPRESSED_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.MIME_COMPRESSED_ODS.openStream(), + TestFiles.MIME_COMPRESSED_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("MIME_COMPRESSED_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MIM-2")).count() > 0); } @Test - public void testMimeCompressedLast() throws ParserConfigurationException, SAXException, IOException, ParseException { + public void testMimeCompressedLast() + throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.MIME_COMPRESSED_LAST_ODS.openStream(), TestFiles.MIME_COMPRESSED_LAST_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.MIME_COMPRESSED_LAST_ODS.openStream(), + TestFiles.MIME_COMPRESSED_LAST_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("MIME_COMPRESSED_LAST_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MIM-1")).count() > 0); @@ -291,7 +322,8 @@ public void testMimeCompressedLast() throws ParserConfigurationException, SAXExc @Test public void testMimeExtra() throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.MIME_EXTRA_ODS.openStream(), TestFiles.MIME_EXTRA_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.MIME_EXTRA_ODS.openStream(), + TestFiles.MIME_EXTRA_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertFalse("MIME_EXTRA_ODS should NOT be valid", report.isValid()); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("MIM-3")).count() > 0); @@ -300,7 +332,8 @@ public void testMimeExtra() throws ParserConfigurationException, SAXException, I @Test public void testNoThumbnail() throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.NO_THUMBNAIL_ODS.openStream(), TestFiles.NO_THUMBNAIL_ODS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.NO_THUMBNAIL_ODS.openStream(), + TestFiles.NO_THUMBNAIL_ODS.toString()); ValidationReport report = parser.validatePackage(pkg); assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("PKG-7")).count() > 0); } @@ -316,10 +349,11 @@ public void testNoEmbeddedWord() throws ParserConfigurationException, SAXExcepti @Test public void testPasswordEncrypted() throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); - OdfPackage pkg = parser.parsePackage(TestFiles.ENCRYPTED_PASSWORDS.openStream(), TestFiles.ENCRYPTED_PASSWORDS.toString()); + OdfPackage pkg = parser.parsePackage(TestFiles.ENCRYPTED_PASSWORDS.openStream(), + TestFiles.ENCRYPTED_PASSWORDS.toString()); ValidationReport report = parser.validatePackage(pkg); - assertFalse("ENCRYPTED_PASSWORDS should NOT be valid", report.isValid()); - assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("XML-3")).count() > 0); + assertTrue("ENCRYPTED_PASSWORDS should be valid", report.isValid()); + assertTrue(report.getMessages().stream().filter(m -> m.getId().equals("PKG-10")).count() > 0); } @Test @@ -328,7 +362,7 @@ public void testDsigValid() throws ParserConfigurationException, SAXException, I InputStream is = TestFiles.DSIG_VALID.openStream(); OdfPackage pkg = parser.parsePackage(is, TestFiles.DSIG_VALID.toString()); ValidationReport report = parser.validatePackage(pkg); - assertTrue("Package is not valid" , report.isValid()); + assertTrue("Package is not valid", report.isValid()); } @Test @@ -337,16 +371,17 @@ public void testDsigInvalid() throws ParserConfigurationException, SAXException, InputStream is = TestFiles.DSIG_INVALID.openStream(); OdfPackage pkg = parser.parsePackage(is, TestFiles.DSIG_INVALID.toString()); ValidationReport report = parser.validatePackage(pkg); - assertFalse("Package should be NOT be valid, dsig file has bad version" , report.isValid()); + assertFalse("Package should be NOT be valid, dsig file has bad version", report.isValid()); } @Test - public void testDsigInvalidBadName() throws ParserConfigurationException, SAXException, IOException, ParseException { + public void testDsigInvalidBadName() + throws ParserConfigurationException, SAXException, IOException, ParseException { ValidatingParser parser = Validators.getValidatingParser(); InputStream is = TestFiles.DSIG_BADNAME.openStream(); OdfPackage pkg = parser.parsePackage(is, TestFiles.DSIG_BADNAME.toString()); ValidationReport report = parser.validatePackage(pkg); - assertFalse("Package should be NOT be valid, badly named META-INF file." , report.isValid()); + assertFalse("Package should be NOT be valid, badly named META-INF file.", report.isValid()); assertEquals(1, report.getMessages().stream().filter(m -> m.getId().equals("PKG-5")).count()); } } diff --git a/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/META-INF/manifest.xml b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/META-INF/manifest.xml new file mode 100644 index 00000000..a076030a --- /dev/null +++ b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/META-INF/manifest.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/Thumbnails/thumbnail.png b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/Thumbnails/thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..2c939f2dcc6e605cd5afbb8d247c5075bb473e30 GIT binary patch literal 15196 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 F{{XMF-%bDk literal 0 HcmV?d00001 diff --git a/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/content.xml b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/content.xml new file mode 100644 index 00000000..1d74214c --- /dev/null +++ b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/content.xml @@ -0,0 +1,2 @@ + +Besøg på museum efter besøg, alder og køn efter tid, alder og køn ogbesøg2021K4Inden for de seneste 3 månederMellem 3-6 måneder sidenMellem et halvt og et helt år sidenMellem 1 og 3 år sidenMellem 3 og 5 år sidenMere end 5 år sidenAldrig været på et museumØnsker ikke at svareVed ikkeI alt29911221014401Mænd25811241115501Kvinder3391119101330116-24 år3411132011650125-34 år317122610941035-44 år2811825121140145-54 år2791222101731055-64 år3081019111740165-74 år339111861850175 år og derover22610211221504Spørgsmål til respondenter: Hvornår har du senest besøgt et museum? Pct. af befolkningen \ No newline at end of file diff --git a/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/manifest.rdf b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/manifest.rdf new file mode 100644 index 00000000..927e206b --- /dev/null +++ b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/manifest.rdf @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/meta.xml b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/meta.xml new file mode 100644 index 00000000..961b395c --- /dev/null +++ b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/meta.xml @@ -0,0 +1,2 @@ + +mariaMaria Messerschmidt2024-04-11T09:03:422024-04-30T07:54:52LibreOffice/24.2.2.2$MacOSX_AARCH64 LibreOffice_project/d56cc158d8a96260b836f100ef4b4ef25d6f1a0116.0300 \ No newline at end of file diff --git a/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/mimetype b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/mimetype new file mode 100644 index 00000000..78a49cc5 --- /dev/null +++ b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/mimetype @@ -0,0 +1 @@ +application/vnd.oasis.opendocument.spreadsheet \ No newline at end of file diff --git a/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/settings.xml b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/settings.xml new file mode 100644 index 00000000..9e7935bb --- /dev/null +++ b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/settings.xml @@ -0,0 +1,2 @@ + +00157299525truetruetrue0truetruefalsetruefalse-1truetrue0falsefalsetruetruefalse3falsefalsefalse1000100011truefalsefalsetruetruetruetrue2true \ No newline at end of file diff --git a/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/styles.xml b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/styles.xml new file mode 100644 index 00000000..e8d3170e --- /dev/null +++ b/odf-core/src/test/resources/org/openpreservation/odf/fmt/pkg/version/T104/styles.xml @@ -0,0 +1,2 @@ + +---- - - - - ::::???Page 1???(???)0000-00-00, 00:00:00Page 1/ 99 \ No newline at end of file diff --git a/odf-reporting/pom.xml b/odf-reporting/pom.xml index ea5ff00f..990bef6d 100644 --- a/odf-reporting/pom.xml +++ b/odf-reporting/pom.xml @@ -5,7 +5,7 @@ org.openpreservation.odf odf-validator - 0.14.0 + 0.16.0 ../pom.xml diff --git a/odf-validator b/odf-validator index d278c1d5..b307df8b 100755 --- a/odf-validator +++ b/odf-validator @@ -78,5 +78,5 @@ fi exec "$JAVACMD" -Dfile.encoding=UTF8 -XX:+IgnoreUnrecognizedVMOptions \ -Dapp.name="ODF Validator" \ - -jar odf-apps/target/odf-apps-0.14.0-jar-with-dependencies.jar \ + -jar odf-apps/target/odf-apps-0.16.0-jar-with-dependencies.jar \ "$@" diff --git a/odf-validator.bat b/odf-validator.bat index 5f16a8ed..92665c39 100644 --- a/odf-validator.bat +++ b/odf-validator.bat @@ -85,7 +85,7 @@ if NOT "%CLASSPATH_PREFIX%" == "" set CLASSPATH=%CLASSPATH_PREFIX%;%CLASSPATH% @REM Reaching here means variables are defined and arguments have been captured :endInit -"%JAVACMD%" -Dfile.encoding=UTF8 -XX:+IgnoreUnrecognizedVMOptions -Dapp.name="ODF Validator" -jar .\odf-apps\target\odf-apps-0.14.0-jar-with-dependencies.jar %CMD_LINE_ARGS% +"%JAVACMD%" -Dfile.encoding=UTF8 -XX:+IgnoreUnrecognizedVMOptions -Dapp.name="ODF Validator" -jar .\odf-apps\target\odf-apps-0.16.0-jar-with-dependencies.jar %CMD_LINE_ARGS% if %ERRORLEVEL% NEQ 0 goto error goto end diff --git a/pom.xml b/pom.xml index 70fb11a2..8d74f7a5 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ org.openpreservation.odf odf-validator - 0.14.0 + 0.16.0 pom