1 package org.apache.turbine.util;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 /**
23 * This class parses the user agent string and sets javasciptOK and
24 * cssOK following the rules described below. If you want to check
25 * for specific browsers/versions then use this class to parse the
26 * user agent string and use the accessor methods in this class.
27 *
28 * JavaScriptOK means that the browser understands JavaScript on the
29 * same level the Navigator 3 does. Specifically, it can use named
30 * images. This allows easier rollovers. If a browser doesn't do
31 * this (Nav 2 or MSIE 3), then we just assume it can't do any
32 * JavaScript. Referencing images by load order is too hard to
33 * maintain.
34 *
35 * CSSOK is kind of sketchy in that Nav 4 and MSIE work differently,
36 * but they do seem to have most of the functionality. MSIE 4 for the
37 * Mac has buggy CSS support, so we let it do JavaScript, but no CSS.
38 *
39 * Ported from Leon's PHP code at
40 * http://www.working-dogs.com/freetrade by Frank.
41 *
42 * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
43 * @author <a href="mailto:leon@clearink.com">Leon Atkisnon</a>
44 * @author <a href="mailto:mospaw@polk-county.com">Chris Mospaw</a>
45 * @author <a href="mailto:bgriffin@cddb.com">Benjamin Elijah Griffin</a>
46 * @version $Id: BrowserDetector.java 1706239 2015-10-01 13:18:35Z tv $
47 */
48 public class BrowserDetector
49 {
50 /** Internet Explorer */
51 public static final String MSIE = "MSIE";
52 /** Opera */
53 public static final String OPERA = "Opera";
54 /** Mozilla, Firefox and friends */
55 public static final String MOZILLA = "Mozilla";
56
57 /** Running on Windows */
58 public static final String WINDOWS = "Windows";
59 /** Running on Unix */
60 public static final String UNIX = "Unix";
61 /** Running on Mac OS X */
62 public static final String MACINTOSH = "Macintosh";
63
64 /** The user agent string. */
65 private String userAgentString = "";
66
67 /** The browser name specified in the user agent string. */
68 private String browserName = "";
69
70 /**
71 * The browser version specified in the user agent string. If we
72 * can't parse the version just assume an old browser.
73 */
74 private float browserVersion = (float) 1.0;
75
76 /**
77 * The browser platform specified in the user agent string.
78 */
79 private String browserPlatform = "unknown";
80
81 /** Whether or not javascript works in this browser. */
82 private boolean javascriptOK = false;
83
84 /** Whether or not CSS works in this browser. */
85 private boolean cssOK = false;
86
87 /** Whether or not file upload works in this browser. */
88 private boolean fileUploadOK = false;
89
90 /**
91 * Constructor used to initialize this class.
92 *
93 * @param userAgentString A String with the user agent field.
94 */
95 public BrowserDetector(String userAgentString)
96 {
97 this.userAgentString = userAgentString;
98 parse();
99 }
100
101 /**
102 * Constructor used to initialize this class.
103 *
104 * @param data The Turbine RunData object.
105 */
106 public BrowserDetector(RunData data)
107 {
108 this.userAgentString = data.getUserAgent();
109 parse();
110 }
111
112 /**
113 * Whether or not CSS works in this browser.
114 *
115 * @return True if CSS works in this browser.
116 */
117 public boolean isCssOK()
118 {
119 return cssOK;
120 }
121
122 /**
123 * Whether or not file upload works in this browser.
124 *
125 * @return True if file upload works in this browser.
126 */
127 public boolean isFileUploadOK()
128 {
129 return fileUploadOK;
130 }
131
132 /**
133 * Whether or not Javascript works in this browser.
134 *
135 * @return True if Javascript works in this browser.
136 */
137 public boolean isJavascriptOK()
138 {
139 return javascriptOK;
140 }
141
142 /**
143 * The browser name specified in the user agent string.
144 *
145 * @return A String with the browser name.
146 */
147 public String getBrowserName()
148 {
149 return browserName;
150 }
151
152 /**
153 * The browser platform specified in the user agent string.
154 *
155 * @return A String with the browser platform.
156 */
157 public String getBrowserPlatform()
158 {
159 return browserPlatform;
160 }
161
162 /**
163 * The browser version specified in the user agent string.
164 *
165 * @return A String with the browser version.
166 */
167 public float getBrowserVersion()
168 {
169 return browserVersion;
170 }
171
172 /**
173 * The user agent string for this class.
174 *
175 * @return A String with the user agent.
176 */
177 public String getUserAgentString()
178 {
179 return userAgentString;
180 }
181
182 /**
183 * Helper method to initialize this class.
184 */
185 private void parse()
186 {
187 int versionStartIndex = userAgentString.indexOf("/");
188 int versionEndIndex = userAgentString.indexOf(" ");
189
190 // Get the browser name and version.
191 browserName = userAgentString.substring(0, versionStartIndex);
192 try
193 {
194 // Not all user agents will have a space in the reported
195 // string.
196 String agentSubstring = null;
197 if (versionEndIndex < 0)
198 {
199 agentSubstring
200 = userAgentString.substring(versionStartIndex + 1);
201 }
202 else
203 {
204 agentSubstring = userAgentString
205 .substring(versionStartIndex + 1, versionEndIndex);
206 }
207 browserVersion = toFloat(agentSubstring);
208 }
209 catch (NumberFormatException e)
210 {
211 // Just use the default value.
212 }
213
214 // MSIE lies about its name. Of course...
215 if (userAgentString.indexOf(MSIE) != -1)
216 {
217 // Ex: Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)
218 versionStartIndex = (userAgentString.indexOf(MSIE)
219 + MSIE.length() + 1);
220 versionEndIndex = userAgentString.indexOf(";", versionStartIndex);
221
222 browserName = MSIE;
223 try
224 {
225 browserVersion = toFloat(userAgentString
226 .substring(versionStartIndex, versionEndIndex));
227 }
228 catch (NumberFormatException e)
229 {
230 // Just use the default value.
231 }
232
233 // PHP code
234 // $Browser_Name = "MSIE";
235 // $Browser_Version = strtok("MSIE");
236 // $Browser_Version = strtok(" ");
237 // $Browser_Version = strtok(";");
238 }
239
240 // Opera isn't completely honest, either...
241 // Modificaton by Chris Mospaw <mospaw@polk-county.com>
242 if (userAgentString.indexOf(OPERA) != -1)
243 {
244 // Ex: Mozilla/4.0 (Windows NT 4.0;US) Opera 3.61 [en]
245 // Ex: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 8.02
246 versionStartIndex = (userAgentString.indexOf(OPERA)
247 + OPERA.length() + 1);
248 versionEndIndex = userAgentString.indexOf(" ", versionStartIndex);
249 if (versionEndIndex == -1)
250 {
251 versionEndIndex = userAgentString.length();
252 }
253
254 browserName = OPERA;
255 try
256 {
257 browserVersion = toFloat(userAgentString
258 .substring(versionStartIndex, versionEndIndex));
259 }
260 catch (NumberFormatException e)
261 {
262 // Just use the default value.
263 }
264
265 // PHP code
266 // $Browser_Name = "Opera";
267 // $Browser_Version = strtok("Opera");
268 // $Browser_Version = strtok("/");
269 // $Browser_Version = strtok(";");
270 }
271
272
273 // Try to figure out what platform.
274 if ((userAgentString.indexOf("Windows") != -1)
275 || (userAgentString.indexOf("WinNT") != -1)
276 || (userAgentString.indexOf("Win98") != -1)
277 || (userAgentString.indexOf("Win95") != -1))
278 {
279 browserPlatform = WINDOWS;
280 }
281
282 if (userAgentString.indexOf("Mac") != -1)
283 {
284 browserPlatform = MACINTOSH;
285 }
286
287 if (userAgentString.indexOf("X11") != -1)
288 {
289 browserPlatform = UNIX;
290 }
291
292 if (browserPlatform == WINDOWS)
293 {
294 if (browserName.equals(MOZILLA))
295 {
296 if (browserVersion >= 3.0)
297 {
298 javascriptOK = true;
299 fileUploadOK = true;
300 }
301 if (browserVersion >= 4.0)
302 {
303 cssOK = true;
304 }
305 }
306 else if (browserName == MSIE)
307 {
308 if (browserVersion >= 4.0)
309 {
310 javascriptOK = true;
311 fileUploadOK = true;
312 cssOK = true;
313 }
314 }
315 else if (browserName == OPERA)
316 {
317 if (browserVersion >= 3.0)
318 {
319 javascriptOK = true;
320 fileUploadOK = true;
321 cssOK = true;
322 }
323 }
324 }
325 else if (browserPlatform == MACINTOSH)
326 {
327 if (browserName.equals(MOZILLA))
328 {
329 if (browserVersion >= 3.0)
330 {
331 javascriptOK = true;
332 fileUploadOK = true;
333 }
334 if (browserVersion >= 4.0)
335 {
336 cssOK = true;
337 }
338 }
339 else if (browserName == MSIE)
340 {
341 if (browserVersion >= 4.0)
342 {
343 javascriptOK = true;
344 fileUploadOK = true;
345 }
346 if (browserVersion > 4.0)
347 {
348 cssOK = true;
349 }
350 }
351 }
352 else if (browserPlatform == UNIX)
353 {
354 if (browserName.equals(MOZILLA))
355 {
356 if (browserVersion >= 3.0)
357 {
358 javascriptOK = true;
359 fileUploadOK = true;
360 }
361 if (browserVersion >= 4.0)
362 {
363 cssOK = true;
364 }
365 }
366 }
367 }
368
369 /**
370 * Helper method to convert String to a float.
371 *
372 * @param s A String.
373 * @return The String converted to float.
374 */
375 private static final float toFloat(String s)
376 {
377 return Float.valueOf(s).floatValue();
378 }
379
380 }