mobile/android/thirdparty/ch/boye/httpclientandroidlib/impl/cookie/RFC2965DomainAttributeHandler.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /*
michael@0 2 * ====================================================================
michael@0 3 * Licensed to the Apache Software Foundation (ASF) under one
michael@0 4 * or more contributor license agreements. See the NOTICE file
michael@0 5 * distributed with this work for additional information
michael@0 6 * regarding copyright ownership. The ASF licenses this file
michael@0 7 * to you under the Apache License, Version 2.0 (the
michael@0 8 * "License"); you may not use this file except in compliance
michael@0 9 * with the License. You may obtain a copy of the License at
michael@0 10 *
michael@0 11 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 12 *
michael@0 13 * Unless required by applicable law or agreed to in writing,
michael@0 14 * software distributed under the License is distributed on an
michael@0 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
michael@0 16 * KIND, either express or implied. See the License for the
michael@0 17 * specific language governing permissions and limitations
michael@0 18 * under the License.
michael@0 19 * ====================================================================
michael@0 20 *
michael@0 21 * This software consists of voluntary contributions made by many
michael@0 22 * individuals on behalf of the Apache Software Foundation. For more
michael@0 23 * information on the Apache Software Foundation, please see
michael@0 24 * <http://www.apache.org/>.
michael@0 25 *
michael@0 26 */
michael@0 27
michael@0 28 package ch.boye.httpclientandroidlib.impl.cookie;
michael@0 29
michael@0 30 import java.util.Locale;
michael@0 31
michael@0 32 import ch.boye.httpclientandroidlib.annotation.Immutable;
michael@0 33
michael@0 34 import ch.boye.httpclientandroidlib.cookie.ClientCookie;
michael@0 35 import ch.boye.httpclientandroidlib.cookie.Cookie;
michael@0 36 import ch.boye.httpclientandroidlib.cookie.CookieAttributeHandler;
michael@0 37 import ch.boye.httpclientandroidlib.cookie.CookieOrigin;
michael@0 38 import ch.boye.httpclientandroidlib.cookie.CookieRestrictionViolationException;
michael@0 39 import ch.boye.httpclientandroidlib.cookie.MalformedCookieException;
michael@0 40 import ch.boye.httpclientandroidlib.cookie.SetCookie;
michael@0 41
michael@0 42 /**
michael@0 43 * <tt>"Domain"</tt> cookie attribute handler for RFC 2965 cookie spec.
michael@0 44 *
michael@0 45 *
michael@0 46 * @since 3.1
michael@0 47 */
michael@0 48 @Immutable
michael@0 49 public class RFC2965DomainAttributeHandler implements CookieAttributeHandler {
michael@0 50
michael@0 51 public RFC2965DomainAttributeHandler() {
michael@0 52 super();
michael@0 53 }
michael@0 54
michael@0 55 /**
michael@0 56 * Parse cookie domain attribute.
michael@0 57 */
michael@0 58 public void parse(final SetCookie cookie, String domain)
michael@0 59 throws MalformedCookieException {
michael@0 60 if (cookie == null) {
michael@0 61 throw new IllegalArgumentException("Cookie may not be null");
michael@0 62 }
michael@0 63 if (domain == null) {
michael@0 64 throw new MalformedCookieException(
michael@0 65 "Missing value for domain attribute");
michael@0 66 }
michael@0 67 if (domain.trim().length() == 0) {
michael@0 68 throw new MalformedCookieException(
michael@0 69 "Blank value for domain attribute");
michael@0 70 }
michael@0 71 domain = domain.toLowerCase(Locale.ENGLISH);
michael@0 72 if (!domain.startsWith(".")) {
michael@0 73 // Per RFC 2965 section 3.2.2
michael@0 74 // "... If an explicitly specified value does not start with
michael@0 75 // a dot, the user agent supplies a leading dot ..."
michael@0 76 // That effectively implies that the domain attribute
michael@0 77 // MAY NOT be an IP address of a host name
michael@0 78 domain = '.' + domain;
michael@0 79 }
michael@0 80 cookie.setDomain(domain);
michael@0 81 }
michael@0 82
michael@0 83 /**
michael@0 84 * Performs domain-match as defined by the RFC2965.
michael@0 85 * <p>
michael@0 86 * Host A's name domain-matches host B's if
michael@0 87 * <ol>
michael@0 88 * <ul>their host name strings string-compare equal; or</ul>
michael@0 89 * <ul>A is a HDN string and has the form NB, where N is a non-empty
michael@0 90 * name string, B has the form .B', and B' is a HDN string. (So,
michael@0 91 * x.y.com domain-matches .Y.com but not Y.com.)</ul>
michael@0 92 * </ol>
michael@0 93 *
michael@0 94 * @param host host name where cookie is received from or being sent to.
michael@0 95 * @param domain The cookie domain attribute.
michael@0 96 * @return true if the specified host matches the given domain.
michael@0 97 */
michael@0 98 public boolean domainMatch(String host, String domain) {
michael@0 99 boolean match = host.equals(domain)
michael@0 100 || (domain.startsWith(".") && host.endsWith(domain));
michael@0 101
michael@0 102 return match;
michael@0 103 }
michael@0 104
michael@0 105 /**
michael@0 106 * Validate cookie domain attribute.
michael@0 107 */
michael@0 108 public void validate(final Cookie cookie, final CookieOrigin origin)
michael@0 109 throws MalformedCookieException {
michael@0 110 if (cookie == null) {
michael@0 111 throw new IllegalArgumentException("Cookie may not be null");
michael@0 112 }
michael@0 113 if (origin == null) {
michael@0 114 throw new IllegalArgumentException("Cookie origin may not be null");
michael@0 115 }
michael@0 116 String host = origin.getHost().toLowerCase(Locale.ENGLISH);
michael@0 117 if (cookie.getDomain() == null) {
michael@0 118 throw new CookieRestrictionViolationException("Invalid cookie state: " +
michael@0 119 "domain not specified");
michael@0 120 }
michael@0 121 String cookieDomain = cookie.getDomain().toLowerCase(Locale.ENGLISH);
michael@0 122
michael@0 123 if (cookie instanceof ClientCookie
michael@0 124 && ((ClientCookie) cookie).containsAttribute(ClientCookie.DOMAIN_ATTR)) {
michael@0 125 // Domain attribute must start with a dot
michael@0 126 if (!cookieDomain.startsWith(".")) {
michael@0 127 throw new CookieRestrictionViolationException("Domain attribute \"" +
michael@0 128 cookie.getDomain() + "\" violates RFC 2109: domain must start with a dot");
michael@0 129 }
michael@0 130
michael@0 131 // Domain attribute must contain at least one embedded dot,
michael@0 132 // or the value must be equal to .local.
michael@0 133 int dotIndex = cookieDomain.indexOf('.', 1);
michael@0 134 if (((dotIndex < 0) || (dotIndex == cookieDomain.length() - 1))
michael@0 135 && (!cookieDomain.equals(".local"))) {
michael@0 136 throw new CookieRestrictionViolationException(
michael@0 137 "Domain attribute \"" + cookie.getDomain()
michael@0 138 + "\" violates RFC 2965: the value contains no embedded dots "
michael@0 139 + "and the value is not .local");
michael@0 140 }
michael@0 141
michael@0 142 // The effective host name must domain-match domain attribute.
michael@0 143 if (!domainMatch(host, cookieDomain)) {
michael@0 144 throw new CookieRestrictionViolationException(
michael@0 145 "Domain attribute \"" + cookie.getDomain()
michael@0 146 + "\" violates RFC 2965: effective host name does not "
michael@0 147 + "domain-match domain attribute.");
michael@0 148 }
michael@0 149
michael@0 150 // effective host name minus domain must not contain any dots
michael@0 151 String effectiveHostWithoutDomain = host.substring(
michael@0 152 0, host.length() - cookieDomain.length());
michael@0 153 if (effectiveHostWithoutDomain.indexOf('.') != -1) {
michael@0 154 throw new CookieRestrictionViolationException("Domain attribute \""
michael@0 155 + cookie.getDomain() + "\" violates RFC 2965: "
michael@0 156 + "effective host minus domain may not contain any dots");
michael@0 157 }
michael@0 158 } else {
michael@0 159 // Domain was not specified in header. In this case, domain must
michael@0 160 // string match request host (case-insensitive).
michael@0 161 if (!cookie.getDomain().equals(host)) {
michael@0 162 throw new CookieRestrictionViolationException("Illegal domain attribute: \""
michael@0 163 + cookie.getDomain() + "\"."
michael@0 164 + "Domain of origin: \""
michael@0 165 + host + "\"");
michael@0 166 }
michael@0 167 }
michael@0 168 }
michael@0 169
michael@0 170 /**
michael@0 171 * Match cookie domain attribute.
michael@0 172 */
michael@0 173 public boolean match(final Cookie cookie, final CookieOrigin origin) {
michael@0 174 if (cookie == null) {
michael@0 175 throw new IllegalArgumentException("Cookie may not be null");
michael@0 176 }
michael@0 177 if (origin == null) {
michael@0 178 throw new IllegalArgumentException("Cookie origin may not be null");
michael@0 179 }
michael@0 180 String host = origin.getHost().toLowerCase(Locale.ENGLISH);
michael@0 181 String cookieDomain = cookie.getDomain();
michael@0 182
michael@0 183 // The effective host name MUST domain-match the Domain
michael@0 184 // attribute of the cookie.
michael@0 185 if (!domainMatch(host, cookieDomain)) {
michael@0 186 return false;
michael@0 187 }
michael@0 188 // effective host name minus domain must not contain any dots
michael@0 189 String effectiveHostWithoutDomain = host.substring(
michael@0 190 0, host.length() - cookieDomain.length());
michael@0 191 return effectiveHostWithoutDomain.indexOf('.') == -1;
michael@0 192 }
michael@0 193
michael@0 194 }

mercurial