2 // ========================================================================
3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
19 package org.eclipse.jetty.server;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.Locale;
24 import javax.servlet.http.Cookie;
26 import org.eclipse.jetty.util.QuotedStringTokenizer;
27 import org.eclipse.jetty.util.log.Log;
28 import org.eclipse.jetty.util.log.Logger;
31 /* ------------------------------------------------------------ */
33 * <p>Optimized stateful cookie parser. Cookies fields are added with the
34 * {@link #addCookieField(String)} method and parsed on the next subsequent
35 * call to {@link #getCookies()}.
36 * If the added fields are identical to those last added (as strings), then the
37 * cookies are not re parsed.
41 public class CookieCutter
43 private static final Logger LOG = Log.getLogger(CookieCutter.class);
45 private Cookie[] _cookies;
46 private Cookie[] _lastCookies;
47 private final List<String> _fieldList = new ArrayList<>();
54 public Cookie[] getCookies()
59 if (_lastCookies!=null && _fields==_fieldList.size())
60 _cookies=_lastCookies;
63 _lastCookies=_cookies;
67 public void setCookies(Cookie[] cookies)
81 public void addCookieField(String f)
89 if (_fieldList.size()>_fields)
91 if (f.equals(_fieldList.get(_fields)))
97 while (_fieldList.size()>_fields)
98 _fieldList.remove(_fields);
102 _fieldList.add(_fields++,f);
106 protected void parseFields()
111 List<Cookie> cookies = new ArrayList<>();
115 // delete excess fields
116 while (_fieldList.size()>_fields)
117 _fieldList.remove(_fields);
119 // For each cookie field
120 for (String hdr : _fieldList)
126 Cookie cookie = null;
128 boolean invalue=false;
129 boolean quoted=false;
130 boolean escaped=false;
133 for (int i = 0, length = hdr.length(), last=length-1; i < length; i++)
135 char c = hdr.charAt(i);
137 // Handle quoted values for name or value
152 // handle quote as last character specially
156 value = hdr.substring(tokenstart, tokenend+1);
159 name = hdr.substring(tokenstart, tokenend+1);
174 // Handle name and value state machines
193 value = hdr.substring(tokenstart, tokenend+1);
200 value = hdr.substring(tokenstart, tokenend+1);
213 value = hdr.substring(tokenstart, tokenend+1);
237 name = hdr.substring(tokenstart, tokenend+1);
246 name = hdr.substring(tokenstart, tokenend+1);
254 name = hdr.substring(tokenstart, tokenend+1);
265 name = hdr.substring(tokenstart, tokenend+1);
274 // If after processing the current character we have a value and a name, then it is a cookie
275 if (value!=null && name!=null)
277 name=QuotedStringTokenizer.unquoteOnly(name);
278 value=QuotedStringTokenizer.unquoteOnly(value);
282 if (name.startsWith("$"))
284 String lowercaseName = name.toLowerCase(Locale.ENGLISH);
285 if ("$path".equals(lowercaseName))
288 cookie.setPath(value);
290 else if ("$domain".equals(lowercaseName))
293 cookie.setDomain(value);
295 else if ("$port".equals(lowercaseName))
298 cookie.setComment("$port="+value);
300 else if ("$version".equals(lowercaseName))
302 version = Integer.parseInt(value);
307 cookie = new Cookie(name, value);
309 cookie.setVersion(version);
324 _cookies = (Cookie[]) cookies.toArray(new Cookie[cookies.size()]);
325 _lastCookies=_cookies;