1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.esigate.cookie;
17
18 import java.util.Collection;
19 import java.util.Date;
20 import java.util.List;
21 import java.util.Properties;
22
23 import org.apache.http.cookie.Cookie;
24 import org.apache.http.impl.client.BasicCookieStore;
25 import org.apache.http.impl.cookie.BasicClientCookie;
26 import org.apache.http.impl.cookie.BasicClientCookie2;
27 import org.esigate.ConfigurationException;
28 import org.esigate.Driver;
29 import org.esigate.Parameters;
30 import org.esigate.UserContext;
31 import org.esigate.http.cookie.CookieUtil;
32 import org.esigate.impl.DriverRequest;
33 import org.esigate.util.UriUtils;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class DefaultCookieManager implements CookieManager {
51 private static final Logger LOG = LoggerFactory.getLogger(CookieManager.class);
52 private static final String COOKIES_LIST_SESSION_KEY = CookieManager.class.getName() + "#cookies";
53 private Collection<String> discardCookies;
54 private Collection<String> storeCookiesInSession;
55
56 protected Collection<String> getStoredCookies() {
57 return storeCookiesInSession;
58 }
59
60
61
62
63 @Override
64 public void init(Driver d, Properties properties) {
65
66 this.storeCookiesInSession = Parameters.STORE_COOKIES_IN_SESSION.getValue(properties);
67
68 this.discardCookies = Parameters.DISCARD_COOKIES.getValue(properties);
69
70
71 if (this.storeCookiesInSession.contains("*") && this.storeCookiesInSession.size() > 1) {
72 throw new ConfigurationException("storeCookiesInSession must be a list of cookie names OR *");
73 }
74 if (this.discardCookies.contains("*") && this.discardCookies.size() > 1) {
75 throw new ConfigurationException("discardCookies must be a list of cookie names OR *");
76 }
77 if (this.storeCookiesInSession.contains("*") && this.discardCookies.contains("*")) {
78 throw new ConfigurationException(
79 "cannot use * for storeCookiesInSession AND discardCookies at the same time");
80 }
81 }
82
83 @Override
84 public void addCookie(Cookie cookie, DriverRequest originalRequest) {
85 String name = cookie.getName();
86 if (discardCookies.contains(name) || (discardCookies.contains("*") && !storeCookiesInSession.contains(name))) {
87 if (LOG.isInfoEnabled()) {
88 LOG.info("Cookie " + toString(cookie) + " -> discarding");
89 }
90
91 } else if (storeCookiesInSession.contains(name) || storeCookiesInSession.contains("*")) {
92 if (LOG.isInfoEnabled()) {
93 LOG.info("Cookie " + toString(cookie) + " -> storing to session");
94 }
95
96 UserContext userContext = originalRequest.getUserContext();
97 BasicCookieStore cookies = (BasicCookieStore) userContext.getAttribute(COOKIES_LIST_SESSION_KEY);
98 if (cookies == null) {
99 cookies = new BasicCookieStore();
100 }
101 cookies.addCookie(cookie);
102 userContext.setAttribute(COOKIES_LIST_SESSION_KEY, cookies);
103 } else {
104 if (LOG.isInfoEnabled()) {
105 LOG.info("Cookie " + toString(cookie) + " -> forwarding");
106 }
107
108 originalRequest.getOriginalRequest().addNewCookie(rewriteForBrowser(cookie, originalRequest));
109 }
110 }
111
112 @Override
113 public List<Cookie> getCookies(DriverRequest originalRequest) {
114 BasicCookieStore cookies = new BasicCookieStore();
115 UserContext userContext = originalRequest.getUserContext();
116
117
118 BasicCookieStore sessionCookies = (BasicCookieStore) userContext.getAttribute(COOKIES_LIST_SESSION_KEY);
119 if (sessionCookies != null) {
120 for (Cookie c : sessionCookies.getCookies()) {
121 cookies.addCookie(c);
122 }
123 }
124
125
126 Cookie[] requestCookies = originalRequest.getOriginalRequest().getCookies();
127 if (requestCookies != null) {
128 for (Cookie cookie : requestCookies) {
129 String name = cookie.getName();
130 if (!storeCookiesInSession.contains(name) && !storeCookiesInSession.contains("*")
131 && !discardCookies.contains(name) && !discardCookies.contains("*")) {
132 cookies.addCookie(rewriteForServer(cookie, originalRequest));
133 }
134 }
135 }
136 return cookies.getCookies();
137 }
138
139 private static Cookie rewriteForServer(Cookie cookie, DriverRequest request) {
140 String name = cookie.getName();
141 if ("_JSESSIONID".equalsIgnoreCase(name)) {
142 name = name.substring(1);
143 }
144 BasicClientCookie2 httpClientCookie = new BasicClientCookie2(name, cookie.getValue());
145 httpClientCookie.setSecure(false);
146 String domain;
147 if (request.getDriver().getConfiguration().isPreserveHost()) {
148 domain = UriUtils.extractHostName(request.getOriginalRequest().getRequestLine().getUri());
149 } else {
150 domain = request.getBaseUrl().getHost();
151 }
152
153 httpClientCookie.setDomain(domain);
154 httpClientCookie.setPath("/");
155 httpClientCookie.setComment(cookie.getComment());
156 httpClientCookie.setVersion(cookie.getVersion());
157 return httpClientCookie;
158 }
159
160 protected static String rewriteDomain(String originalDomain, String providerHostName, String requestHostName) {
161 String domain = null;
162 if (!providerHostName.equals(originalDomain)) {
163
164 if (originalDomain.startsWith(".")) {
165 originalDomain = originalDomain.substring(1);
166 }
167 String[] originalDomainParts = originalDomain.split("\\.");
168 String[] requestHostNameParts = requestHostName.split("\\.");
169 int targetLength = Math.min(originalDomainParts.length, requestHostNameParts.length);
170 if (targetLength == requestHostNameParts.length) {
171
172
173 return null;
174 }
175 domain = "";
176 for (int i = requestHostNameParts.length; i > requestHostNameParts.length - targetLength; i--) {
177 domain = "." + requestHostNameParts[i - 1] + domain;
178 }
179 }
180 return domain;
181 }
182
183 protected static Cookie rewriteForBrowser(Cookie cookie, DriverRequest request) {
184 String name = cookie.getName();
185
186
187 if ("JSESSIONID".equalsIgnoreCase(name)) {
188 name = "_" + name;
189 }
190
191
192 String domain =
193 rewriteDomain(cookie.getDomain(), request.getBaseUrl().getHost(),
194 UriUtils.extractHostName(request.getOriginalRequest().getRequestLine().getUri()));
195
196
197 String originalPath = cookie.getPath();
198 String requestPath = UriUtils.getPath(request.getOriginalRequest().getRequestLine().getUri());
199 String path = originalPath;
200 if (requestPath == null || !requestPath.startsWith(originalPath)) {
201 path = "/";
202 }
203
204
205 boolean secure =
206 (cookie.isSecure() && request.getOriginalRequest().getRequestLine().getUri().startsWith("https"));
207
208 BasicClientCookie cookieToForward = new BasicClientCookie(name, cookie.getValue());
209 if (domain != null) {
210 cookieToForward.setDomain(domain);
211 }
212 cookieToForward.setPath(path);
213 cookieToForward.setSecure(secure);
214 cookieToForward.setComment(cookie.getComment());
215 cookieToForward.setVersion(cookie.getVersion());
216 cookieToForward.setExpiryDate(cookie.getExpiryDate());
217
218 if (((BasicClientCookie) cookie).containsAttribute(CookieUtil.HTTP_ONLY_ATTR)) {
219 cookieToForward.setAttribute(CookieUtil.HTTP_ONLY_ATTR, "");
220 }
221
222 if (LOG.isDebugEnabled()) {
223
224 LOG.debug("Forwarding cookie {} -> {}", cookie.toString(), cookieToForward.toString());
225 }
226 return cookieToForward;
227 }
228
229 private String toString(Cookie cookie) {
230 StringBuilder result = new StringBuilder(Parameters.SMALL_BUFFER_SIZE);
231 result.append(cookie.getName());
232 result.append("=");
233 result.append(cookie.getValue());
234 if (cookie.getDomain() != null) {
235 result.append(";domain=");
236 result.append(cookie.getDomain());
237 }
238 if (cookie.getPath() != null) {
239 result.append(";path=");
240 result.append(cookie.getPath());
241 }
242 if (cookie.getExpiryDate() != null) {
243 result.append(";expires=");
244 result.append(cookie.getExpiryDate());
245 }
246 if (cookie.getCommentURL() != null) {
247 result.append(";comment=");
248 result.append(cookie.getComment());
249 }
250 if (cookie.getCommentURL() != null) {
251 result.append(";comment=");
252 result.append(cookie.getCommentURL());
253 }
254 return result.toString();
255 }
256
257 @Override
258 public boolean clearExpired(Date date, DriverRequest request) {
259 UserContext userContext = request.getUserContext();
260 BasicCookieStore cookies = (BasicCookieStore) userContext.getAttribute(COOKIES_LIST_SESSION_KEY);
261
262 return cookies != null && cookies.clearExpired(date);
263
264 }
265
266 @Override
267 public void clear(DriverRequest request) {
268 UserContext userContext = request.getUserContext();
269 BasicCookieStore cookies = (BasicCookieStore) userContext.getAttribute(COOKIES_LIST_SESSION_KEY);
270 if (cookies != null) {
271 cookies.clear();
272 userContext.setAttribute(COOKIES_LIST_SESSION_KEY, cookies);
273 }
274 }
275
276 }