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