]> WPIA git - gigi.git/blob - lib/jetty/org/eclipse/jetty/server/CookieCutter.java
updating jetty to jetty-9.2.16.v2016040
[gigi.git] / lib / jetty / org / eclipse / jetty / server / CookieCutter.java
1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2016 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.
8 //
9 //      The Eclipse Public License is available at
10 //      http://www.eclipse.org/legal/epl-v10.html
11 //
12 //      The Apache License v2.0 is available at
13 //      http://www.opensource.org/licenses/apache2.0.php
14 //
15 //  You may elect to redistribute this code under either of these licenses.
16 //  ========================================================================
17 //
18
19 package org.eclipse.jetty.server;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.Locale;
23
24 import javax.servlet.http.Cookie;
25
26 import org.eclipse.jetty.util.QuotedStringTokenizer;
27 import org.eclipse.jetty.util.log.Log;
28 import org.eclipse.jetty.util.log.Logger;
29
30
31 /* ------------------------------------------------------------ */
32 /** Cookie parser
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.
38  * 
39  *
40  */
41 public class CookieCutter
42 {
43     private static final Logger LOG = Log.getLogger(CookieCutter.class);
44
45     private Cookie[] _cookies;
46     private Cookie[] _lastCookies;
47     private final List<String> _fieldList = new ArrayList<>();
48     int _fields;
49     
50     public CookieCutter()
51     {  
52     }
53     
54     public Cookie[] getCookies()
55     {
56         if (_cookies!=null)
57             return _cookies;
58         
59         if (_lastCookies!=null && _fields==_fieldList.size())
60             _cookies=_lastCookies;
61         else
62             parseFields();
63         _lastCookies=_cookies;
64         return _cookies;
65     }
66     
67     public void setCookies(Cookie[] cookies)
68     {
69         _cookies=cookies;
70         _lastCookies=null;
71         _fieldList.clear();
72         _fields=0;
73     }
74     
75     public void reset()
76     {
77         _cookies=null;
78         _fields=0;
79     }
80     
81     public void addCookieField(String f)
82     {
83         if (f==null)
84             return;
85         f=f.trim();
86         if (f.length()==0)
87             return;
88             
89         if (_fieldList.size()>_fields)
90         {
91             if (f.equals(_fieldList.get(_fields)))
92             {
93                 _fields++;
94                 return;
95             }
96             
97             while (_fieldList.size()>_fields)
98                 _fieldList.remove(_fields);
99         }
100         _cookies=null;
101         _lastCookies=null;
102         _fieldList.add(_fields++,f);
103     }
104     
105     
106     protected void parseFields()
107     {
108         _lastCookies=null;
109         _cookies=null;
110         
111         List<Cookie> cookies = new ArrayList<>();
112
113         int version = 0;
114
115         // delete excess fields
116         while (_fieldList.size()>_fields)
117             _fieldList.remove(_fields);
118         
119         // For each cookie field
120         for (String hdr : _fieldList)
121         {
122             // Parse the header
123             String name = null;
124             String value = null;
125
126             Cookie cookie = null;
127
128             boolean invalue=false;
129             boolean quoted=false;
130             boolean escaped=false;
131             int tokenstart=-1;
132             int tokenend=-1;
133             for (int i = 0, length = hdr.length(), last=length-1; i < length; i++)
134             {
135                 char c = hdr.charAt(i);
136                 
137                 // Handle quoted values for name or value
138                 if (quoted)
139                 {
140                     if (escaped)
141                     {
142                         escaped=false;
143                         continue;
144                     }
145                     
146                     switch (c)
147                     {
148                         case '"':
149                             tokenend=i;
150                             quoted=false;
151
152                             // handle quote as last character specially
153                             if (i==last)
154                             {
155                                 if (invalue)
156                                     value = hdr.substring(tokenstart, tokenend+1);
157                                 else
158                                 {
159                                     name = hdr.substring(tokenstart, tokenend+1);
160                                     value = "";
161                                 }
162                             }
163                             break;
164                             
165                         case '\\':
166                             escaped=true;
167                             continue;
168                         default:
169                             continue;
170                     }
171                 }
172                 else
173                 {
174                     // Handle name and value state machines
175                     if (invalue)
176                     {
177                         // parse the value
178                         switch (c)
179                         {
180                             case ' ':
181                             case '\t':
182                                 continue;
183                                 
184                             case '"':
185                                 if (tokenstart<0)
186                                 {
187                                     quoted=true;
188                                     tokenstart=i;
189                                 }
190                                 tokenend=i;
191                                 if (i==last)
192                                 {
193                                     value = hdr.substring(tokenstart, tokenend+1);
194                                     break;
195                                 }
196                                 continue;
197
198                             case ';':
199                                 if (tokenstart>=0)
200                                     value = hdr.substring(tokenstart, tokenend+1);
201                                 else
202                                     value="";
203                                 tokenstart = -1;
204                                 invalue=false;
205                                 break;
206                                 
207                             default:
208                                 if (tokenstart<0)
209                                     tokenstart=i;
210                                 tokenend=i;
211                                 if (i==last)
212                                 {
213                                     value = hdr.substring(tokenstart, tokenend+1);
214                                     break;
215                                 }
216                                 continue;
217                         }
218                     }
219                     else
220                     {
221                         // parse the name
222                         switch (c)
223                         {
224                             case ' ':
225                             case '\t':
226                                 continue;
227                                 
228                             case '"':
229                                 if (tokenstart<0)
230                                 {
231                                     quoted=true;
232                                     tokenstart=i;
233                                 }
234                                 tokenend=i;
235                                 if (i==last)
236                                 {
237                                     name = hdr.substring(tokenstart, tokenend+1);
238                                     value = "";
239                                     break;
240                                 }
241                                 continue;
242
243                             case ';':
244                                 if (tokenstart>=0)
245                                 {
246                                     name = hdr.substring(tokenstart, tokenend+1);
247                                     value = "";
248                                 }
249                                 tokenstart = -1;
250                                 break;
251
252                             case '=':
253                                 if (tokenstart>=0)
254                                     name = hdr.substring(tokenstart, tokenend+1);
255                                 tokenstart = -1;
256                                 invalue=true;
257                                 continue;
258                                 
259                             default:
260                                 if (tokenstart<0)
261                                     tokenstart=i;
262                                 tokenend=i;
263                                 if (i==last)
264                                 {
265                                     name = hdr.substring(tokenstart, tokenend+1);
266                                     value = "";
267                                     break;
268                                 }
269                                 continue;
270                         }
271                     }
272                 }
273
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)
276                 {
277                     name=QuotedStringTokenizer.unquoteOnly(name);
278                     value=QuotedStringTokenizer.unquoteOnly(value);
279                     
280                     try
281                     {
282                         if (name.startsWith("$"))
283                         {
284                             String lowercaseName = name.toLowerCase(Locale.ENGLISH);
285                             if ("$path".equals(lowercaseName))
286                             {
287                                 if (cookie!=null)
288                                     cookie.setPath(value);
289                             }
290                             else if ("$domain".equals(lowercaseName))
291                             {
292                                 if (cookie!=null)
293                                     cookie.setDomain(value);
294                             }
295                             else if ("$port".equals(lowercaseName))
296                             {
297                                 if (cookie!=null)
298                                     cookie.setComment("$port="+value);
299                             }
300                             else if ("$version".equals(lowercaseName))
301                             {
302                                 version = Integer.parseInt(value);
303                             }
304                         }
305                         else
306                         {
307                             cookie = new Cookie(name, value);
308                             if (version > 0)
309                                 cookie.setVersion(version);
310                             cookies.add(cookie);
311                         }
312                     }
313                     catch (Exception e)
314                     {
315                         LOG.debug(e);
316                     }
317
318                     name = null;
319                     value = null;
320                 }
321             }
322         }
323
324         _cookies = (Cookie[]) cookies.toArray(new Cookie[cookies.size()]);
325         _lastCookies=_cookies;
326     }
327     
328 }