diff --git a/pom.xml b/pom.xml index a83c5d7cb..9c1dc3135 100644 --- a/pom.xml +++ b/pom.xml @@ -173,7 +173,7 @@ com.ibm.icu icu4j - 70.1 + 72.1 net.sf.saxon diff --git a/src/main/java/com/adobe/epubcheck/ocf/OCFChecker.java b/src/main/java/com/adobe/epubcheck/ocf/OCFChecker.java index 04960f4b4..7e03d3edb 100755 --- a/src/main/java/com/adobe/epubcheck/ocf/OCFChecker.java +++ b/src/main/java/com/adobe/epubcheck/ocf/OCFChecker.java @@ -287,8 +287,6 @@ private boolean checkContainerStructure(OCFCheckerState state) List directories = new LinkedList<>(); // Loop through the entries - OCFFilenameChecker filenameChecker = new OCFFilenameChecker(state.context().build()); - // FIXME catch IAE MALFORMED entries for (OCFResource resource : resourcesProvider) { Preconditions.checkNotNull(resource.getPath()); @@ -318,7 +316,7 @@ else if (resources.containsKey( else { // Check file name requirements - filenameChecker.checkCompatiblyEscaped(resource.getPath()); + new OCFFilenameChecker(resource.getPath(), state.context().build()).check();; // report entry metadata reportFeatures(resource.getProperties()); diff --git a/src/main/java/com/adobe/epubcheck/ocf/OCFFilenameChecker.java b/src/main/java/com/adobe/epubcheck/ocf/OCFFilenameChecker.java index 8a2e4a5eb..d9bd3217e 100644 --- a/src/main/java/com/adobe/epubcheck/ocf/OCFFilenameChecker.java +++ b/src/main/java/com/adobe/epubcheck/ocf/OCFFilenameChecker.java @@ -1,127 +1,162 @@ package com.adobe.epubcheck.ocf; +import java.util.LinkedHashSet; import java.util.Set; +import java.util.stream.Collectors; + +import org.w3c.epubcheck.core.Checker; import com.adobe.epubcheck.api.EPUBLocation; import com.adobe.epubcheck.api.Report; import com.adobe.epubcheck.messages.MessageId; import com.adobe.epubcheck.opf.ValidationContext; import com.adobe.epubcheck.util.EPUBVersion; -import com.google.common.collect.ImmutableSet; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.ibm.icu.lang.UCharacter; +import com.ibm.icu.text.UCharacterIterator; +import com.ibm.icu.text.UForwardCharacterIterator; +import com.ibm.icu.text.UnicodeSet; -//FIXME 2022 update related PKG-* messages to contain the file name string -public final class OCFFilenameChecker +public final class OCFFilenameChecker implements Checker { - private static final Set RESTRICTED_30_CHARACTER_SET = ImmutableSet.of("PRIVATE_USE_AREA", - "ARABIC_PRESENTATION_FORMS_A", "SPECIALS", "SUPPLEMENTARY_PRIVATE_USE_AREA_A", - "SUPPLEMENTARY_PRIVATE_USE_AREA_B", "VARIATION_SELECTORS_SUPPLEMENT", "TAGS"); + + private static final UnicodeSet ASCII = new UnicodeSet("[:ascii:]").freeze(); + + private static final UnicodeSet DISALLOWED_EPUB2 = new UnicodeSet() + // .add(0x002F)// SOLIDUS '/' -- allowed as path separator + .add(0x0022)// QUOTATION MARK '"' + .add(0x002A)// ASTERISK '*' + // .add(0x002E)// FULL STOP '.' -- only disallowed as the last character + .add(0x003A)// COLON ':' + .add(0x003C)// LESS-THAN SIGN '<' + .add(0x003E)// GREATER-THAN SIGN '>' + .add(0x003F)// QUESTION MARK '?' + .add(0x005C)// REVERSE SOLIDUS '\' + .freeze(); + + private static final ImmutableMap DISALLOWED_EPUB3 = new ImmutableMap.Builder() + .put("ASCII", new UnicodeSet() // + .addAll(DISALLOWED_EPUB2)// all disallowed in EPUB 2.0.1 + .add(0x007C) // VERTICAL LINE '|' + .freeze()) + .put("NON CHARACTER", new UnicodeSet("[:Noncharacter_Code_Point=Yes:]")// + .freeze()) + .put("CONTROL", new UnicodeSet().add(0x007F) // DEL + .addAll(0x0000, 0x001F) // C0 range + .addAll(0x0080, 0x009F) // C1 range + .freeze()) + .put("PRIVATE USE", new UnicodeSet() // + .addAll(0xE000, 0xF8FF) // Private Use Area + .addAll(0xF0000, 0xFFFFF) // Supplementary Private Use Area-A + .addAll(0x100000, 0x10FFFF) // Supplementary Private Use Area-B + .freeze()) + .put("SPECIALS", new UnicodeSet() // + .addAll(0xFFF0, 0xFFFF) // Specials Blocks + .freeze()) + .put("DEPRECATED", new UnicodeSet() // + .add(0xE0001)// LANGUAGE TAG + // .add(0xE007F)// CANCEL TAG -- reinstated in Emoji tag sequences + .freeze()) + .build(); + + private static String toString(int codepoint, String setName) + { + assert setName != null; + StringBuilder result = new StringBuilder().append(String.format("U+%04X ", codepoint)); + if ("ASCII".equals(setName)) + { + result.append('(').append(UCharacter.toString(codepoint)).append(')'); + } + else + { + String characterName = UCharacter.getName(codepoint); + if (characterName != null) + { + result.append(characterName).append(' '); + } + result.append('(').append(setName).append(')'); + } + return result.toString(); + } private final Report report; private final EPUBVersion version; private final EPUBLocation location; + private final String filename; + + public OCFFilenameChecker(String filename, ValidationContext context) + { + this(filename, context, null); + } - public OCFFilenameChecker(ValidationContext context) + public OCFFilenameChecker(String filename, ValidationContext context, EPUBLocation location) { + Preconditions.checkArgument(filename != null); + Preconditions.checkArgument(context != null); + this.filename = filename; this.report = context.report; this.version = context.version; - this.location = EPUBLocation.of(context); + this.location = (location != null) ? location : EPUBLocation.of(context); } - public String checkCompatiblyEscaped(final String str) + @Override + public void check() { - // don't check remote resources - if (str.matches("^[^:/?#]+://.*")) - { - return ""; - } - - // the test string will be used to compare test result - String test = checkNonAsciiFilename(str); - - if (str.endsWith(".")) - { - report.message(MessageId.PKG_011, location, str); - test += "."; - } - - boolean spaces = false; - final char[] ascciGraphic = new char[] { '<', '>', '"', '{', '}', '|', '^', '`', '*', - '?' /* , ':','/', '\\' */ }; - String result = ""; - char[] chars = str.toCharArray(); - for (char c : chars) + // Iterate through the code points to search disallowed characters + UCharacterIterator chars = UCharacterIterator.getInstance(filename); + final Set disallowed = new LinkedHashSet<>(); + boolean hasSpaces = false; + boolean isASCIIOnly = true; + int codepoint; + while ((codepoint = chars.nextCodePoint()) != UForwardCharacterIterator.DONE) { - for (char a : ascciGraphic) + // Check if the string has non-ASCII characters + isASCIIOnly = isASCIIOnly && ASCII.contains(codepoint); + // Check if the string has space characters + hasSpaces = hasSpaces || UCharacter.isUWhiteSpace(codepoint); + // Check for disallowed characters + switch (version) { - if (c == a) + case VERSION_2: + if (DISALLOWED_EPUB2.contains(codepoint)) { - result += "\"" + Character.toString(c) + "\","; - test += Character.toString(c); + disallowed.add(toString(codepoint, "ASCII")); } - } - if (Character.isSpaceChar(c)) - { - spaces = true; - test += Character.toString(c); + break; + default: + for (String name : DISALLOWED_EPUB3.keySet()) + { + if (DISALLOWED_EPUB3.get(name).contains(codepoint)) + { + disallowed.add(toString(codepoint, name)); + break; + } + } + break; } } - if (result.length() > 1) + // Check that FULL STOP is not used as the last character + if (chars.previousCodePoint() == 0x002E) { - result = result.substring(0, result.length() - 1); - report.message(MessageId.PKG_009, location, str, result); + report.message(MessageId.PKG_011, location, filename); } - if (spaces) + // Report if disallowed characters were found + if (!disallowed.isEmpty()) { - report.message(MessageId.PKG_010, location, str); + report.message(MessageId.PKG_009, location, filename, + disallowed.stream().collect(Collectors.joining(", "))); } - - if (version == EPUBVersion.VERSION_3) + // Report whitespace characters + if (hasSpaces) { - checkCompatiblyEscaped30(str, test); + report.message(MessageId.PKG_010, location, filename); } - return test; - } - - private String checkNonAsciiFilename(final String str) - { - String nonAscii = str.replaceAll("[\\p{ASCII}]", ""); - if (nonAscii.length() > 0) + // Report non-ASCII characters as usage + if (!isASCIIOnly) { - report.message(MessageId.PKG_012, location, str, nonAscii); + report.message(MessageId.PKG_012, location, filename); } - return nonAscii; } - private String checkCompatiblyEscaped30(String str, String test) - { - String result = ""; - - char[] chars = str.toCharArray(); - for (char c : chars) - { - if (Character.isISOControl(c)) - { - result += "\"" + Character.toString(c) + "\","; - test += Character.toString(c); - } - - // DEL (U+007F) - if (c == '\u007F') - { - result += "\"" + Character.toString(c) + "\","; - test += Character.toString(c); - } - String unicodeType = Character.UnicodeBlock.of(c).toString(); - if (RESTRICTED_30_CHARACTER_SET.contains(unicodeType)) - { - result += "\"" + Character.toString(c) + "\","; - } - } - if (result.length() > 1) - { - result = result.substring(0, result.length() - 1); - report.message(MessageId.PKG_009, location, str, result); - } - return test; - } } diff --git a/src/main/java/com/adobe/epubcheck/opf/OPFChecker.java b/src/main/java/com/adobe/epubcheck/opf/OPFChecker.java index e54fe3b59..f69190ffb 100755 --- a/src/main/java/com/adobe/epubcheck/opf/OPFChecker.java +++ b/src/main/java/com/adobe/epubcheck/opf/OPFChecker.java @@ -207,16 +207,12 @@ protected boolean checkContent() for (OPFItem item : opfHandler.getItems()) { - // only check Filename CompatiblyEscaped when in "-mode opf" - // this is when 'xrefChecker' Object is null which is an indicator for - // single file validation - // (Had no better possibility in mind since "mode" isn't available in - // OPFChecker.java) - // - // bugfix for issue 239 - if (!context.xrefChecker.isPresent()) + // only check the filename in single-file mode + // (it is checked by the container checker in full-publication mode) + // and for local resources (i.e. computed to a file URL) + if (!context.container.isPresent() && !item.isRemote()) { - new OCFFilenameChecker(context).checkCompatiblyEscaped(item.getPath()); + new OCFFilenameChecker(item.getPath(), context, item.getLocation()).check(); } if (!item.equals(opfHandler.getItemByURL(item.getURL()).orNull())) { diff --git a/src/main/resources/com/adobe/epubcheck/messages/MessageBundle.properties b/src/main/resources/com/adobe/epubcheck/messages/MessageBundle.properties index a09ca0378..bed87d83a 100644 --- a/src/main/resources/com/adobe/epubcheck/messages/MessageBundle.properties +++ b/src/main/resources/com/adobe/epubcheck/messages/MessageBundle.properties @@ -297,10 +297,10 @@ PKG_005=The mimetype file has an extra field of length %1$s. The use of the extr PKG_006=Mimetype file entry is missing or is not the first file in the archive. PKG_007=Mimetype file should only contain the string "application/epub+zip" and should not be compressed. PKG_008=Unable to read file "%1$s". -PKG_009=File name contains characters that are not allowed in OCF file names: "%1$s". -PKG_010=Filename contains spaces, therefore URI escaping is necessary. Consider removing spaces from filename. -PKG_011=Filename is not allowed to end with ".". -PKG_012=File name contains the following non-ascii characters: %1$s. Consider changing the filename. +PKG_009=The file name "%1$s" contains characters that are not allowed in OCF file names: %2$s. +PKG_010=The file name "%1$s" contains spaces, which may create interoperability issues with older reading systems. +PKG_011=The file name "%1$s" is not allowed to end with ".". +PKG_012=The file name "%1$s" contains non-ASCII characters, which might create interoperability issues with older reading systems. PKG_013=The EPUB file includes multiple OPS renditions. PKG_014=The EPUB contains empty directory "%1$s". PKG_015=Unable to read EPUB contents: %1$s diff --git a/src/test/java/com/adobe/epubcheck/ocf/OCFFilenameCheckerTest.java b/src/test/java/com/adobe/epubcheck/ocf/OCFFilenameCheckerTest.java deleted file mode 100644 index 7fa7fd726..000000000 --- a/src/test/java/com/adobe/epubcheck/ocf/OCFFilenameCheckerTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2011 Adobe Systems Incorporated - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package com.adobe.epubcheck.ocf; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import com.adobe.epubcheck.api.EPUBProfile; -import com.adobe.epubcheck.api.Report; -import com.adobe.epubcheck.opf.ValidationContext; -import com.adobe.epubcheck.util.EPUBVersion; -import com.adobe.epubcheck.util.Messages; -import com.adobe.epubcheck.util.ValidationReport; -import com.adobe.epubcheck.util.outWriter; - -public class OCFFilenameCheckerTest -{ - - private boolean verbose = false; - private final Messages messages = Messages.getInstance(); - - /* - * TEST DEBUG FUNCTION - */ - public void testValidateDocument(String fileName, String expected, EPUBVersion version, - boolean verbose) - { - if (verbose) - { - this.verbose = verbose; - } - testValidateDocument(fileName, expected, version); - - } - - public void testValidateDocument(String fileName, String expected, EPUBVersion version) - { - Report testReport = new ValidationReport(fileName, - String.format(messages.get("single_file"), "opf", version.toString(), EPUBProfile.DEFAULT)); - - ValidationContext testContext = ValidationContext.test().report(testReport).version(version) - .build(); - - OCFFilenameChecker checker = new OCFFilenameChecker(testContext); - - String result = checker.checkCompatiblyEscaped(fileName); - - if (verbose) - { - verbose = false; - outWriter.println(testReport); - outWriter.println("Test result: " + result + " \nExpected: " + expected); - } - - assertEquals(expected, result); - } - - @Test - public void testValidateDocumentTest001() - { - testValidateDocument("abc\u3053abc", "\u3053", EPUBVersion.VERSION_3); - } - - @Test - public void testValidateDocumentTest002() - { - testValidateDocument("www.google.ro.", ".", EPUBVersion.VERSION_3); - } - - @Test - public void testValidateDocumentTest003() - { - testValidateDocument("go gle/ro", " ", EPUBVersion.VERSION_3); - } - - @Test - public void testValidateDocumentTest004() - { - testValidateDocument("/foo/b>ar/quux", ">", EPUBVersion.VERSION_3); - } - - @Test - public void testValidateDocumentTest005() - { - testValidateDocument("/foo/b>ar/quu\uE000x", "\uE000>", EPUBVersion.VERSION_3); - } - - @Test - public void testValidateDocumentTest006() - { - testValidateDocument("http://www% .google.ro", "", EPUBVersion.VERSION_2); - } -} diff --git a/src/test/java/org/w3c/epubcheck/container/FilenameCheckerSteps.java b/src/test/java/org/w3c/epubcheck/container/FilenameCheckerSteps.java new file mode 100644 index 000000000..860f6fba4 --- /dev/null +++ b/src/test/java/org/w3c/epubcheck/container/FilenameCheckerSteps.java @@ -0,0 +1,41 @@ +package org.w3c.epubcheck.container; + +import org.w3c.epubcheck.test.TestConfiguration; + +import com.adobe.epubcheck.ocf.OCFFilenameChecker; +import com.adobe.epubcheck.opf.ValidationContext; + +import io.cucumber.java.ParameterType; +import io.cucumber.java.en.When; + +public class FilenameCheckerSteps +{ + + private final ValidationContext context; + + public FilenameCheckerSteps(TestConfiguration configuration) + { + this.context = configuration.getContextBuilder().build(); + } + + @ParameterType("U\\+[0-9a-zA-Z]{4,6}") + public int codepoint(String codepoint) + { + return Integer.valueOf(codepoint.substring(2), 16); + } + + @When("checking file name {string}") + public void checkFilename(String string) + { + new OCFFilenameChecker(string, context).check(); + } + + @When("checking file name containing code point {codepoint}") + public void checkFilenameWithCodepoint(int codepoint) + { + new OCFFilenameChecker( + new StringBuilder().append("a").appendCodePoint(codepoint).append("name").toString(), + context).check(); + } + +} diff --git a/src/test/resources/epub3/04-ocf/filename-checker.feature b/src/test/resources/epub3/04-ocf/filename-checker.feature new file mode 100644 index 000000000..e8d685f4b --- /dev/null +++ b/src/test/resources/epub3/04-ocf/filename-checker.feature @@ -0,0 +1,84 @@ +Feature: File name checker + + Tests the checker for disallowed characters in file names. + + Note that these test cases evaluate raw Unicode file name strings. + Additional functional tests (based on full publications or package documents) + are also available in the feature file for container-relates tests. + + Scenario Outline: valid file name '' is accepted + When checking file name '' + Then no error or warning is reported + + Scenarios: + | filename | + | only-ascii | + | not-ascii-รฉ | + | ideograph-ไ€€ | + | emoji-๐Ÿ˜Š | + | emoji-tag-sequence-๐Ÿด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ | + + Scenario Outline: space () is reported as warning + When checking file name containing code point + Then warning PKG-010 is reported + + Scenarios: + | codepoint | name | + | U+0009 | TAB | + | U+000A | LF | + | U+000C | FF | + | U+000D | CR | + | U+0020 | SPACE | + | U+2009 | THIN SPACE | + + Scenario: disallow FULL STOP as the last character + When checking file name 'aname.' + Then error PKG-011 is reported + + Scenario: disallowed characters are reported + When checking file name 'a*name' + Then error PKG-009 is reported + Then the message contains 'U+002A (*)' + + Scenario: disallowed characters are all reported + When checking file name 'a*na"me' + Then error PKG-009 is reported + Then the message contains 'U+002A (*), U+0022 (")' + + Scenario: disallowed characters are reported only once + When checking file name 'a*na*me' + Then error PKG-009 is reported + Then the message contains 'U+002A (*).' + + Scenario Outline: disallowed character is reported + When checking file name containing code point + Then error PKG-009 is reported + And the message contains ' ' + + Scenarios: + | codepoint | tostring | + | U+0022 | (") | + | U+002A | (*) | + | U+003A | (:) | + | U+003C | (<) | + | U+003E | (>) | + | U+003F | (?) | + | U+005C | (\) | + | U+007C | (\|) | + | U+007F | (CONTROL) | + | U+0000 | (CONTROL) | + | U+0080 | (CONTROL) | + | U+E000 | (PRIVATE USE) | + | U+FDD0 | (NON CHARACTER) | + | U+FFFD | REPLACEMENT CHARACTER (SPECIALS) | + | U+FFFE | (NON CHARACTER) | + | U+9FFFE | (NON CHARACTER) | + | U+E0001 | LANGUAGE TAG (DEPRECATED) | + #| U+E007F | CANCEL TAG | # Re-instated for ETS use + | U+F0001 | (PRIVATE USE) | + | U+100000 | (PRIVATE USE) | + + Scenario: VERTICAL LINE (|) is not disallowed in EPUB 2.0.1 + Given EPUBCheck configured to check EPUB 2 rules + When checking file name 'a|name' + Then no error or warning is reported diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error/EPUB/content_001.xhtml "b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-emoji-tag-sequence-valid/EPUB/content_\360\237\217\264\363\240\201\247\363\240\201\242\363\240\201\245\363\240\201\256\363\240\201\247\363\240\201\277.xhtml" similarity index 100% rename from src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error/EPUB/content_001.xhtml rename to "src/test/resources/epub3/04-ocf/files/ocf-filename-character-emoji-tag-sequence-valid/EPUB/content_\360\237\217\264\363\240\201\247\363\240\201\242\363\240\201\245\363\240\201\256\363\240\201\247\363\240\201\277.xhtml" diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-emoji-tag-sequence-valid/EPUB/nav.xhtml b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-emoji-tag-sequence-valid/EPUB/nav.xhtml new file mode 100644 index 000000000..a11ebc68d --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-emoji-tag-sequence-valid/EPUB/nav.xhtml @@ -0,0 +1,14 @@ + + + + + Minimal Nav + + + + + diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-emoji-tag-sequence-valid/EPUB/package.opf b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-emoji-tag-sequence-valid/EPUB/package.opf new file mode 100644 index 000000000..77441bdac --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-emoji-tag-sequence-valid/EPUB/package.opf @@ -0,0 +1,16 @@ + + + + Minimal EPUB 3.0 + en + NOID + 2017-06-14T00:00:01Z + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-emoji-tag-sequence-valid/META-INF/container.xml b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-emoji-tag-sequence-valid/META-INF/container.xml new file mode 100644 index 000000000..318782179 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-emoji-tag-sequence-valid/META-INF/container.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-emoji-tag-sequence-valid/mimetype b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-emoji-tag-sequence-valid/mimetype new file mode 100644 index 000000000..57ef03f24 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-emoji-tag-sequence-valid/mimetype @@ -0,0 +1 @@ +application/epub+zip \ No newline at end of file diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error.opf b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error.opf new file mode 100644 index 000000000..ffb6b06a0 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error.opf @@ -0,0 +1,16 @@ + + + + Minimal EPUB 3.0 + en + NOID + 2017-06-14T00:00:01Z + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error/EPUB/content_|.xhtml b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error/EPUB/content_|.xhtml new file mode 100644 index 000000000..ea29a1610 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error/EPUB/content_|.xhtml @@ -0,0 +1,11 @@ + + + + + Minimal EPUB + + +

