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 static org.eclipse.jetty.util.QuotedStringTokenizer.isQuoted;
22 import static org.eclipse.jetty.util.QuotedStringTokenizer.quoteOnly;
23
24 import java.io.IOException;
25 import java.nio.ByteBuffer;
26 import java.text.SimpleDateFormat;
27 import java.util.ArrayList;
28 import java.util.Calendar;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Date;
32 import java.util.Enumeration;
33 import java.util.GregorianCalendar;
34 import java.util.HashMap;
35 import java.util.HashSet;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Locale;
39 import java.util.Map;
40 import java.util.NoSuchElementException;
41 import java.util.Set;
42 import java.util.StringTokenizer;
43 import java.util.TimeZone;
44
45 import org.eclipse.jetty.util.ArrayTernaryTrie;
46 import org.eclipse.jetty.util.BufferUtil;
47 import org.eclipse.jetty.util.DateCache;
48 import org.eclipse.jetty.util.LazyList;
49 import org.eclipse.jetty.util.QuotedStringTokenizer;
50 import org.eclipse.jetty.util.StringMap;
51 import org.eclipse.jetty.util.StringUtil;
52 import org.eclipse.jetty.util.Trie;
53 import org.eclipse.jetty.util.log.Log;
54 import org.eclipse.jetty.util.log.Logger;
55
56
57
58
59
60
61
62
63
64
65
66 public class HttpFields implements Iterable<HttpField>
67 {
68 private static final Logger LOG = Log.getLogger(HttpFields.class);
69 public static final TimeZone __GMT = TimeZone.getTimeZone("GMT");
70 public static final DateCache __dateCache = new DateCache("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
71
72 public static final String __COOKIE_DELIM="\",;\\ \t";
73
74 static
75 {
76 __GMT.setID("GMT");
77 __dateCache.setTimeZone(__GMT);
78 }
79
80 public final static String __separators = ", \t";
81
82 private static final String[] DAYS =
83 { "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
84 private static final String[] MONTHS =
85 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan"};
86
87 public static class DateGenerator
88 {
89 private final StringBuilder buf = new StringBuilder(32);
90 private final GregorianCalendar gc = new GregorianCalendar(__GMT);
91
92
93
94
95 public String formatDate(long date)
96 {
97 buf.setLength(0);
98 gc.setTimeInMillis(date);
99
100 int day_of_week = gc.get(Calendar.DAY_OF_WEEK);
101 int day_of_month = gc.get(Calendar.DAY_OF_MONTH);
102 int month = gc.get(Calendar.MONTH);
103 int year = gc.get(Calendar.YEAR);
104 int century = year / 100;
105 year = year % 100;
106
107 int hours = gc.get(Calendar.HOUR_OF_DAY);
108 int minutes = gc.get(Calendar.MINUTE);
109 int seconds = gc.get(Calendar.SECOND);
110
111 buf.append(DAYS[day_of_week]);
112 buf.append(',');
113 buf.append(' ');
114 StringUtil.append2digits(buf, day_of_month);
115
116 buf.append(' ');
117 buf.append(MONTHS[month]);
118 buf.append(' ');
119 StringUtil.append2digits(buf, century);
120 StringUtil.append2digits(buf, year);
121
122 buf.append(' ');
123 StringUtil.append2digits(buf, hours);
124 buf.append(':');
125 StringUtil.append2digits(buf, minutes);
126 buf.append(':');
127 StringUtil.append2digits(buf, seconds);
128 buf.append(" GMT");
129 return buf.toString();
130 }
131
132
133
134
135 public void formatCookieDate(StringBuilder buf, long date)
136 {
137 gc.setTimeInMillis(date);
138
139 int day_of_week = gc.get(Calendar.DAY_OF_WEEK);
140 int day_of_month = gc.get(Calendar.DAY_OF_MONTH);
141 int month = gc.get(Calendar.MONTH);
142 int year = gc.get(Calendar.YEAR);
143 year = year % 10000;
144
145 int epoch = (int) ((date / 1000) % (60 * 60 * 24));
146 int seconds = epoch % 60;
147 epoch = epoch / 60;
148 int minutes = epoch % 60;
149 int hours = epoch / 60;
150
151 buf.append(DAYS[day_of_week]);
152 buf.append(',');
153 buf.append(' ');
154 StringUtil.append2digits(buf, day_of_month);
155
156 buf.append('-');
157 buf.append(MONTHS[month]);
158 buf.append('-');
159 StringUtil.append2digits(buf, year/100);
160 StringUtil.append2digits(buf, year%100);
161
162 buf.append(' ');
163 StringUtil.append2digits(buf, hours);
164 buf.append(':');
165 StringUtil.append2digits(buf, minutes);
166 buf.append(':');
167 StringUtil.append2digits(buf, seconds);
168 buf.append(" GMT");
169 }
170 }
171
172 private static final ThreadLocal<DateGenerator> __dateGenerator =new ThreadLocal<DateGenerator>()
173 {
174 @Override
175 protected DateGenerator initialValue()
176 {
177 return new DateGenerator();
178 }
179 };
180
181
182
183
184 public static String formatDate(long date)
185 {
186 return __dateGenerator.get().formatDate(date);
187 }
188
189
190
191
192 public static void formatCookieDate(StringBuilder buf, long date)
193 {
194 __dateGenerator.get().formatCookieDate(buf,date);
195 }
196
197
198
199
200 public static String formatCookieDate(long date)
201 {
202 StringBuilder buf = new StringBuilder(28);
203 formatCookieDate(buf, date);
204 return buf.toString();
205 }
206
207 private final static String __dateReceiveFmt[] =
208 {
209 "EEE, dd MMM yyyy HH:mm:ss zzz",
210 "EEE, dd-MMM-yy HH:mm:ss",
211 "EEE MMM dd HH:mm:ss yyyy",
212
213 "EEE, dd MMM yyyy HH:mm:ss", "EEE dd MMM yyyy HH:mm:ss zzz",
214 "EEE dd MMM yyyy HH:mm:ss", "EEE MMM dd yyyy HH:mm:ss zzz", "EEE MMM dd yyyy HH:mm:ss",
215 "EEE MMM-dd-yyyy HH:mm:ss zzz", "EEE MMM-dd-yyyy HH:mm:ss", "dd MMM yyyy HH:mm:ss zzz",
216 "dd MMM yyyy HH:mm:ss", "dd-MMM-yy HH:mm:ss zzz", "dd-MMM-yy HH:mm:ss", "MMM dd HH:mm:ss yyyy zzz",
217 "MMM dd HH:mm:ss yyyy", "EEE MMM dd HH:mm:ss yyyy zzz",
218 "EEE, MMM dd HH:mm:ss yyyy zzz", "EEE, MMM dd HH:mm:ss yyyy", "EEE, dd-MMM-yy HH:mm:ss zzz",
219 "EEE dd-MMM-yy HH:mm:ss zzz", "EEE dd-MMM-yy HH:mm:ss",
220 };
221
222 private static class DateParser
223 {
224 final SimpleDateFormat _dateReceive[]= new SimpleDateFormat[__dateReceiveFmt.length];
225
226 long parse(final String dateVal)
227 {
228 for (int i = 0; i < _dateReceive.length; i++)
229 {
230 if (_dateReceive[i] == null)
231 {
232 _dateReceive[i] = new SimpleDateFormat(__dateReceiveFmt[i], Locale.US);
233 _dateReceive[i].setTimeZone(__GMT);
234 }
235
236 try
237 {
238 Date date = (Date) _dateReceive[i].parseObject(dateVal);
239 return date.getTime();
240 }
241 catch (java.lang.Exception e)
242 {
243
244 }
245 }
246
247 if (dateVal.endsWith(" GMT"))
248 {
249 final String val = dateVal.substring(0, dateVal.length() - 4);
250
251 for (SimpleDateFormat element : _dateReceive)
252 {
253 try
254 {
255 Date date = (Date) element.parseObject(val);
256 return date.getTime();
257 }
258 catch (java.lang.Exception e)
259 {
260
261 }
262 }
263 }
264 return -1;
265 }
266 }
267
268 public static long parseDate(String date)
269 {
270 return __dateParser.get().parse(date);
271 }
272
273 private static final ThreadLocal<DateParser> __dateParser =new ThreadLocal<DateParser>()
274 {
275 @Override
276 protected DateParser initialValue()
277 {
278 return new DateParser();
279 }
280 };
281
282 public final static String __01Jan1970=formatDate(0);
283 public final static ByteBuffer __01Jan1970_BUFFER=BufferUtil.toBuffer(__01Jan1970);
284 public final static String __01Jan1970_COOKIE = formatCookieDate(0).trim();
285 private final ArrayList<HttpField> _fields = new ArrayList<>(20);
286
287
288
289
290 public HttpFields()
291 {
292 }
293
294
295
296
297
298 public Collection<String> getFieldNamesCollection()
299 {
300 final Set<String> list = new HashSet<>(_fields.size());
301 for (HttpField f : _fields)
302 {
303 if (f!=null)
304 list.add(f.getName());
305 }
306 return list;
307 }
308
309
310
311
312
313 public Enumeration<String> getFieldNames()
314 {
315 return Collections.enumeration(getFieldNamesCollection());
316 }
317
318 public int size()
319 {
320 return _fields.size();
321 }
322
323
324
325
326
327
328 public HttpField getField(int i)
329 {
330 return _fields.get(i);
331 }
332
333 @Override
334 public Iterator<HttpField> iterator()
335 {
336 return _fields.iterator();
337 }
338
339 public HttpField getField(HttpHeader header)
340 {
341 for (int i=0;i<_fields.size();i++)
342 {
343 HttpField f=_fields.get(i);
344 if (f.getHeader()==header)
345 return f;
346 }
347 return null;
348 }
349
350 public HttpField getField(String name)
351 {
352 for (int i=0;i<_fields.size();i++)
353 {
354 HttpField f=_fields.get(i);
355 if (f.getName().equalsIgnoreCase(name))
356 return f;
357 }
358 return null;
359 }
360
361 public boolean contains(HttpHeader header, String value)
362 {
363 for (int i=0;i<_fields.size();i++)
364 {
365 HttpField f=_fields.get(i);
366 if (f.getHeader()==header && f.contains(value))
367 return true;
368 }
369 return false;
370 }
371
372 public boolean contains(String name, String value)
373 {
374 for (int i=0;i<_fields.size();i++)
375 {
376 HttpField f=_fields.get(i);
377 if (f.getName().equalsIgnoreCase(name) && f.contains(value))
378 return true;
379 }
380 return false;
381 }
382
383 public boolean containsKey(String name)
384 {
385 for (int i=0;i<_fields.size();i++)
386 {
387 HttpField f=_fields.get(i);
388 if (f.getName().equalsIgnoreCase(name))
389 return true;
390 }
391 return false;
392 }
393
394 public String getStringField(HttpHeader header)
395 {
396 return getStringField(header.asString());
397 }
398
399 public String get(HttpHeader header)
400 {
401 return getStringField(header.asString());
402 }
403
404 public String get(String header)
405 {
406 return getStringField(header);
407 }
408
409
410
411
412
413
414 public String getStringField(String name)
415 {
416 HttpField field = getField(name);
417 return field==null?null:field.getValue();
418 }
419
420
421
422
423
424
425
426
427 public Collection<String> getValuesCollection(String name)
428 {
429 final List<String> list = new ArrayList<>();
430 for (HttpField f : _fields)
431 if (f.getName().equalsIgnoreCase(name))
432 list.add(f.getValue());
433 return list;
434 }
435
436
437
438
439
440
441
442 public Enumeration<String> getValues(final String name)
443 {
444 for (int i=0;i<_fields.size();i++)
445 {
446 final HttpField f = _fields.get(i);
447
448 if (f.getName().equalsIgnoreCase(name) && f.getValue()!=null)
449 {
450 final int first=i;
451 return new Enumeration<String>()
452 {
453 HttpField field=f;
454 int i = first+1;
455
456 @Override
457 public boolean hasMoreElements()
458 {
459 if (field==null)
460 {
461 while (i<_fields.size())
462 {
463 field=_fields.get(i++);
464 if (field.getName().equalsIgnoreCase(name) && field.getValue()!=null)
465 return true;
466 }
467 field=null;
468 return false;
469 }
470 return true;
471 }
472
473 @Override
474 public String nextElement() throws NoSuchElementException
475 {
476 if (hasMoreElements())
477 {
478 String value=field.getValue();
479 field=null;
480 return value;
481 }
482 throw new NoSuchElementException();
483 }
484
485 };
486 }
487 }
488
489 List<String> empty=Collections.emptyList();
490 return Collections.enumeration(empty);
491
492 }
493
494
495
496
497
498
499
500
501
502
503 public Enumeration<String> getValues(String name, final String separators)
504 {
505 final Enumeration<String> e = getValues(name);
506 if (e == null)
507 return null;
508 return new Enumeration<String>()
509 {
510 QuotedStringTokenizer tok = null;
511
512 @Override
513 public boolean hasMoreElements()
514 {
515 if (tok != null && tok.hasMoreElements()) return true;
516 while (e.hasMoreElements())
517 {
518 String value = e.nextElement();
519 if (value!=null)
520 {
521 tok = new QuotedStringTokenizer(value, separators, false, false);
522 if (tok.hasMoreElements()) return true;
523 }
524 }
525 tok = null;
526 return false;
527 }
528
529 @Override
530 public String nextElement() throws NoSuchElementException
531 {
532 if (!hasMoreElements()) throw new NoSuchElementException();
533 String next = (String) tok.nextElement();
534 if (next != null) next = next.trim();
535 return next;
536 }
537 };
538 }
539
540 public void put(HttpField field)
541 {
542 boolean put=false;
543 for (int i=_fields.size();i-->0;)
544 {
545 HttpField f=_fields.get(i);
546 if (f.isSame(field))
547 {
548 if (put)
549 _fields.remove(i);
550 else
551 {
552 _fields.set(i,field);
553 put=true;
554 }
555 }
556 }
557 if (!put)
558 _fields.add(field);
559 }
560
561
562
563
564
565
566
567 public void put(String name, String value)
568 {
569 if (value == null)
570 remove(name);
571 else
572 put(new HttpField(name, value));
573 }
574
575 public void put(HttpHeader header, HttpHeaderValue value)
576 {
577 put(header,value.toString());
578 }
579
580
581
582
583
584
585
586 public void put(HttpHeader header, String value)
587 {
588 if (value == null)
589 remove(header);
590 else
591 put(new HttpField(header, value));
592 }
593
594
595
596
597
598
599
600 public void put(String name, List<String> list)
601 {
602 remove(name);
603 for (String v : list)
604 if (v!=null)
605 add(name,v);
606 }
607
608
609
610
611
612
613
614
615
616
617 public void add(String name, String value) throws IllegalArgumentException
618 {
619 if (value == null)
620 return;
621
622 HttpField field = new HttpField(name, value);
623 _fields.add(field);
624 }
625
626 public void add(HttpHeader header, HttpHeaderValue value) throws IllegalArgumentException
627 {
628 add(header,value.toString());
629 }
630
631
632
633
634
635
636
637
638
639 public void add(HttpHeader header, String value) throws IllegalArgumentException
640 {
641 if (value == null) throw new IllegalArgumentException("null value");
642
643 HttpField field = new HttpField(header, value);
644 _fields.add(field);
645 }
646
647
648
649
650
651
652 public void remove(HttpHeader name)
653 {
654 for (int i=_fields.size();i-->0;)
655 {
656 HttpField f=_fields.get(i);
657 if (f.getHeader()==name)
658 _fields.remove(i);
659 }
660 }
661
662
663
664
665
666
667 public void remove(String name)
668 {
669 for (int i=_fields.size();i-->0;)
670 {
671 HttpField f=_fields.get(i);
672 if (f.getName().equalsIgnoreCase(name))
673 _fields.remove(i);
674 }
675 }
676
677
678
679
680
681
682
683
684 public long getLongField(String name) throws NumberFormatException
685 {
686 HttpField field = getField(name);
687 return field==null?-1L:field.getLongValue();
688 }
689
690
691
692
693
694
695
696 public long getDateField(String name)
697 {
698 HttpField field = getField(name);
699 if (field == null)
700 return -1;
701
702 String val = valueParameters(field.getValue(), null);
703 if (val == null)
704 return -1;
705
706 final long date = __dateParser.get().parse(val);
707 if (date==-1)
708 throw new IllegalArgumentException("Cannot convert date: " + val);
709 return date;
710 }
711
712
713
714
715
716
717
718
719 public void putLongField(HttpHeader name, long value)
720 {
721 String v = Long.toString(value);
722 put(name, v);
723 }
724
725
726
727
728
729
730
731 public void putLongField(String name, long value)
732 {
733 String v = Long.toString(value);
734 put(name, v);
735 }
736
737
738
739
740
741
742
743
744 public void putDateField(HttpHeader name, long date)
745 {
746 String d=formatDate(date);
747 put(name, d);
748 }
749
750
751
752
753
754
755
756 public void putDateField(String name, long date)
757 {
758 String d=formatDate(date);
759 put(name, d);
760 }
761
762
763
764
765
766
767
768 public void addDateField(String name, long date)
769 {
770 String d=formatDate(date);
771 add(name,d);
772 }
773
774
775
776
777
778
779 public void addSetCookie(HttpCookie cookie)
780 {
781 addSetCookie(
782 cookie.getName(),
783 cookie.getValue(),
784 cookie.getDomain(),
785 cookie.getPath(),
786 cookie.getMaxAge(),
787 cookie.getComment(),
788 cookie.isSecure(),
789 cookie.isHttpOnly(),
790 cookie.getVersion());
791 }
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806 public void addSetCookie(
807 final String name,
808 final String value,
809 final String domain,
810 final String path,
811 final long maxAge,
812 final String comment,
813 final boolean isSecure,
814 final boolean isHttpOnly,
815 int version)
816 {
817
818 if (name == null || name.length() == 0)
819 throw new IllegalArgumentException("Bad cookie name");
820
821
822 StringBuilder buf = new StringBuilder(128);
823
824
825 boolean quote_name=isQuoteNeededForCookie(name);
826 quoteOnlyOrAppend(buf,name,quote_name);
827
828 buf.append('=');
829
830
831 String name_equals=buf.toString();
832
833
834 boolean quote_value=isQuoteNeededForCookie(value);
835 quoteOnlyOrAppend(buf,value,quote_value);
836
837
838 boolean has_domain = domain!=null && domain.length()>0;
839 boolean quote_domain = has_domain && isQuoteNeededForCookie(domain);
840 boolean has_path = path!=null && path.length()>0;
841 boolean quote_path = has_path && isQuoteNeededForCookie(path);
842
843
844 if (version==0 && ( comment!=null || quote_name || quote_value || quote_domain || quote_path || isQuoted(name) || isQuoted(value) || isQuoted(path) || isQuoted(domain)))
845 version=1;
846
847
848 if (version==1)
849 buf.append (";Version=1");
850 else if (version>1)
851 buf.append (";Version=").append(version);
852
853
854 if (has_path)
855 {
856 buf.append(";Path=");
857 quoteOnlyOrAppend(buf,path,quote_path);
858 }
859
860
861 if (has_domain)
862 {
863 buf.append(";Domain=");
864 quoteOnlyOrAppend(buf,domain,quote_domain);
865 }
866
867
868 if (maxAge >= 0)
869 {
870
871
872 buf.append(";Expires=");
873 if (maxAge == 0)
874 buf.append(__01Jan1970_COOKIE);
875 else
876 formatCookieDate(buf, System.currentTimeMillis() + 1000L * maxAge);
877
878
879 if (version>=1)
880 {
881 buf.append(";Max-Age=");
882 buf.append(maxAge);
883 }
884 }
885
886
887 if (isSecure)
888 buf.append(";Secure");
889 if (isHttpOnly)
890 buf.append(";HttpOnly");
891 if (comment != null)
892 {
893 buf.append(";Comment=");
894 quoteOnlyOrAppend(buf,comment,isQuoteNeededForCookie(comment));
895 }
896
897
898 Iterator<HttpField> i=_fields.iterator();
899 while (i.hasNext())
900 {
901 HttpField field=i.next();
902 if (field.getHeader()==HttpHeader.SET_COOKIE)
903 {
904 String val = field.getValue();
905 if (val!=null && val.startsWith(name_equals))
906 {
907
908 if (((!has_domain && !val.contains("Domain")) || (has_domain && val.contains(domain))) &&
909 ((!has_path && !val.contains("Path")) || (has_path && val.contains(path))))
910 {
911 i.remove();
912 }
913 }
914 }
915 }
916
917
918 add(HttpHeader.SET_COOKIE.toString(), buf.toString());
919
920
921 put(HttpHeader.EXPIRES.toString(), __01Jan1970);
922 }
923
924 public void putTo(ByteBuffer bufferInFillMode)
925 {
926 for (HttpField field : _fields)
927 {
928 if (field != null)
929 field.putTo(bufferInFillMode);
930 }
931 BufferUtil.putCRLF(bufferInFillMode);
932 }
933
934 @Override
935 public String
936 toString()
937 {
938 try
939 {
940 StringBuilder buffer = new StringBuilder();
941 for (HttpField field : _fields)
942 {
943 if (field != null)
944 {
945 String tmp = field.getName();
946 if (tmp != null) buffer.append(tmp);
947 buffer.append(": ");
948 tmp = field.getValue();
949 if (tmp != null) buffer.append(tmp);
950 buffer.append("\r\n");
951 }
952 }
953 buffer.append("\r\n");
954 return buffer.toString();
955 }
956 catch (Exception e)
957 {
958 LOG.warn(e);
959 return e.toString();
960 }
961 }
962
963
964
965
966 public void clear()
967 {
968 _fields.clear();
969 }
970
971 public void add(HttpField field)
972 {
973 _fields.add(field);
974 }
975
976
977
978
979
980
981
982
983
984 public void add(HttpFields fields)
985 {
986 if (fields == null) return;
987
988 Enumeration<String> e = fields.getFieldNames();
989 while (e.hasMoreElements())
990 {
991 String name = e.nextElement();
992 Enumeration<String> values = fields.getValues(name);
993 while (values.hasMoreElements())
994 add(name, values.nextElement());
995 }
996 }
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012 public static String valueParameters(String value, Map<String,String> parameters)
1013 {
1014 if (value == null) return null;
1015
1016 int i = value.indexOf(';');
1017 if (i < 0) return value;
1018 if (parameters == null) return value.substring(0, i).trim();
1019
1020 StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";", false, true);
1021 while (tok1.hasMoreTokens())
1022 {
1023 String token = tok1.nextToken();
1024 StringTokenizer tok2 = new QuotedStringTokenizer(token, "= ");
1025 if (tok2.hasMoreTokens())
1026 {
1027 String paramName = tok2.nextToken();
1028 String paramVal = null;
1029 if (tok2.hasMoreTokens()) paramVal = tok2.nextToken();
1030 parameters.put(paramName, paramVal);
1031 }
1032 }
1033
1034 return value.substring(0, i).trim();
1035 }
1036
1037 private static final Float __one = new Float("1.0");
1038 private static final Float __zero = new Float("0.0");
1039 private static final Trie<Float> __qualities = new ArrayTernaryTrie<>();
1040 static
1041 {
1042 __qualities.put("*", __one);
1043 __qualities.put("1.0", __one);
1044 __qualities.put("1", __one);
1045 __qualities.put("0.9", new Float("0.9"));
1046 __qualities.put("0.8", new Float("0.8"));
1047 __qualities.put("0.7", new Float("0.7"));
1048 __qualities.put("0.66", new Float("0.66"));
1049 __qualities.put("0.6", new Float("0.6"));
1050 __qualities.put("0.5", new Float("0.5"));
1051 __qualities.put("0.4", new Float("0.4"));
1052 __qualities.put("0.33", new Float("0.33"));
1053 __qualities.put("0.3", new Float("0.3"));
1054 __qualities.put("0.2", new Float("0.2"));
1055 __qualities.put("0.1", new Float("0.1"));
1056 __qualities.put("0", __zero);
1057 __qualities.put("0.0", __zero);
1058 }
1059
1060 public static Float getQuality(String value)
1061 {
1062 if (value == null) return __zero;
1063
1064 int qe = value.indexOf(";");
1065 if (qe++ < 0 || qe == value.length()) return __one;
1066
1067 if (value.charAt(qe++) == 'q')
1068 {
1069 qe++;
1070 Float q = __qualities.get(value, qe, value.length() - qe);
1071 if (q != null)
1072 return q;
1073 }
1074
1075 Map<String,String> params = new HashMap<>(4);
1076 valueParameters(value, params);
1077 String qs = params.get("q");
1078 if (qs==null)
1079 qs="*";
1080 Float q = __qualities.get(qs);
1081 if (q == null)
1082 {
1083 try
1084 {
1085 q = new Float(qs);
1086 }
1087 catch (Exception e)
1088 {
1089 q = __one;
1090 }
1091 }
1092 return q;
1093 }
1094
1095
1096
1097
1098
1099
1100
1101 public static List<String> qualityList(Enumeration<String> e)
1102 {
1103 if (e == null || !e.hasMoreElements())
1104 return Collections.emptyList();
1105
1106 Object list = null;
1107 Object qual = null;
1108
1109
1110 while (e.hasMoreElements())
1111 {
1112 String v = e.nextElement();
1113 Float q = getQuality(v);
1114
1115 if (q >= 0.001)
1116 {
1117 list = LazyList.add(list, v);
1118 qual = LazyList.add(qual, q);
1119 }
1120 }
1121
1122 List<String> vl = LazyList.getList(list, false);
1123 if (vl.size() < 2)
1124 return vl;
1125
1126 List<Float> ql = LazyList.getList(qual, false);
1127
1128
1129 Float last = __zero;
1130 for (int i = vl.size(); i-- > 0;)
1131 {
1132 Float q = ql.get(i);
1133 if (last.compareTo(q) > 0)
1134 {
1135 String tmp = vl.get(i);
1136 vl.set(i, vl.get(i + 1));
1137 vl.set(i + 1, tmp);
1138 ql.set(i, ql.get(i + 1));
1139 ql.set(i + 1, q);
1140 last = __zero;
1141 i = vl.size();
1142 continue;
1143 }
1144 last = q;
1145 }
1146 ql.clear();
1147 return vl;
1148 }
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158 public static boolean isQuoteNeededForCookie(String s)
1159 {
1160 if (s==null || s.length()==0)
1161 return true;
1162
1163 if (QuotedStringTokenizer.isQuoted(s))
1164 return false;
1165
1166 for (int i=0;i<s.length();i++)
1167 {
1168 char c = s.charAt(i);
1169 if (__COOKIE_DELIM.indexOf(c)>=0)
1170 return true;
1171
1172 if (c<0x20 || c>=0x7f)
1173 throw new IllegalArgumentException("Illegal character in cookie value");
1174 }
1175
1176 return false;
1177 }
1178
1179
1180 private static void quoteOnlyOrAppend(StringBuilder buf, String s, boolean quote)
1181 {
1182 if (quote)
1183 QuotedStringTokenizer.quoteOnly(buf,s);
1184 else
1185 buf.append(s);
1186 }
1187 }