001/* 002 * ==================================================================== 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 * ==================================================================== 020 * 021 * This software consists of voluntary contributions made by many 022 * individuals on behalf of the Apache Software Foundation. For more 023 * information on the Apache Software Foundation, please see 024 * <http://www.apache.org/>. 025 * 026 */ 027package org.apache.http.impl.cookie; 028 029import java.util.Locale; 030import java.util.StringTokenizer; 031 032import org.apache.http.annotation.Contract; 033import org.apache.http.annotation.ThreadingBehavior; 034import org.apache.http.cookie.ClientCookie; 035import org.apache.http.cookie.Cookie; 036import org.apache.http.cookie.CookieOrigin; 037import org.apache.http.cookie.CookieRestrictionViolationException; 038import org.apache.http.cookie.MalformedCookieException; 039import org.apache.http.cookie.SetCookie; 040import org.apache.http.util.Args; 041import org.apache.http.util.TextUtils; 042 043/** 044 * 045 * @since 4.0 046 */ 047@Contract(threading = ThreadingBehavior.IMMUTABLE) 048public class NetscapeDomainHandler extends BasicDomainHandler { 049 050 public NetscapeDomainHandler() { 051 super(); 052 } 053 054 @Override 055 public void parse(final SetCookie cookie, final String value) throws MalformedCookieException { 056 Args.notNull(cookie, "Cookie"); 057 if (TextUtils.isBlank(value)) { 058 throw new MalformedCookieException("Blank or null value for domain attribute"); 059 } 060 cookie.setDomain(value); 061 } 062 063 @Override 064 public void validate(final Cookie cookie, final CookieOrigin origin) 065 throws MalformedCookieException { 066 final String host = origin.getHost(); 067 final String domain = cookie.getDomain(); 068 if (!host.equals(domain) && !BasicDomainHandler.domainMatch(domain, host)) { 069 throw new CookieRestrictionViolationException( 070 "Illegal domain attribute \"" + domain + "\". Domain of origin: \"" + host + "\""); 071 } 072 if (host.contains(".")) { 073 final int domainParts = new StringTokenizer(domain, ".").countTokens(); 074 075 if (isSpecialDomain(domain)) { 076 if (domainParts < 2) { 077 throw new CookieRestrictionViolationException("Domain attribute \"" 078 + domain 079 + "\" violates the Netscape cookie specification for " 080 + "special domains"); 081 } 082 } else { 083 if (domainParts < 3) { 084 throw new CookieRestrictionViolationException("Domain attribute \"" 085 + domain 086 + "\" violates the Netscape cookie specification"); 087 } 088 } 089 } 090 } 091 092 /** 093 * Checks if the given domain is in one of the seven special 094 * top level domains defined by the Netscape cookie specification. 095 * @param domain The domain. 096 * @return True if the specified domain is "special" 097 */ 098 private static boolean isSpecialDomain(final String domain) { 099 final String ucDomain = domain.toUpperCase(Locale.ROOT); 100 return ucDomain.endsWith(".COM") 101 || ucDomain.endsWith(".EDU") 102 || ucDomain.endsWith(".NET") 103 || ucDomain.endsWith(".GOV") 104 || ucDomain.endsWith(".MIL") 105 || ucDomain.endsWith(".ORG") 106 || ucDomain.endsWith(".INT"); 107 } 108 109 @Override 110 public boolean match(final Cookie cookie, final CookieOrigin origin) { 111 Args.notNull(cookie, "Cookie"); 112 Args.notNull(origin, "Cookie origin"); 113 final String host = origin.getHost(); 114 final String domain = cookie.getDomain(); 115 if (domain == null) { 116 return false; 117 } 118 return host.endsWith(domain); 119 } 120 121 @Override 122 public String getAttributeName() { 123 return ClientCookie.DOMAIN_ATTR; 124 } 125 126}