Loomings

+

Call me Ishmael.

+ + diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error/EPUB/nav.xhtml b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error/EPUB/nav.xhtml new file mode 100644 index 000000000..508931b93 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error/EPUB/nav.xhtml @@ -0,0 +1,14 @@ + + + + + Minimal Nav + + + + + diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error/EPUB/package.opf b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error/EPUB/package.opf index 44f20ae4b..ffb6b06a0 100644 --- a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error/EPUB/package.opf +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error/EPUB/package.opf @@ -7,8 +7,8 @@ 2017-06-14T00:00:01Z - - + + diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-in-remote-URL-valid.opf b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-in-remote-URL-valid.opf new file mode 100644 index 000000000..ee1dd54b1 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-in-remote-URL-valid.opf @@ -0,0 +1,17 @@ + + + + Minimal EPUB 3.0 + en + NOID + 2017-06-14T00:00:01Z + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/EPUB/content_001.xhtml b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/EPUB/content_001.xhtml new file mode 100644 index 000000000..ea29a1610 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/EPUB/content_001.xhtml @@ -0,0 +1,11 @@ + + + + + Minimal EPUB + + +

Loomings

+

Call me Ishmael.

+ + diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error/EPUB/nav_{}.xhtml b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/EPUB/nav.xhtml similarity index 100% rename from src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-error/EPUB/nav_{}.xhtml rename to src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/EPUB/nav.xhtml diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/EPUB/package.opf b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/EPUB/package.opf new file mode 100644 index 000000000..0d1eec6e9 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/EPUB/package.opf @@ -0,0 +1,16 @@ + + + + Minimal EPUB 3.0 + en + NOID + 2017-06-14T00:00:01Z + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/META-INF/container.xml b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/META-INF/container.xml new file mode 100644 index 000000000..318782179 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/META-INF/container.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/META-INF/file_<>.txt b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/META-INF/file_<>.txt new file mode 100644 index 000000000..e69de29bb diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/mimetype b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/mimetype new file mode 100644 index 000000000..57ef03f24 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-forbidden-non-publication-resource-error/mimetype @@ -0,0 +1 @@ +application/epub+zip \ No newline at end of file diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-non-ascii-warning.opf b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-non-ascii-warning.opf new file mode 100644 index 000000000..ed2f02006 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-non-ascii-warning.opf @@ -0,0 +1,16 @@ + + + + Minimal EPUB 3.0 + en + NOID + 2017-06-14T00:00:01Z + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning.opf b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning.opf new file mode 100644 index 000000000..8ab0fcbe4 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning.opf @@ -0,0 +1,16 @@ + + + + Minimal EPUB 3.0 + en + NOID + 2017-06-14T00:00:01Z + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/EPUB/content 001.xhtml b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/EPUB/content 001.xhtml new file mode 100644 index 000000000..ea29a1610 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/EPUB/content 001.xhtml @@ -0,0 +1,11 @@ + + + + + Minimal EPUB + + +

