Author: sebb Date: Wed Jan 14 23:09:12 2015 New Revision: 1651873 URL: http://svn.apache.org/r1651873 Log: VALIDATOR-356 IDN.toASCII drops trailing dot in Java 6 & 7
Modified: commons/proper/validator/trunk/src/changes/changes.xml commons/proper/validator/trunk/src/main/java/org/apache/commons/validator/routines/DomainValidator.java commons/proper/validator/trunk/src/test/java/org/apache/commons/validator/routines/DomainValidatorTest.java commons/proper/validator/trunk/src/test/java/org/apache/commons/validator/routines/UrlValidatorTest.java Modified: commons/proper/validator/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/validator/trunk/src/changes/changes.xml?rev=1651873&r1=1651872&r2=1651873&view=diff ============================================================================== --- commons/proper/validator/trunk/src/changes/changes.xml (original) +++ commons/proper/validator/trunk/src/changes/changes.xml Wed Jan 14 23:09:12 2015 @@ -43,6 +43,9 @@ The <action> type attribute can be add,u <body> <release version="1.5.0" date="tba" description="tba"> + <action issue="VALIDATOR-356" dev="seb" type="fix" > + IDN.toASCII drops trailing dot in Java 6 & 7 + </action> <action issue="VALIDATOR-355" dev="britter" type="update" > Update to Java 6 </action> Modified: commons/proper/validator/trunk/src/main/java/org/apache/commons/validator/routines/DomainValidator.java URL: http://svn.apache.org/viewvc/commons/proper/validator/trunk/src/main/java/org/apache/commons/validator/routines/DomainValidator.java?rev=1651873&r1=1651872&r2=1651873&view=diff ============================================================================== --- commons/proper/validator/trunk/src/main/java/org/apache/commons/validator/routines/DomainValidator.java (original) +++ commons/proper/validator/trunk/src/main/java/org/apache/commons/validator/routines/DomainValidator.java Wed Jan 14 23:09:12 2015 @@ -1085,16 +1085,46 @@ public class DomainValidator implements */ // Needed by UrlValidator static String unicodeToASCII(String input) { - if (isOnlyASCII(input)) { // TODO temporary hack to work round IDN.toASCII bug + if (isOnlyASCII(input)) { // skip possibly expensive processing return input; } try { - return IDN.toASCII(input); + final String ascii = IDN.toASCII(input); + if (IDNBUGHOLDER.IDN_TOASCII_PRESERVES_TRAILING_DOTS) { + return ascii; + } + final int length = input.length(); + if (length == 0) {// check there is a last character + return input; + } +// RFC3490 3.1. 1) +// Whenever dots are used as label separators, the following +// characters MUST be recognized as dots: U+002E (full stop), U+3002 +// (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61 +// (halfwidth ideographic full stop). + char lastChar = input.charAt(length-1);// fetch original last char + switch(lastChar) { + case '\u002E': // "." full stop + case '\u3002': // ideographic full stop + case '\uFF0E': // fullwidth full stop + case '\uFF61': // halfwidth ideographic full stop + return ascii + "."; // restore the missing stop + default: + return ascii; + } } catch (IllegalArgumentException e) { // input is not valid return input; } } + private static class IDNBUGHOLDER { + private static boolean keepsTrailingDot() { + final String input = "a."; // must be a valid name + return input.equals(IDN.toASCII(input)); + } + private static final boolean IDN_TOASCII_PRESERVES_TRAILING_DOTS = keepsTrailingDot(); + } + /* * Check if input contains only ASCII * Treats null as all ASCII Modified: commons/proper/validator/trunk/src/test/java/org/apache/commons/validator/routines/DomainValidatorTest.java URL: http://svn.apache.org/viewvc/commons/proper/validator/trunk/src/test/java/org/apache/commons/validator/routines/DomainValidatorTest.java?rev=1651873&r1=1651872&r2=1651873&view=diff ============================================================================== --- commons/proper/validator/trunk/src/test/java/org/apache/commons/validator/routines/DomainValidatorTest.java (original) +++ commons/proper/validator/trunk/src/test/java/org/apache/commons/validator/routines/DomainValidatorTest.java Wed Jan 14 23:09:12 2015 @@ -208,6 +208,67 @@ public class DomainValidatorTest extends assertFalse("254 chars domain should fail", validator.isValidDomainSyntax(longDomain+"x")); } + // Check that IDN.toASCII behaves as it should (when wrapped by DomainValidator.unicodeToASCII) + // Tests show that method incorrectly trims a trailing "." character + public void testUnicodeToASCII() { + String[] asciidots = { + "", + ",", + ".", // fails IDN.toASCII, but should pass wrapped version + "a.", // ditto + "a.b", + "a..b", + "a...b", + ".a", + "..a", + }; + for(String s : asciidots) { + assertEquals(s,DomainValidator.unicodeToASCII(s)); + } + // RFC3490 3.1. 1) +// Whenever dots are used as label separators, the following +// characters MUST be recognized as dots: U+002E (full stop), U+3002 +// (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61 +// (halfwidth ideographic full stop). + final String otherDots[][] = { + {"b\u3002", "b.",}, + {"b\uFF0E", "b.",}, + {"b\uFF61", "b.",}, + {"\u3002", ".",}, + {"\uFF0E", ".",}, + {"\uFF61", ".",}, + }; + for(String s[] : otherDots) { + assertEquals(s[1],DomainValidator.unicodeToASCII(s[0])); + } + } + + // Check if IDN.toASCII is broken or not + public void testIsIDNtoASCIIBroken() { + System.out.println(">>DomainValidatorTest.testIsIDNtoASCIIBroken()"); + final String input = "."; + final boolean ok = input.equals(IDN.toASCII(input)); + System.out.println("IDN.toASCII is " + (ok? "OK" : "BROKEN")); + String props[] = { + "java.version", // Java Runtime Environment version + "java.vendor", // Java Runtime Environment vendor + "java.vm.specification.version", // Java Virtual Machine specification version + "java.vm.specification.vendor", // Java Virtual Machine specification vendor + "java.vm.specification.name", // Java Virtual Machine specification name + "java.vm.version", // Java Virtual Machine implementation version + "java.vm.vendor", // Java Virtual Machine implementation vendor + "java.vm.name", // Java Virtual Machine implementation name + "java.specification.version", // Java Runtime Environment specification version + "java.specification.vendor", // Java Runtime Environment specification vendor + "java.specification.name", // Java Runtime Environment specification name + "java.class.version", // Java class format version number + }; + for(String t : props) { + System.out.println(t + "=" + System.getProperty(t)); + } + System.out.println("<<DomainValidatorTest.testIsIDNtoASCIIBroken()"); + } + // Check array is sorted and is lower-case public void test_INFRASTRUCTURE_TLDS_sortedAndLowerCase() throws Exception { final boolean sorted = isSortedLowerCase("INFRASTRUCTURE_TLDS"); Modified: commons/proper/validator/trunk/src/test/java/org/apache/commons/validator/routines/UrlValidatorTest.java URL: http://svn.apache.org/viewvc/commons/proper/validator/trunk/src/test/java/org/apache/commons/validator/routines/UrlValidatorTest.java?rev=1651873&r1=1651872&r2=1651873&view=diff ============================================================================== --- commons/proper/validator/trunk/src/test/java/org/apache/commons/validator/routines/UrlValidatorTest.java (original) +++ commons/proper/validator/trunk/src/test/java/org/apache/commons/validator/routines/UrlValidatorTest.java Wed Jan 14 23:09:12 2015 @@ -295,6 +295,15 @@ public class UrlValidatorTest extends Te assertFalse(urlValidator.isValid("http://www.cnn.invalid./")); // check . does not affect invalid domains } + public void testValidator339IDN(){ + UrlValidator urlValidator = new UrlValidator(); + assertTrue(urlValidator.isValid("http://пÑезиденÑ.ÑÑ/WORLD/?hpt=sitenav")); // without + assertTrue(urlValidator.isValid("http://пÑезиденÑ.ÑÑ./WORLD/?hpt=sitenav")); // with + assertFalse(urlValidator.isValid("http://пÑезиденÑ.ÑÑ..../")); // very dotty + assertFalse(urlValidator.isValid("http://пÑезиденÑ.ÑÑ.../")); // triply dotty + assertFalse(urlValidator.isValid("http://пÑезиденÑ.ÑÑ../")); // doubly dotty + } + public void testValidator342(){ UrlValidator urlValidator = new UrlValidator(); assertTrue(urlValidator.isValid("http://example.rocks/"));