diff --git a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/PublicSuffixFilter.java b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/PublicSuffixFilter.java index 111d806ff..c1b932304 100644 --- a/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/PublicSuffixFilter.java +++ b/httpclient/src/main/java-deprecated/org/apache/http/impl/cookie/PublicSuffixFilter.java @@ -104,6 +104,6 @@ public class PublicSuffixFilter implements CookieAttributeHandler { if (matcher == null) { matcher = new PublicSuffixMatcher(this.suffixes, this.exceptions); } - return matcher.match(cookie.getDomain()); + return matcher.matches(cookie.getDomain()); } } diff --git a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java index 248df90f8..d3993f595 100644 --- a/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java +++ b/httpclient/src/main/java/org/apache/http/conn/util/PublicSuffixMatcher.java @@ -28,6 +28,7 @@ package org.apache.http.conn.util; import java.net.IDN; import java.util.Collection; +import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -66,36 +67,55 @@ public final class PublicSuffixMatcher { } } - public boolean match(final String domain) { - String s = domain; - if (s == null) { - return false; + /** + * Returns registrable part of the domain for the given domain name of {@code null} + * if given domain represents a public suffix. + * + * @param domain + * @return + */ + public String getDomainRoot(final String domain) { + if (domain == null) { + return null; } - if (s.startsWith(".")) { - s = s.substring(1); + if (domain.startsWith(".")) { + return null; } - s = IDN.toUnicode(s); + String domainName = null; + String segment = domain.toLowerCase(Locale.ROOT); + while (segment != null) { - // An exception rule takes priority over any other matching rule. - if (this.exceptions != null && this.exceptions.containsKey(s)) { - return false; - } + // An exception rule takes priority over any other matching rule. + if (this.exceptions != null && this.exceptions.containsKey(IDN.toUnicode(segment))) { + return segment; + } - do { - if (this.rules.containsKey(s)) { - return true; - } - // patterns - if (s.startsWith("*.")) { - s = s.substring(2); - } - final int nextdot = s.indexOf('.'); - if (nextdot == -1) { + if (this.rules.containsKey(IDN.toUnicode(segment))) { break; } - s = "*" + s.substring(nextdot); - } while (!s.isEmpty()); - return false; + final int nextdot = segment.indexOf('.'); + final String nextSegment = nextdot != -1 ? segment.substring(nextdot + 1) : null; + + if (nextSegment != null) { + if (this.rules.containsKey("*." + IDN.toUnicode(nextSegment))) { + break; + } + } + if (nextdot != -1) { + domainName = segment; + } + segment = nextSegment; + } + return domainName; } + + public boolean matches(final String domain) { + if (domain == null) { + return false; + } + final String domainRoot = getDomainRoot(domain.startsWith(".") ? domain.substring(1) : domain); + return domainRoot == null; + } + } diff --git a/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java b/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java index f5b7c4eb1..0211d08a5 100644 --- a/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java +++ b/httpclient/src/main/java/org/apache/http/impl/cookie/PublicSuffixDomainFilter.java @@ -70,7 +70,8 @@ public class PublicSuffixDomainFilter implements CommonCookieAttributeHandler { */ @Override public boolean match(final Cookie cookie, final CookieOrigin origin) { - if (matcher.match(cookie.getDomain())) { + final String domain = cookie.getDomain(); + if (matcher.matches(domain) && !domain.equalsIgnoreCase("localhost")) { return false; } else { return handler.match(cookie, origin); diff --git a/httpclient/src/test/java/org/apache/http/conn/util/TestPublicSuffixMatcher.java b/httpclient/src/test/java/org/apache/http/conn/util/TestPublicSuffixMatcher.java index 894408e20..8c124fff8 100644 --- a/httpclient/src/test/java/org/apache/http/conn/util/TestPublicSuffixMatcher.java +++ b/httpclient/src/test/java/org/apache/http/conn/util/TestPublicSuffixMatcher.java @@ -57,29 +57,36 @@ public class TestPublicSuffixMatcher { } @Test - public void testParse() throws Exception { - Assert.assertTrue(matcher.match(".jp")); - Assert.assertTrue(matcher.match(".ac.jp")); - Assert.assertTrue(matcher.match(".any.tokyo.jp")); + public void testGetDomainRoot() throws Exception { + Assert.assertEquals("example.xx", matcher.getDomainRoot("example.XX")); + Assert.assertEquals("example.xx", matcher.getDomainRoot("www.example.XX")); + Assert.assertEquals("example.xx", matcher.getDomainRoot("www.blah.blah.example.XX")); + Assert.assertEquals(null, matcher.getDomainRoot("xx")); + Assert.assertEquals(null, matcher.getDomainRoot("jp")); + Assert.assertEquals(null, matcher.getDomainRoot("example")); + Assert.assertEquals("example.example", matcher.getDomainRoot("example.example")); + Assert.assertEquals(null, matcher.getDomainRoot("ac.jp")); + Assert.assertEquals(null, matcher.getDomainRoot("any.tokyo.jp")); + Assert.assertEquals("metro.tokyo.jp", matcher.getDomainRoot("metro.tokyo.jp")); + Assert.assertEquals("blah.blah.tokyo.jp", matcher.getDomainRoot("blah.blah.tokyo.jp")); + Assert.assertEquals("blah.ac.jp", matcher.getDomainRoot("blah.blah.ac.jp")); + } + + @Test + public void testMatch() throws Exception { + Assert.assertTrue(matcher.matches(".jp")); + Assert.assertTrue(matcher.matches(".ac.jp")); + Assert.assertTrue(matcher.matches(".any.tokyo.jp")); // exception - Assert.assertFalse(matcher.match(".metro.tokyo.jp")); + Assert.assertFalse(matcher.matches(".metro.tokyo.jp")); } @Test - public void testUnicode() throws Exception { - Assert.assertTrue(matcher.match(".h\u00E5.no")); // \u00E5 is - Assert.assertTrue(matcher.match(".xn--h-2fa.no")); - Assert.assertTrue(matcher.match(".h\u00E5.no")); - Assert.assertTrue(matcher.match(".xn--h-2fa.no")); - } - - @Test - public void testWhitespace() throws Exception { - Assert.assertTrue(matcher.match(".xx")); - // yy appears after whitespace - Assert.assertFalse(matcher.match(".yy")); - // zz is commented - Assert.assertFalse(matcher.match(".zz")); + public void testMatchUnicode() throws Exception { + Assert.assertTrue(matcher.matches(".h\u00E5.no")); // \u00E5 is + Assert.assertTrue(matcher.matches(".xn--h-2fa.no")); + Assert.assertTrue(matcher.matches(".h\u00E5.no")); + Assert.assertTrue(matcher.matches(".xn--h-2fa.no")); } } diff --git a/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicCookieAttribHandlers.java b/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicCookieAttribHandlers.java index 8c3bf2993..ce6bd15c6 100644 --- a/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicCookieAttribHandlers.java +++ b/httpclient/src/test/java/org/apache/http/impl/cookie/TestBasicCookieAttribHandlers.java @@ -482,12 +482,24 @@ public class TestBasicCookieAttribHandlers { cookie.setDomain("co.uk"); Assert.assertFalse(h.match(cookie, new CookieOrigin("apache.co.uk", 80, "/stuff", false))); + cookie.setDomain(".co.com"); + Assert.assertTrue(h.match(cookie, new CookieOrigin("apache.co.com", 80, "/stuff", false))); + + cookie.setDomain("co.com"); + Assert.assertFalse(h.match(cookie, new CookieOrigin("apache.co.com", 80, "/stuff", false))); + cookie.setDomain(".com"); Assert.assertFalse(h.match(cookie, new CookieOrigin("apache.com", 80, "/stuff", false))); cookie.setDomain("com"); Assert.assertFalse(h.match(cookie, new CookieOrigin("apache.com", 80, "/stuff", false))); + cookie.setDomain("apache.com"); + Assert.assertTrue(h.match(cookie, new CookieOrigin("apache.com", 80, "/stuff", false))); + + cookie.setDomain(".apache.com"); + Assert.assertTrue(h.match(cookie, new CookieOrigin("www.apache.com", 80, "/stuff", false))); + cookie.setDomain("localhost"); Assert.assertTrue(h.match(cookie, new CookieOrigin("localhost", 80, "/stuff", false))); } diff --git a/httpclient/src/test/java/org/apache/http/impl/cookie/TestPublicSuffixListParser.java b/httpclient/src/test/java/org/apache/http/impl/cookie/TestPublicSuffixListParser.java index ac58e58bd..86dded928 100644 --- a/httpclient/src/test/java/org/apache/http/impl/cookie/TestPublicSuffixListParser.java +++ b/httpclient/src/test/java/org/apache/http/impl/cookie/TestPublicSuffixListParser.java @@ -95,19 +95,4 @@ public class TestPublicSuffixListParser { Assert.assertFalse(filter.match(cookie, new CookieOrigin("apache.h\u00E5.no", 80, "/stuff", false))); } - @Test - public void testWhitespace() throws Exception { - final BasicClientCookie cookie = new BasicClientCookie("name", "value"); - cookie.setDomain(".xx"); - Assert.assertFalse(filter.match(cookie, new CookieOrigin("apache.xx", 80, "/stuff", false))); - - // yy appears after whitespace - cookie.setDomain(".yy"); - Assert.assertTrue(filter.match(cookie, new CookieOrigin("apache.yy", 80, "/stuff", false))); - - // zz is commented - cookie.setDomain(".zz"); - Assert.assertTrue(filter.match(cookie, new CookieOrigin("apache.zz", 80, "/stuff", false))); - } - }