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