1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.http;
20
21 import java.util.ArrayList;
22 import java.util.Objects;
23
24 import org.eclipse.jetty.util.StringUtil;
25
26
27
28 public class HttpField
29 {
30 private final static String __zeroquality="q=0";
31 private final HttpHeader _header;
32 private final String _name;
33 private final String _value;
34
35 private int hash = 0;
36
37 public HttpField(HttpHeader header, String name, String value)
38 {
39 _header = header;
40 _name = name;
41 _value = value;
42 }
43
44 public HttpField(HttpHeader header, String value)
45 {
46 this(header,header.asString(),value);
47 }
48
49 public HttpField(HttpHeader header, HttpHeaderValue value)
50 {
51 this(header,header.asString(),value.asString());
52 }
53
54 public HttpField(String name, String value)
55 {
56 this(HttpHeader.CACHE.get(name),name,value);
57 }
58
59 public HttpHeader getHeader()
60 {
61 return _header;
62 }
63
64 public String getName()
65 {
66 return _name;
67 }
68
69 public String getValue()
70 {
71 return _value;
72 }
73
74 public int getIntValue()
75 {
76 return Integer.valueOf(_value);
77 }
78
79 public long getLongValue()
80 {
81 return Long.valueOf(_value);
82 }
83
84 public String[] getValues()
85 {
86 ArrayList<String> list = new ArrayList<>();
87 int state = 0;
88 int start=0;
89 int end=0;
90 StringBuilder builder = new StringBuilder();
91
92 for (int i=0;i<_value.length();i++)
93 {
94 char c = _value.charAt(i);
95 switch(state)
96 {
97 case 0:
98 switch(c)
99 {
100 case '"':
101 state=2;
102 break;
103
104 case ',':
105 break;
106
107 case ' ':
108 case '\t':
109 break;
110
111 default:
112 start=i;
113 end=i;
114 state=1;
115 }
116 break;
117
118 case 1:
119 switch(c)
120 {
121 case ',':
122 list.add(_value.substring(start,end+1));
123 state=0;
124 break;
125
126 case ' ':
127 case '\t':
128 break;
129
130 default:
131 end=i;
132 }
133 break;
134
135 case 2:
136 switch(c)
137 {
138 case '\\':
139 state=3;
140 break;
141
142 case '"':
143 list.add(builder.toString());
144 builder.setLength(0);
145 state=4;
146 break;
147
148 default:
149 builder.append(c);
150 }
151 break;
152
153 case 3:
154 builder.append(c);
155 state=2;
156 break;
157
158 case 4:
159 switch(c)
160 {
161 case ' ':
162 case '\t':
163 break;
164
165 case ',':
166 state=0;
167 break;
168
169 default:
170 throw new IllegalArgumentException("c="+(int)c);
171
172 }
173 break;
174 }
175 }
176
177 switch(state)
178 {
179 case 0:
180 break;
181 case 1:
182 list.add(_value.substring(start,end+1));
183 break;
184 case 4:
185 break;
186
187 default:
188 throw new IllegalArgumentException("state="+state);
189 }
190
191 return list.toArray(new String[list.size()]);
192 }
193
194
195
196
197
198
199
200
201 public boolean contains(String search)
202 {
203 if (search==null)
204 return _value==null;
205 if (search.length()==0)
206 return false;
207 if (_value==null)
208 return false;
209
210 search = StringUtil.asciiToLowerCase(search);
211
212 int state=0;
213 int match=0;
214 int param=0;
215
216 for (int i=0;i<_value.length();i++)
217 {
218 char c = _value.charAt(i);
219 switch(state)
220 {
221 case 0:
222 switch(c)
223 {
224 case '"':
225 match=0;
226 state=2;
227 break;
228
229 case ',':
230 break;
231
232 case ';':
233 param=-1;
234 match=-1;
235 state=5;
236 break;
237
238 case ' ':
239 case '\t':
240 break;
241
242 default:
243 match = Character.toLowerCase(c)==search.charAt(0)?1:-1;
244 state=1;
245 break;
246 }
247 break;
248
249 case 1:
250 switch(c)
251 {
252 case ',':
253
254 if (match==search.length())
255 return true;
256 state=0;
257 break;
258
259 case ';':
260 param=match>=0?0:-1;
261 state=5;
262 break;
263
264 default:
265 if (match>0)
266 {
267 if (match<search.length())
268 match=Character.toLowerCase(c)==search.charAt(match)?(match+1):-1;
269 else if (c!=' ' && c!= '\t')
270 match=-1;
271 }
272 break;
273
274 }
275 break;
276
277 case 2:
278 switch(c)
279 {
280 case '\\':
281 state=3;
282 break;
283
284 case '"':
285 state=4;
286 break;
287
288 default:
289 if (match>=0)
290 {
291 if (match<search.length())
292 match=Character.toLowerCase(c)==search.charAt(match)?(match+1):-1;
293 else
294 match=-1;
295 }
296 }
297 break;
298
299 case 3:
300 if (match>=0)
301 {
302 if (match<search.length())
303 match=Character.toLowerCase(c)==search.charAt(match)?(match+1):-1;
304 else
305 match=-1;
306 }
307 state=2;
308 break;
309
310 case 4:
311 switch(c)
312 {
313 case ' ':
314 case '\t':
315 break;
316
317 case ';':
318 state=5;
319 break;
320
321 case ',':
322
323 if (match==search.length())
324 return true;
325 state=0;
326 break;
327
328 default:
329
330 match=-1;
331 }
332 break;
333
334 case 5:
335 switch(c)
336 {
337 case ',':
338
339 if (param!=__zeroquality.length() && match==search.length())
340 return true;
341 param=0;
342 state=0;
343 break;
344
345 case ' ':
346 case '\t':
347 break;
348
349 default:
350 if (param>=0)
351 {
352 if (param<__zeroquality.length())
353 param=Character.toLowerCase(c)==__zeroquality.charAt(param)?(param+1):-1;
354 else if (c!='0'&&c!='.')
355 param=-1;
356 }
357
358 }
359 break;
360
361 default:
362 throw new IllegalStateException();
363 }
364 }
365
366 return param!=__zeroquality.length() && match==search.length();
367 }
368
369
370 @Override
371 public String toString()
372 {
373 String v=getValue();
374 return getName() + ": " + (v==null?"":v);
375 }
376
377 public boolean isSameName(HttpField field)
378 {
379 if (field==null)
380 return false;
381 if (field==this)
382 return true;
383 if (_header!=null && _header==field.getHeader())
384 return true;
385 if (_name.equalsIgnoreCase(field.getName()))
386 return true;
387 return false;
388 }
389
390 private int nameHashCode()
391 {
392 int h = this.hash;
393 int len = _name.length();
394 if (h == 0 && len > 0)
395 {
396 for (int i = 0; i < len; i++)
397 {
398
399 char c = _name.charAt(i);
400
401 if ((c >= 'a' && c <= 'z'))
402 c -= 0x20;
403 h = 31 * h + c;
404 }
405 this.hash = h;
406 }
407 return h;
408 }
409
410 @Override
411 public int hashCode()
412 {
413 if (_header==null)
414 return _value.hashCode() ^ nameHashCode();
415 return _value.hashCode() ^ _header.hashCode();
416 }
417
418 @Override
419 public boolean equals(Object o)
420 {
421 if (o==this)
422 return true;
423 if (!(o instanceof HttpField))
424 return false;
425 HttpField field=(HttpField)o;
426 if (_header!=field.getHeader())
427 return false;
428 if (!_name.equalsIgnoreCase(field.getName()))
429 return false;
430 if (_value==null && field.getValue()!=null)
431 return false;
432 return Objects.equals(_value,field.getValue());
433 }
434
435 public static class IntValueHttpField extends HttpField
436 {
437 private final int _int;
438
439 public IntValueHttpField(HttpHeader header, String name, String value, int intValue)
440 {
441 super(header,name,value);
442 _int=intValue;
443 }
444
445 public IntValueHttpField(HttpHeader header, String name, String value)
446 {
447 this(header,name,value,Integer.valueOf(value));
448 }
449
450 public IntValueHttpField(HttpHeader header, String name, int intValue)
451 {
452 this(header,name,Integer.toString(intValue),intValue);
453 }
454
455 public IntValueHttpField(HttpHeader header, int value)
456 {
457 this(header,header.asString(),value);
458 }
459
460 @Override
461 public int getIntValue()
462 {
463 return _int;
464 }
465
466 @Override
467 public long getLongValue()
468 {
469 return _int;
470 }
471 }
472
473 public static class LongValueHttpField extends HttpField
474 {
475 private final long _long;
476
477 public LongValueHttpField(HttpHeader header, String name, String value, long longValue)
478 {
479 super(header,name,value);
480 _long=longValue;
481 }
482
483 public LongValueHttpField(HttpHeader header, String name, String value)
484 {
485 this(header,name,value,Long.valueOf(value));
486 }
487
488 public LongValueHttpField(HttpHeader header, String name, long value)
489 {
490 this(header,name,Long.toString(value),value);
491 }
492
493 public LongValueHttpField(HttpHeader header,long value)
494 {
495 this(header,header.asString(),value);
496 }
497
498 @Override
499 public int getIntValue()
500 {
501 return (int)_long;
502 }
503
504 @Override
505 public long getLongValue()
506 {
507 return _long;
508 }
509 }
510 }