1 package org.apache.velocity.tools.view;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
24 import java.util.regex.PatternSyntaxException;
25 import java.util.*;
26 import javax.servlet.http.HttpServletRequest;
27 import org.apache.velocity.runtime.log.Log;
28 import org.apache.velocity.tools.Scope;
29 import org.apache.velocity.tools.ConversionUtils;
30 import org.apache.velocity.tools.generic.FormatConfig;
31 import org.apache.velocity.tools.config.DefaultKey;
32 import org.apache.velocity.tools.config.InvalidScope;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 @DefaultKey("browser")
72 @InvalidScope(Scope.APPLICATION)
73 public class BrowserTool extends FormatConfig implements java.io.Serializable
74 {
75 private static final long serialVersionUID = 1734529350532353339L;
76
77 protected Log LOG;
78
79
80 private String userAgent = null;
81 private String version = null;
82 private int majorVersion = -1;
83 private int minorVersion = -1;
84 private String geckoVersion = null;
85 private int geckoMajorVersion = -1;
86 private int geckoMinorVersion = -1;
87
88 private static Pattern genericVersion = Pattern.compile(
89 "/"
90
91 +
92 "([A-Za-z]*"
93
94 +
95 "( [\\d]* )"
96
97 + "\\."
98 +
99 "( [\\d]* )"
100
101 + "[^\\s]*)"
102 , Pattern.COMMENTS);
103 private static Pattern firefoxVersion = Pattern.compile(
104 "/"
105 +
106 "(( [\\d]* )"
107
108 + "\\."
109 +
110 "( [\\d]* )"
111
112 + "[^\\s]*)"
113 , Pattern.COMMENTS);
114 private static Pattern ieVersion = Pattern.compile(
115 "compatible;"
116 + "\\s*"
117 + "\\w*"
118 + "[\\s|/]"
119 +
120 "([A-Za-z]*"
121
122 +
123 "( [\\d]* )"
124
125 + "\\."
126 +
127 "( [\\d]* )"
128
129 + "[^\\s]*)"
130 , Pattern.COMMENTS);
131 private static Pattern safariVersion = Pattern.compile(
132 "safari/"
133 +
134 "(( [\\d]* )"
135
136 + "(?:"
137 + "\\."
138 +
139 " [\\d]* )?)"
140
141 , Pattern.COMMENTS);
142 private static Pattern mozillaVersion = Pattern.compile(
143 "netscape/"
144 +
145 "(( [\\d]* )"
146
147 + "\\."
148 +
149 "( [\\d]* )"
150
151 + "[^\\s]*)"
152 , Pattern.COMMENTS);
153 private static Pattern fallbackVersion = Pattern.compile(
154 "[\\w]+/"
155 +
156 "( [\\d]+ );"
157
158 , Pattern.COMMENTS);
159
160
161
162 private String acceptLanguage = null;
163 private SortedMap<Float,List<String>> languageRangesByQuality = null;
164 private String starLanguageRange = null;
165
166 private List<String> languagesFilter = null;
167 private String preferredLanguage = null;
168
169 private static Pattern quality = Pattern.compile("^q\\s*=\\s*(\\d(?:0(?:.\\d{0,3})?|1(?:.0{0,3}))?)$");
170
171
172
173
174
175 public void setRequest(HttpServletRequest request)
176 {
177 if (request != null)
178 {
179 setUserAgent(request.getHeader("User-Agent"));
180 setAcceptLanguage(request.getHeader("Accept-Language"));
181 }
182 else
183 {
184 setUserAgent(null);
185 setAcceptLanguage(null);
186 }
187 }
188
189
190
191
192 public void setLog(Log log)
193 {
194 if (log == null)
195 {
196 throw new NullPointerException("log should not be set to null");
197 }
198 this.LOG = log;
199 }
200
201
202
203
204
205
206
207
208 public void setUserAgent(String ua)
209 {
210 if (ua == null)
211 {
212 userAgent = "";
213 }
214 else
215 {
216 userAgent = ua.toLowerCase();
217 }
218 }
219
220 public void setAcceptLanguage(String al)
221 {
222 if(al == null)
223 {
224 acceptLanguage = "";
225 }
226 else
227 {
228 acceptLanguage = al.toLowerCase();
229 }
230 }
231
232 public void setLanguagesFilter(String filter)
233 {
234 if(filter == null || filter.length() == 0)
235 {
236 languagesFilter = null;
237 }
238 else
239 {
240 languagesFilter = Arrays.asList(filter.split(","));
241 }
242
243 preferredLanguage = null;
244 }
245
246 public String getLanguagesFilter()
247 {
248 return languagesFilter.toString();
249 }
250
251 @Override
252 public String toString()
253 {
254 return this.getClass().getSimpleName()+"[ua="+userAgent+"]";
255 }
256
257
258
259
260 public boolean get(String key)
261 {
262 return test(key);
263 }
264
265 public String getUserAgent()
266 {
267 return userAgent;
268 }
269
270 public String getAcceptLanguage()
271 {
272 return acceptLanguage;
273 }
274
275
276
277 public String getVersion()
278 {
279 parseVersion();
280 return version;
281 }
282
283 public int getMajorVersion()
284 {
285 parseVersion();
286 return majorVersion;
287 }
288
289 public int getMinorVersion()
290 {
291 parseVersion();
292 return minorVersion;
293 }
294
295 public String getGeckoVersion()
296 {
297 parseVersion();
298 return geckoVersion;
299 }
300
301 public int getGeckoMajorVersion()
302 {
303 parseVersion();
304 return geckoMajorVersion;
305 }
306
307 public int getGeckoMinorVersion()
308 {
309 parseVersion();
310 return geckoMinorVersion;
311 }
312
313
314
315 public boolean getGecko()
316 {
317 return test("gecko") && !test("like gecko");
318 }
319
320 public boolean getFirefox()
321 {
322 return test("firefox") || test("firebird") || test("phoenix") || test("iceweasel");
323 }
324
325 public boolean getIceweasel()
326 {
327 return test("iceweasel");
328 }
329
330 public boolean getGaleon()
331 {
332 return test("galeon");
333 }
334
335 public boolean getKmeleon()
336 {
337 return test("k-meleon");
338 }
339
340 public boolean getEpiphany()
341 {
342 return test("epiphany");
343 }
344
345 public boolean getSafari()
346 {
347 return (test("safari") || test("applewebkit")) && !test("chrome");
348 }
349
350 public boolean getChrome() {
351 return test("chrome");
352 }
353
354 public boolean getDillo()
355 {
356 return test("dillo");
357 }
358
359 public boolean getNetscape()
360 {
361 return test("netscape") || !getFirefox() && !getSafari() && test("mozilla") &&
362 !test("spoofer") && !test("compatible") && !test("opera") &&
363 !test("webtv") && !test("hotjava");
364 }
365
366 public boolean getNav2()
367 {
368 return getNetscape() && getMajorVersion() == 2;
369 }
370
371 public boolean getNav3()
372 {
373 return getNetscape() && getMajorVersion() == 3;
374 }
375
376 public boolean getNav4()
377 {
378 return getNetscape() && getMajorVersion() == 4;
379 }
380
381 public boolean getNav4up()
382 {
383 return getNetscape() && getMajorVersion() >= 4;
384 }
385
386 public boolean getNav45()
387 {
388 return getNetscape() && getMajorVersion() == 4 &&
389 getMinorVersion() == 5;
390 }
391
392 public boolean getNav45up()
393 {
394 return getNetscape() && getMajorVersion() >= 5 ||
395 getNav4() && getMinorVersion() >= 5;
396 }
397
398 public boolean getNavgold()
399 {
400 return test("gold");
401 }
402
403 public boolean getNav6()
404 {
405 return getNetscape() && getMajorVersion() == 5;
406 }
407
408 public boolean getNav6up()
409 {
410 return getNetscape() && getMajorVersion() >= 5;
411 }
412
413 public boolean getMozilla()
414 {
415 return getNetscape() && getGecko();
416 }
417
418 public boolean getIe()
419 {
420 return test("msie") && !test("opera") ||
421 test("microsoft internet explorer");
422 }
423
424 public boolean getIe3()
425 {
426 return getIe() && getMajorVersion() < 4;
427 }
428
429 public boolean getIe4()
430 {
431 return getIe() && getMajorVersion() == 4;
432 }
433
434 public boolean getIe4up()
435 {
436 return getIe() && getMajorVersion() >= 4;
437 }
438
439 public boolean getIe5()
440 {
441 return getIe() && getMajorVersion() == 5;
442 }
443
444 public boolean getIe5up()
445 {
446 return getIe() && getMajorVersion() >= 5;
447 }
448
449 public boolean getIe55()
450 {
451 return getIe() && getMajorVersion() == 5 && getMinorVersion() >= 5;
452 }
453
454 public boolean getIe55up()
455 {
456 return (getIe5() && getMinorVersion() >= 5) ||
457 (getIe() && getMajorVersion() >= 6);
458 }
459
460 public boolean getIe6()
461 {
462 return getIe() && getMajorVersion() == 6;
463 }
464
465 public boolean getIe6up()
466 {
467 return getIe() && getMajorVersion() >= 6;
468 }
469
470 public boolean getIe7()
471 {
472 return getIe() && getMajorVersion() == 7;
473 }
474
475 public boolean getIe7up()
476 {
477 return getIe() && getMajorVersion() >= 7;
478 }
479
480 public boolean getIe8()
481 {
482 return getIe() && getMajorVersion() == 8;
483 }
484
485 public boolean getIe8up()
486 {
487 return getIe() && getMajorVersion() >= 8;
488 }
489
490 public boolean getNeoplanet()
491 {
492 return test("neoplanet");
493 }
494
495 public boolean getNeoplanet2()
496 {
497 return getNeoplanet() && test("2.");
498 }
499
500 public boolean getAol()
501 {
502 return test("aol");
503 }
504
505 public boolean getAol3()
506 {
507 return test("aol 3.0") || getAol() && getIe3();
508 }
509
510 public boolean getAol4()
511 {
512 return test("aol 4.0") || getAol() && getIe4();
513 }
514
515 public boolean getAol5()
516 {
517 return test("aol 5.0");
518 }
519
520 public boolean getAol6()
521 {
522 return test("aol 6.0");
523 }
524
525 public boolean getAolTV()
526 {
527 return test("navio") || test("navio_aoltv");
528 }
529
530 public boolean getOpera()
531 {
532 return test("opera");
533 }
534
535 public boolean getOpera3()
536 {
537 return test("opera 3") || test("opera/3");
538 }
539
540 public boolean getOpera4()
541 {
542 return test("opera 4") || test("opera/4");
543 }
544
545 public boolean getOpera5()
546 {
547 return test("opera 5") || test("opera/5");
548 }
549
550 public boolean getOpera6()
551 {
552 return test("opera 6") || test("opera/6");
553 }
554
555 public boolean getOpera7()
556 {
557 return test("opera 7") || test("opera/7");
558 }
559
560 public boolean getOpera8()
561 {
562 return test("opera 8") || test("opera/8");
563 }
564
565 public boolean getOpera9()
566 {
567 return test("opera/9");
568 }
569
570 public boolean getHotjava()
571 {
572 return test("hotjava");
573 }
574
575 public boolean getHotjava3()
576 {
577 return getHotjava() && getMajorVersion() == 3;
578 }
579
580 public boolean getHotjava3up()
581 {
582 return getHotjava() && getMajorVersion() >= 3;
583 }
584
585 public boolean getLobo()
586 {
587 return test("lobo");
588 }
589
590 public boolean getHttpclient()
591 {
592 return test("httpclient");
593 }
594
595 public boolean getAmaya()
596 {
597 return test("amaya");
598 }
599
600 public boolean getCurl()
601 {
602 return test("libcurl");
603 }
604
605 public boolean getStaroffice()
606 {
607 return test("staroffice");
608 }
609
610 public boolean getIcab()
611 {
612 return test("icab");
613 }
614
615 public boolean getLotusnotes()
616 {
617 return test("lotus-notes");
618 }
619
620 public boolean getKonqueror()
621 {
622 return test("konqueror");
623 }
624
625 public boolean getLynx()
626 {
627 return test("lynx");
628 }
629
630 public boolean getLinks()
631 {
632 return test("links");
633 }
634
635 public boolean getW3m()
636 {
637 return test("w3m");
638 }
639
640 public boolean getWebTV()
641 {
642 return test("webtv");
643 }
644
645 public boolean getMosaic()
646 {
647 return test("mosaic");
648 }
649
650 public boolean getWget()
651 {
652 return test("wget");
653 }
654
655 public boolean getGetright()
656 {
657 return test("getright");
658 }
659
660 public boolean getLwp()
661 {
662 return test("libwww-perl") || test("lwp-");
663 }
664
665 public boolean getYahoo()
666 {
667 return test("yahoo");
668 }
669
670 public boolean getGoogle()
671 {
672 return test("google");
673 }
674
675 public boolean getJava()
676 {
677 return test("java") || test("jdk") || test("httpunit") || test("httpclient") || test("lobo");
678 }
679
680 public boolean getAltavista()
681 {
682 return test("altavista");
683 }
684
685 public boolean getScooter()
686 {
687 return test("scooter");
688 }
689
690 public boolean getLycos()
691 {
692 return test("lycos");
693 }
694
695 public boolean getInfoseek()
696 {
697 return test("infoseek");
698 }
699
700 public boolean getWebcrawler()
701 {
702 return test("webcrawler");
703 }
704
705 public boolean getLinkexchange()
706 {
707 return test("lecodechecker");
708 }
709
710 public boolean getSlurp()
711 {
712 return test("slurp");
713 }
714
715 public boolean getRobot()
716 {
717 return getWget() || getGetright() || getLwp() || getYahoo() ||
718 getGoogle() || getAltavista() || getScooter() || getLycos() ||
719 getInfoseek() || getWebcrawler() || getLinkexchange() ||
720 test("bot") || test("spider") || test("crawl") ||
721 test("agent") || test("seek") || test("search") ||
722 test("reap") || test("worm") || test("find") || test("index") ||
723 test("copy") || test("fetch") || test("ia_archive") ||
724 test("zyborg");
725 }
726
727
728
729 public boolean getBlackberry()
730 {
731 return test("blackberry");
732 }
733
734 public boolean getAudrey()
735 {
736 return test("audrey");
737 }
738
739 public boolean getIopener()
740 {
741 return test("i-opener");
742 }
743
744 public boolean getAvantgo()
745 {
746 return test("avantgo");
747 }
748
749 public boolean getPalm()
750 {
751 return getAvantgo() || test("palmos");
752 }
753
754 public boolean getWap()
755 {
756 return test("up.browser") || test("nokia") || test("alcatel") ||
757 test("ericsson") || userAgent.indexOf("sie-") == 0 ||
758 test("wmlib") || test(" wap") || test("wap ") ||
759 test("wap/") || test("-wap") || test("wap-") ||
760 userAgent.indexOf("wap") == 0 ||
761 test("wapper") || test("zetor");
762 }
763
764
765
766 public boolean getWin16()
767 {
768 return test("win16") || test("16bit") || test("windows 3") ||
769 test("windows 16-bit");
770 }
771
772 public boolean getWin3x()
773 {
774 return test("win16") || test("windows 3") || test("windows 16-bit");
775 }
776
777 public boolean getWin31()
778 {
779 return test("win16") || test("windows 3.1") || test("windows 16-bit");
780 }
781
782 public boolean getWin95()
783 {
784 return test("win95") || test("windows 95");
785 }
786
787 public boolean getWin98()
788 {
789 return test("win98") || test("windows 98");
790 }
791
792 public boolean getWinnt()
793 {
794 return test("winnt") || test("windows nt") || test("nt4") || test("nt3");
795 }
796
797 public boolean getWin2k()
798 {
799 return test("nt 5.0") || test("nt5");
800 }
801
802 public boolean getWinxp()
803 {
804 return test("nt 5.1");
805 }
806
807 public boolean getVista()
808 {
809 return test("nt 6.0");
810 }
811
812 public boolean getDotnet()
813 {
814 return test(".net clr");
815 }
816
817 public boolean getWinme()
818 {
819 return test("win 9x 4.90");
820 }
821
822 public boolean getWin32()
823 {
824 return getWin95() || getWin98() || getWinnt() || getWin2k() ||
825 getWinxp() || getWinme() || test("win32");
826 }
827
828 public boolean getWindows()
829 {
830 return getWin16() || getWin31() || getWin95() || getWin98() ||
831 getWinnt() || getWin32() || getWin2k() || getWinme() ||
832 test("win");
833 }
834
835 public boolean getMac()
836 {
837 return test("macintosh") || test("mac_");
838 }
839
840 public boolean getMacosx()
841 {
842 return test("macintosh") || test("mac os x");
843 }
844
845 public boolean getMac68k()
846 {
847 return getMac() && (test("68k") || test("68000"));
848 }
849
850 public boolean getMacppc()
851 {
852 return getMac() && (test("ppc") || test("powerpc"));
853 }
854
855 public boolean getAmiga()
856 {
857 return test("amiga");
858 }
859
860 public boolean getEmacs()
861 {
862 return test("emacs");
863 }
864
865 public boolean getOs2()
866 {
867 return test("os/2");
868 }
869
870 public boolean getSun()
871 {
872 return test("sun");
873 }
874
875 public boolean getSun4()
876 {
877 return test("sunos 4");
878 }
879
880 public boolean getSun5()
881 {
882 return test("sunos 5");
883 }
884
885 public boolean getSuni86()
886 {
887 return getSun() && test("i86");
888 }
889
890 public boolean getIrix()
891 {
892 return test("irix");
893 }
894
895 public boolean getIrix5()
896 {
897 return test("irix5");
898 }
899
900 public boolean getIrix6()
901 {
902 return test("irix6");
903 }
904
905 public boolean getHpux()
906 {
907 return test("hp-ux");
908 }
909
910 public boolean getHpux9()
911 {
912 return getHpux() && test("09.");
913 }
914
915 public boolean getHpux10()
916 {
917 return getHpux() && test("10.");
918 }
919
920 public boolean getAix()
921 {
922 return test("aix");
923 }
924
925 public boolean getAix1()
926 {
927 return test("aix 1");
928 }
929
930 public boolean getAix2()
931 {
932 return test("aix 2");
933 }
934
935 public boolean getAix3()
936 {
937 return test("aix 3");
938 }
939
940 public boolean getAix4()
941 {
942 return test("aix 4");
943 }
944
945 public boolean getLinux()
946 {
947 return test("linux");
948 }
949
950 public boolean getSco()
951 {
952 return test("sco") || test("unix_sv");
953 }
954
955 public boolean getUnixware()
956 {
957 return test("unix_system_v");
958 }
959
960 public boolean getMpras()
961 {
962 return test("ncr");
963 }
964
965 public boolean getReliant()
966 {
967 return test("reliantunix");
968 }
969
970 public boolean getDec()
971 {
972 return test("dec") || test("osf1") || test("delalpha") ||
973 test("alphaserver") || test("ultrix") || test("alphastation");
974 }
975
976 public boolean getSinix()
977 {
978 return test("sinix");
979 }
980
981 public boolean getFreebsd()
982 {
983 return test("freebsd");
984 }
985
986 public boolean getBsd()
987 {
988 return test("bsd");
989 }
990
991 public boolean getX11()
992 {
993 return test("x11");
994 }
995
996 public boolean getUnix()
997 {
998 return getX11() || getSun() || getIrix() || getHpux() || getSco() ||
999 getUnixware() || getMpras() || getReliant() || getDec() ||
1000 getLinux() || getBsd() || test("unix");
1001 }
1002
1003 public boolean getVMS()
1004 {
1005 return test("vax") || test("openvms");
1006 }
1007
1008
1009
1010
1011
1012
1013 public boolean getCss()
1014 {
1015 return (getIe() && getMajorVersion() >= 4) ||
1016 (getNetscape() && getMajorVersion() >= 4) ||
1017 getGecko() ||
1018 getKonqueror() ||
1019 (getOpera() && getMajorVersion() >= 3) ||
1020 getSafari() ||
1021 getChrome() ||
1022 getLinks();
1023 }
1024
1025 public boolean getCss1()
1026 {
1027 return getCss();
1028 }
1029
1030 public boolean getCss2()
1031 {
1032 return getIe() &&
1033 (getMac() && getMajorVersion() >= 5) ||
1034 (getWin32() && getMajorVersion() >= 6) ||
1035 getGecko() ||
1036 (getOpera() && getMajorVersion() >= 4) ||
1037 (getSafari() && getMajorVersion() >= 2) ||
1038 (getKonqueror() && getMajorVersion() >= 2) ||
1039 getChrome();
1040 }
1041
1042 public boolean getDom0()
1043 {
1044 return (getIe() && getMajorVersion() >= 3) ||
1045 (getNetscape() && getMajorVersion() >= 2) ||
1046 (getOpera() && getMajorVersion() >= 3) ||
1047 getGecko() ||
1048 getSafari() ||
1049 getChrome() ||
1050 getKonqueror();
1051 }
1052
1053 public boolean getDom1()
1054 {
1055 return (getIe() && getMajorVersion() >= 5) ||
1056 getGecko() ||
1057 (getSafari() && getMajorVersion() >= 2) ||
1058 (getOpera() && getMajorVersion() >= 4) ||
1059 (getKonqueror() && getMajorVersion() >= 2)
1060 || getChrome();
1061 }
1062
1063 public boolean getDom2()
1064 {
1065 return (getIe() && getMajorVersion() >= 6) ||
1066 (getMozilla() && getMajorVersion() >= 5.0) ||
1067 (getOpera() && getMajorVersion() >= 7) ||
1068 getFirefox() ||
1069 getChrome();
1070 }
1071
1072 public boolean getJavascript()
1073 {
1074 return getDom0();
1075 }
1076
1077
1078
1079 public String getPreferredLanguage()
1080 {
1081 if(preferredLanguage != null) return preferredLanguage;
1082
1083 parseAcceptLanguage();
1084 if(languageRangesByQuality.size() == 0)
1085 {
1086 preferredLanguage = starLanguageRange;
1087 }
1088 else
1089 {
1090 List<List<String>> lists = new ArrayList<List<String>>(languageRangesByQuality.values());
1091 Collections.reverse(lists);
1092 for(List<String> lst : lists)
1093 {
1094 for(String l : lst)
1095 {
1096 preferredLanguage = filterLanguageTag(l);
1097 if(preferredLanguage != null) break;
1098 }
1099 if(preferredLanguage != null) break;
1100 }
1101 }
1102
1103 if(preferredLanguage == null)
1104 {
1105 preferredLanguage = filterLanguageTag(languagesFilter == null ? getLocale().getDisplayName() : languagesFilter.get(0));
1106 }
1107
1108 assert(preferredLanguage != null);
1109 return preferredLanguage;
1110 }
1111
1112 public Locale getPreferredLocale()
1113 {
1114 return ConversionUtils.toLocale(getPreferredLanguage());
1115 }
1116
1117
1118
1119 private boolean test(String key)
1120 {
1121 return userAgent.indexOf(key) != -1;
1122 }
1123
1124 private void parseVersion()
1125 {
1126 try
1127 {
1128 if (version != null)
1129 {
1130 return;
1131 }
1132
1133
1134 Matcher v = genericVersion.matcher(userAgent);
1135
1136 if (v.find())
1137 {
1138 version = v.group(1);
1139 if(version.endsWith(";"))
1140 {
1141 version = version.substring(0,version.length()-1);
1142 }
1143 try
1144 {
1145 majorVersion = Integer.valueOf(v.group(2));
1146 String minor = v.group(3);
1147 if (minor.startsWith("0"))
1148 {
1149 minorVersion = 0;
1150 }
1151 else
1152 {
1153 minorVersion = Integer.valueOf(minor);
1154 }
1155 }
1156 catch (NumberFormatException nfe)
1157 {
1158 LOG.error("BrowserTool: Could not parse browser version for User-Agent: "+userAgent,nfe);
1159 }
1160 }
1161
1162
1163 if (test("firefox"))
1164 {
1165 Matcher fx = firefoxVersion.matcher(userAgent);
1166 if (fx.find())
1167 {
1168 version = fx.group(1);
1169 try
1170 {
1171 majorVersion = Integer.valueOf(fx.group(2));
1172 String minor = fx.group(3);
1173 if (minor.startsWith("0"))
1174 {
1175 minorVersion = 0;
1176 }
1177 else
1178 {
1179 minorVersion = Integer.valueOf(minor);
1180 }
1181 }
1182 catch (NumberFormatException nfe)
1183 {
1184 LOG.error("BrowserTool: Could not parse browser version for User-Agent: "+userAgent,nfe);
1185 }
1186 }
1187 }
1188
1189
1190 else if (test("compatible"))
1191 {
1192 Matcher ie = ieVersion.matcher(userAgent);
1193
1194 if (ie.find())
1195 {
1196 version = ie.group(1);
1197 try
1198 {
1199 majorVersion = Integer.valueOf(ie.group(2));
1200 String minor = ie.group(3);
1201 if (minor.startsWith("0"))
1202 {
1203 minorVersion = 0;
1204 }
1205 else
1206 {
1207 minorVersion = Integer.valueOf(minor);
1208 }
1209 }
1210 catch (NumberFormatException nfe)
1211 {
1212 LOG.error("BrowserTool: Could not parse browser version for User-Agent: "+userAgent,nfe);
1213 }
1214 }
1215 }
1216
1217
1218 else if (getSafari())
1219 {
1220 Matcher safari = safariVersion.matcher(userAgent);
1221 if (safari.find())
1222 {
1223 version = safari.group(1);
1224 try
1225 {
1226 int sv = Integer.valueOf(safari.group(2));
1227 majorVersion = sv / 100;
1228 minorVersion = sv % 100;
1229 }
1230 catch (NumberFormatException nfe)
1231 {
1232 LOG.error("BrowserTool: Could not parse browser version for User-Agent: "+userAgent,nfe);
1233 }
1234 }
1235 }
1236
1237
1238 else if (getGecko() && getNetscape() && test("netscape"))
1239 {
1240 Matcher netscape = mozillaVersion.matcher(userAgent);
1241 if (netscape.find())
1242 {
1243 version = netscape.group(1);
1244 try
1245 {
1246 majorVersion = Integer.valueOf(netscape.group(2));
1247 String minor = netscape.group(3);
1248 if (minor.startsWith("0"))
1249 {
1250 minorVersion = 0;
1251 }
1252 else
1253 {
1254 minorVersion = Integer.valueOf(minor);
1255 }
1256 }
1257 catch (NumberFormatException nfe)
1258 {
1259 LOG.error("BrowserTool: Could not parse browser version for User-Agent: "+userAgent,nfe);
1260 }
1261 }
1262 }
1263
1264
1265 if (version == null)
1266 {
1267 Matcher mv = fallbackVersion.matcher(userAgent);
1268 if (mv.find())
1269 {
1270 version = mv.group(1);
1271 try
1272 {
1273 majorVersion = Integer.valueOf(version);
1274 minorVersion = 0;
1275 }
1276 catch (NumberFormatException nfe)
1277 {
1278 LOG.error("BrowserTool: Could not parse browser version for User-Agent: "+userAgent,nfe);
1279 }
1280 }
1281 }
1282
1283
1284 if (getGecko())
1285 {
1286 Matcher g = Pattern.compile(
1287 "\\([^)]*rv:(([\\d]*)\\.([\\d]*).*?)\\)"
1288 ).matcher(userAgent);
1289 if (g.find())
1290 {
1291 geckoVersion = g.group(1);
1292 try
1293 {
1294 geckoMajorVersion = Integer.valueOf(g.group(2));
1295 String minor = g.group(3);
1296 if (minor.startsWith("0"))
1297 {
1298 geckoMinorVersion = 0;
1299 }
1300 else
1301 {
1302 geckoMinorVersion = Integer.valueOf(minor);
1303 }
1304 }
1305 catch (NumberFormatException nfe)
1306 {
1307 LOG.error("BrowserTool: Could not parse browser version for User-Agent: "+userAgent,nfe);
1308 }
1309 }
1310 }
1311 }
1312 catch (PatternSyntaxException pse)
1313 {
1314 LOG.error("BrowserTool: Could not parse browser version for User-Agent: "+userAgent,pse);
1315 }
1316 }
1317
1318 private void parseAcceptLanguage()
1319 {
1320 if(languageRangesByQuality != null)
1321 {
1322
1323 return;
1324 }
1325
1326 languageRangesByQuality = new TreeMap<Float,List<String>>();
1327 StringTokenizer languageTokenizer = new StringTokenizer(acceptLanguage, ",");
1328 while (languageTokenizer.hasMoreTokens())
1329 {
1330 String language = languageTokenizer.nextToken().trim();
1331 int qValueIndex = language.indexOf(';');
1332 if(qValueIndex == -1)
1333 {
1334 language = language.replace('-','_');
1335 List<String> l = languageRangesByQuality.get(1.0f);
1336 if(l == null)
1337 {
1338 l = new ArrayList<String>();
1339 languageRangesByQuality.put(1.0f,l);
1340 }
1341 l.add(language);
1342 }
1343 else
1344 {
1345 String code = language.substring(0,qValueIndex).trim().replace('-','_');
1346 String qval = language.substring(qValueIndex + 1).trim();
1347 if("*".equals(qval))
1348 {
1349 starLanguageRange = code;
1350 }
1351 else
1352 {
1353 Matcher m = quality.matcher(qval);
1354 if(m.matches())
1355 {
1356 Float q = Float.valueOf(m.group(1));
1357 List<String> al = languageRangesByQuality.get(q);
1358 if(al == null)
1359 {
1360 al = new ArrayList<String>();
1361 languageRangesByQuality.put(q,al);
1362 }
1363 al.add(code);
1364 }
1365 else
1366 {
1367 LOG.error("BrowserTool: could not parse language quality value: "+language);
1368 }
1369 }
1370 }
1371 }
1372 }
1373
1374 private String filterLanguageTag(String languageTag)
1375 {
1376 languageTag = languageTag.replace('-','_');
1377 if(languagesFilter == null) return languageTag;
1378 if(languagesFilter.contains(languageTag)) return languageTag;
1379 if(languageTag.contains("_"))
1380 {
1381 String[] parts = languageTag.split("_");
1382 if(languagesFilter.contains(parts[0])) return parts[0];
1383 }
1384 return null;
1385 }
1386 }