001: package org.apache.turbine.util;
002:
003: /*
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: /**
023: * This class parses the user agent string and sets javasciptOK and
024: * cssOK following the rules described below. If you want to check
025: * for specific browsers/versions then use this class to parse the
026: * user agent string and use the accessor methods in this class.
027: *
028: * JavaScriptOK means that the browser understands JavaScript on the
029: * same level the Navigator 3 does. Specifically, it can use named
030: * images. This allows easier rollovers. If a browser doesn't do
031: * this (Nav 2 or MSIE 3), then we just assume it can't do any
032: * JavaScript. Referencing images by load order is too hard to
033: * maintain.
034: *
035: * CSSOK is kind of sketchy in that Nav 4 and MSIE work differently,
036: * but they do seem to have most of the functionality. MSIE 4 for the
037: * Mac has buggy CSS support, so we let it do JavaScript, but no CSS.
038: *
039: * Ported from Leon's PHP code at
040: * http://www.working-dogs.com/freetrade by Frank.
041: *
042: * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
043: * @author <a href="mailto:leon@clearink.com">Leon Atkisnon</a>
044: * @author <a href="mailto:mospaw@polk-county.com">Chris Mospaw</a>
045: * @author <a href="mailto:bgriffin@cddb.com">Benjamin Elijah Griffin</a>
046: * @version $Id: BrowserDetector.java 534527 2007-05-02 16:10:59Z tv $
047: */
048: public class BrowserDetector {
049: public static final String MSIE = "MSIE";
050: public static final String OPERA = "Opera";
051: public static final String MOZILLA = "Mozilla";
052:
053: public static final String WINDOWS = "Windows";
054: public static final String UNIX = "Unix";
055: public static final String MACINTOSH = "Macintosh";
056:
057: /** The user agent string. */
058: private String userAgentString = "";
059:
060: /** The browser name specified in the user agent string. */
061: private String browserName = "";
062:
063: /**
064: * The browser version specified in the user agent string. If we
065: * can't parse the version just assume an old browser.
066: */
067: private float browserVersion = (float) 1.0;
068:
069: /**
070: * The browser platform specified in the user agent string.
071: */
072: private String browserPlatform = "unknown";
073:
074: /** Whether or not javascript works in this browser. */
075: private boolean javascriptOK = false;
076:
077: /** Whether or not CSS works in this browser. */
078: private boolean cssOK = false;
079:
080: /** Whether or not file upload works in this browser. */
081: private boolean fileUploadOK = false;
082:
083: /**
084: * Constructor used to initialize this class.
085: *
086: * @param userAgentString A String with the user agent field.
087: */
088: public BrowserDetector(String userAgentString) {
089: this .userAgentString = userAgentString;
090: parse();
091: }
092:
093: /**
094: * Constructor used to initialize this class.
095: *
096: * @param data The Turbine RunData object.
097: */
098: public BrowserDetector(RunData data) {
099: this .userAgentString = data.getUserAgent();
100: parse();
101: }
102:
103: /**
104: * Whether or not CSS works in this browser.
105: *
106: * @return True if CSS works in this browser.
107: */
108: public boolean isCssOK() {
109: return cssOK;
110: }
111:
112: /**
113: * Whether or not file upload works in this browser.
114: *
115: * @return True if file upload works in this browser.
116: */
117: public boolean isFileUploadOK() {
118: return fileUploadOK;
119: }
120:
121: /**
122: * Whether or not Javascript works in this browser.
123: *
124: * @return True if Javascript works in this browser.
125: */
126: public boolean isJavascriptOK() {
127: return javascriptOK;
128: }
129:
130: /**
131: * The browser name specified in the user agent string.
132: *
133: * @return A String with the browser name.
134: */
135: public String getBrowserName() {
136: return browserName;
137: }
138:
139: /**
140: * The browser platform specified in the user agent string.
141: *
142: * @return A String with the browser platform.
143: */
144: public String getBrowserPlatform() {
145: return browserPlatform;
146: }
147:
148: /**
149: * The browser version specified in the user agent string.
150: *
151: * @return A String with the browser version.
152: */
153: public float getBrowserVersion() {
154: return browserVersion;
155: }
156:
157: /**
158: * The user agent string for this class.
159: *
160: * @return A String with the user agent.
161: */
162: public String getUserAgentString() {
163: return userAgentString;
164: }
165:
166: /**
167: * Helper method to initialize this class.
168: */
169: private void parse() {
170: int versionStartIndex = userAgentString.indexOf("/");
171: int versionEndIndex = userAgentString.indexOf(" ");
172:
173: // Get the browser name and version.
174: browserName = userAgentString.substring(0, versionStartIndex);
175: try {
176: // Not all user agents will have a space in the reported
177: // string.
178: String agentSubstring = null;
179: if (versionEndIndex < 0) {
180: agentSubstring = userAgentString
181: .substring(versionStartIndex + 1);
182: } else {
183: agentSubstring = userAgentString.substring(
184: versionStartIndex + 1, versionEndIndex);
185: }
186: browserVersion = toFloat(agentSubstring);
187: } catch (NumberFormatException e) {
188: // Just use the default value.
189: }
190:
191: // MSIE lies about its name. Of course...
192: if (userAgentString.indexOf(MSIE) != -1) {
193: // Ex: Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)
194: versionStartIndex = (userAgentString.indexOf(MSIE)
195: + MSIE.length() + 1);
196: versionEndIndex = userAgentString.indexOf(";",
197: versionStartIndex);
198:
199: browserName = MSIE;
200: try {
201: browserVersion = toFloat(userAgentString.substring(
202: versionStartIndex, versionEndIndex));
203: } catch (NumberFormatException e) {
204: // Just use the default value.
205: }
206:
207: // PHP code
208: // $Browser_Name = "MSIE";
209: // $Browser_Version = strtok("MSIE");
210: // $Browser_Version = strtok(" ");
211: // $Browser_Version = strtok(";");
212: }
213:
214: // Opera isn't completely honest, either...
215: // Modificaton by Chris Mospaw <mospaw@polk-county.com>
216: if (userAgentString.indexOf(OPERA) != -1) {
217: //Ex: Mozilla/4.0 (Windows NT 4.0;US) Opera 3.61 [en]
218: // Ex: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 8.02
219: versionStartIndex = (userAgentString.indexOf(OPERA)
220: + OPERA.length() + 1);
221: versionEndIndex = userAgentString.indexOf(" ",
222: versionStartIndex);
223: if (versionEndIndex == -1) {
224: versionEndIndex = userAgentString.length();
225: }
226:
227: browserName = OPERA;
228: try {
229: browserVersion = toFloat(userAgentString.substring(
230: versionStartIndex, versionEndIndex));
231: } catch (NumberFormatException e) {
232: // Just use the default value.
233: }
234:
235: // PHP code
236: // $Browser_Name = "Opera";
237: // $Browser_Version = strtok("Opera");
238: // $Browser_Version = strtok("/");
239: // $Browser_Version = strtok(";");
240: }
241:
242: // Try to figure out what platform.
243: if ((userAgentString.indexOf("Windows") != -1)
244: || (userAgentString.indexOf("WinNT") != -1)
245: || (userAgentString.indexOf("Win98") != -1)
246: || (userAgentString.indexOf("Win95") != -1)) {
247: browserPlatform = WINDOWS;
248: }
249:
250: if (userAgentString.indexOf("Mac") != -1) {
251: browserPlatform = MACINTOSH;
252: }
253:
254: if (userAgentString.indexOf("X11") != -1) {
255: browserPlatform = UNIX;
256: }
257:
258: if (browserPlatform == WINDOWS) {
259: if (browserName.equals(MOZILLA)) {
260: if (browserVersion >= 3.0) {
261: javascriptOK = true;
262: fileUploadOK = true;
263: }
264: if (browserVersion >= 4.0) {
265: cssOK = true;
266: }
267: } else if (browserName == MSIE) {
268: if (browserVersion >= 4.0) {
269: javascriptOK = true;
270: fileUploadOK = true;
271: cssOK = true;
272: }
273: } else if (browserName == OPERA) {
274: if (browserVersion >= 3.0) {
275: javascriptOK = true;
276: fileUploadOK = true;
277: cssOK = true;
278: }
279: }
280: } else if (browserPlatform == MACINTOSH) {
281: if (browserName.equals(MOZILLA)) {
282: if (browserVersion >= 3.0) {
283: javascriptOK = true;
284: fileUploadOK = true;
285: }
286: if (browserVersion >= 4.0) {
287: cssOK = true;
288: }
289: } else if (browserName == MSIE) {
290: if (browserVersion >= 4.0) {
291: javascriptOK = true;
292: fileUploadOK = true;
293: }
294: if (browserVersion > 4.0) {
295: cssOK = true;
296: }
297: }
298: } else if (browserPlatform == UNIX) {
299: if (browserName.equals(MOZILLA)) {
300: if (browserVersion >= 3.0) {
301: javascriptOK = true;
302: fileUploadOK = true;
303: }
304: if (browserVersion >= 4.0) {
305: cssOK = true;
306: }
307: }
308: }
309: }
310:
311: /**
312: * Helper method to convert String to a float.
313: *
314: * @param s A String.
315: * @return The String converted to float.
316: */
317: private static final float toFloat(String s) {
318: return Float.valueOf(s).floatValue();
319: }
320:
321: }
|