Loomings

+

Call me Ishmael.

+ + diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/EPUB/nav.xhtml b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/EPUB/nav.xhtml new file mode 100644 index 000000000..83df7550b --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/EPUB/nav.xhtml @@ -0,0 +1,14 @@ + + + + + Minimal Nav + + + + + diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/EPUB/package.opf b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/EPUB/package.opf new file mode 100644 index 000000000..8ab0fcbe4 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/EPUB/package.opf @@ -0,0 +1,16 @@ + + + + Minimal EPUB 3.0 + en + NOID + 2017-06-14T00:00:01Z + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/META-INF/container.xml b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/META-INF/container.xml new file mode 100644 index 000000000..318782179 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/META-INF/container.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/mimetype b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/mimetype new file mode 100644 index 000000000..57ef03f24 --- /dev/null +++ b/src/test/resources/epub3/04-ocf/files/ocf-filename-character-space-warning/mimetype @@ -0,0 +1 @@ +application/epub+zip \ No newline at end of file diff --git a/src/test/resources/epub3/04-ocf/ocf.feature b/src/test/resources/epub3/04-ocf/ocf.feature index 001c2adbe..017e9c55a 100644 --- a/src/test/resources/epub3/04-ocf/ocf.feature +++ b/src/test/resources/epub3/04-ocf/ocf.feature @@ -41,15 +41,55 @@ Feature: EPUB 3 โ€” Open Container Format And no other errors or warnings are reported @spec @xref:sec-container-filenames - Scenario: Report forbidden characters in filenames + Scenario: Allow Unicode emoji tag set in file name + When checking EPUB 'ocf-filename-character-emoji-tag-sequence-valid' + Then no other errors or warnings are reported + + @spec @xref:sec-container-filenames + Scenario: Report forbidden characters in file names When checking EPUB 'ocf-filename-character-forbidden-error' - And error PKG-009 is reported + Then error PKG-009 is reported + And no other errors or warnings are reported + + @spec @xref:sec-container-filenames + Scenario: Report forbidden characters in file names even for non-publication resources + When checking EPUB 'ocf-filename-character-forbidden-non-publication-resource-error' + Then error PKG-009 is reported + And no other errors or warnings are reported + + @spec @xref:sec-container-filenames + Scenario: Allow forbidden characters in remote resource URLs + When checking EPUB 'ocf-filename-character-forbidden-in-remote-URL-valid.opf' + Then no other errors or warnings are reported + + @spec @xref:sec-container-filenames + Scenario: Report forbidden characters in file names (single package doc check) + When checking EPUB 'ocf-filename-character-forbidden-error.opf' + Then error PKG-009 is reported And no other errors or warnings are reported - Scenario: Report non-ASCII characters in filenames + Scenario: Inform about non-ASCII characters in file names (full-publication check) Given the reporting level is set to USAGE When checking EPUB 'ocf-filename-character-non-ascii-warning' - And usage PKG-012 is reported + Then usage PKG-012 is reported + And no other errors or warnings are reported + + Scenario: Inform about non-ASCII characters in file names (single package doc check) + Given the reporting level is set to USAGE + When checking EPUB 'ocf-filename-character-non-ascii-warning.opf' + Then usage PKG-012 is reported + And no other errors or warnings are reported + + @spec @xref:sec-container-filenames + Scenario: Warn about spaces in file names (full-publication check) + When checking file 'ocf-filename-character-space-warning' + Then warning PKG-010 is reported + And no other errors or warnings are reported + + @spec @xref:sec-container-filenames + Scenario: Warn about spaces in file names (single package doc check) + When checking file 'ocf-filename-character-space-warning.opf' + Then warning PKG-010 is reported And no other errors or warnings are reported ### 4.1.5 URLs in the OCF abstract container diff --git a/src/test/resources/epub3/05-package-document/files/item-href-contains-spaces-warning.opf b/src/test/resources/epub3/05-package-document/files/item-href-contains-spaces-warning.opf deleted file mode 100644 index d5510d048..000000000 --- a/src/test/resources/epub3/05-package-document/files/item-href-contains-spaces-warning.opf +++ /dev/null @@ -1,17 +0,0 @@ - - - - xxx - Title - en - 2019-01-01T12:00:00Z - - - - - - - - - diff --git a/src/test/resources/epub3/05-package-document/package-document.feature b/src/test/resources/epub3/05-package-document/package-document.feature index 8a9463379..239211170 100644 --- a/src/test/resources/epub3/05-package-document/package-document.feature +++ b/src/test/resources/epub3/05-package-document/package-document.feature @@ -420,17 +420,12 @@ Feature: EPUB 3 โ€” Package document And the message contains 'missing required attribute "media-type"' And no other errors or warnings are reported - Scenario: item URLs should not contain spaces, even if properly encoded + Scenario: item URLs must be properly encoded When checking file 'item-href-contains-spaces-unencoded-error.opf' Then error RSC-020 is reported And warning PKG-010 is reported (side effect of spaces) And no other errors or warnings are reported - Scenario: item URLs should not contain spaces, even if properly encoded - When checking file 'item-href-contains-spaces-warning.opf' - Then warning PKG-010 is reported - And no other errors or warnings are reported - @spec @xref:sec-item-elem Scenario: item URLs must not have a fragment identifier When checking file 'item-href-with-fragment-error.opf'