1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.impl.cookie;
29
30 import java.util.Locale;
31
32 import org.apache.http.annotation.Contract;
33 import org.apache.http.annotation.ThreadingBehavior;
34 import org.apache.http.cookie.ClientCookie;
35 import org.apache.http.cookie.CommonCookieAttributeHandler;
36 import org.apache.http.cookie.Cookie;
37 import org.apache.http.cookie.CookieOrigin;
38 import org.apache.http.cookie.CookieRestrictionViolationException;
39 import org.apache.http.cookie.MalformedCookieException;
40 import org.apache.http.cookie.SetCookie;
41 import org.apache.http.util.Args;
42
43
44
45
46
47
48
49 @Contract(threading = ThreadingBehavior.IMMUTABLE)
50 public class RFC2965DomainAttributeHandler implements CommonCookieAttributeHandler {
51
52 public RFC2965DomainAttributeHandler() {
53 super();
54 }
55
56
57
58
59 @Override
60 public void parse(
61 final SetCookie cookie, final String domain) throws MalformedCookieException {
62 Args.notNull(cookie, "Cookie");
63 if (domain == null) {
64 throw new MalformedCookieException(
65 "Missing value for domain attribute");
66 }
67 if (domain.trim().isEmpty()) {
68 throw new MalformedCookieException(
69 "Blank value for domain attribute");
70 }
71 String s = domain;
72 s = s.toLowerCase(Locale.ROOT);
73 if (!domain.startsWith(".")) {
74
75
76
77
78
79 s = '.' + s;
80 }
81 cookie.setDomain(s);
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100 public boolean domainMatch(final String host, final String domain) {
101 final boolean match = host.equals(domain)
102 || (domain.startsWith(".") && host.endsWith(domain));
103
104 return match;
105 }
106
107
108
109
110 @Override
111 public void validate(final Cookie cookie, final CookieOrigin origin)
112 throws MalformedCookieException {
113 Args.notNull(cookie, "Cookie");
114 Args.notNull(origin, "Cookie origin");
115 final String host = origin.getHost().toLowerCase(Locale.ROOT);
116 if (cookie.getDomain() == null) {
117 throw new CookieRestrictionViolationException("Invalid cookie state: " +
118 "domain not specified");
119 }
120 final String cookieDomain = cookie.getDomain().toLowerCase(Locale.ROOT);
121
122 if (cookie instanceof ClientCookie
123 && ((ClientCookie) cookie).containsAttribute(ClientCookie.DOMAIN_ATTR)) {
124
125 if (!cookieDomain.startsWith(".")) {
126 throw new CookieRestrictionViolationException("Domain attribute \"" +
127 cookie.getDomain() + "\" violates RFC 2109: domain must start with a dot");
128 }
129
130
131
132 final int dotIndex = cookieDomain.indexOf('.', 1);
133 if (((dotIndex < 0) || (dotIndex == cookieDomain.length() - 1))
134 && (!cookieDomain.equals(".local"))) {
135 throw new CookieRestrictionViolationException(
136 "Domain attribute \"" + cookie.getDomain()
137 + "\" violates RFC 2965: the value contains no embedded dots "
138 + "and the value is not .local");
139 }
140
141
142 if (!domainMatch(host, cookieDomain)) {
143 throw new CookieRestrictionViolationException(
144 "Domain attribute \"" + cookie.getDomain()
145 + "\" violates RFC 2965: effective host name does not "
146 + "domain-match domain attribute.");
147 }
148
149
150 final String effectiveHostWithoutDomain = host.substring(
151 0, host.length() - cookieDomain.length());
152 if (effectiveHostWithoutDomain.indexOf('.') != -1) {
153 throw new CookieRestrictionViolationException("Domain attribute \""
154 + cookie.getDomain() + "\" violates RFC 2965: "
155 + "effective host minus domain may not contain any dots");
156 }
157 } else {
158
159
160 if (!cookie.getDomain().equals(host)) {
161 throw new CookieRestrictionViolationException("Illegal domain attribute: \""
162 + cookie.getDomain() + "\"."
163 + "Domain of origin: \""
164 + host + "\"");
165 }
166 }
167 }
168
169
170
171
172 @Override
173 public boolean match(final Cookie cookie, final CookieOrigin origin) {
174 Args.notNull(cookie, "Cookie");
175 Args.notNull(origin, "Cookie origin");
176 final String host = origin.getHost().toLowerCase(Locale.ROOT);
177 final String cookieDomain = cookie.getDomain();
178
179
180
181 if (!domainMatch(host, cookieDomain)) {
182 return false;
183 }
184
185 final String effectiveHostWithoutDomain = host.substring(
186 0, host.length() - cookieDomain.length());
187 return effectiveHostWithoutDomain.indexOf('.') == -1;
188 }
189
190 @Override
191 public String getAttributeName() {
192 return ClientCookie.DOMAIN_ATTR;
193 }
194
195 }