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 615328 2008-01-25 20:25:05Z tv $ 047 */ 048 public class BrowserDetector 049 { 050 public static final String MSIE = "MSIE"; 051 public static final String OPERA = "Opera"; 052 public static final String MOZILLA = "Mozilla"; 053 054 public static final String WINDOWS = "Windows"; 055 public static final String UNIX = "Unix"; 056 public static final String MACINTOSH = "Macintosh"; 057 058 /** The user agent string. */ 059 private String userAgentString = ""; 060 061 /** The browser name specified in the user agent string. */ 062 private String browserName = ""; 063 064 /** 065 * The browser version specified in the user agent string. If we 066 * can't parse the version just assume an old browser. 067 */ 068 private float browserVersion = (float) 1.0; 069 070 /** 071 * The browser platform specified in the user agent string. 072 */ 073 private String browserPlatform = "unknown"; 074 075 /** Whether or not javascript works in this browser. */ 076 private boolean javascriptOK = false; 077 078 /** Whether or not CSS works in this browser. */ 079 private boolean cssOK = false; 080 081 /** Whether or not file upload works in this browser. */ 082 private boolean fileUploadOK = false; 083 084 /** 085 * Constructor used to initialize this class. 086 * 087 * @param userAgentString A String with the user agent field. 088 */ 089 public BrowserDetector(String userAgentString) 090 { 091 this.userAgentString = userAgentString; 092 parse(); 093 } 094 095 /** 096 * Constructor used to initialize this class. 097 * 098 * @param data The Turbine RunData object. 099 */ 100 public BrowserDetector(RunData data) 101 { 102 this.userAgentString = data.getUserAgent(); 103 parse(); 104 } 105 106 /** 107 * Whether or not CSS works in this browser. 108 * 109 * @return True if CSS works in this browser. 110 */ 111 public boolean isCssOK() 112 { 113 return cssOK; 114 } 115 116 /** 117 * Whether or not file upload works in this browser. 118 * 119 * @return True if file upload works in this browser. 120 */ 121 public boolean isFileUploadOK() 122 { 123 return fileUploadOK; 124 } 125 126 /** 127 * Whether or not Javascript works in this browser. 128 * 129 * @return True if Javascript works in this browser. 130 */ 131 public boolean isJavascriptOK() 132 { 133 return javascriptOK; 134 } 135 136 /** 137 * The browser name specified in the user agent string. 138 * 139 * @return A String with the browser name. 140 */ 141 public String getBrowserName() 142 { 143 return browserName; 144 } 145 146 /** 147 * The browser platform specified in the user agent string. 148 * 149 * @return A String with the browser platform. 150 */ 151 public String getBrowserPlatform() 152 { 153 return browserPlatform; 154 } 155 156 /** 157 * The browser version specified in the user agent string. 158 * 159 * @return A String with the browser version. 160 */ 161 public float getBrowserVersion() 162 { 163 return browserVersion; 164 } 165 166 /** 167 * The user agent string for this class. 168 * 169 * @return A String with the user agent. 170 */ 171 public String getUserAgentString() 172 { 173 return userAgentString; 174 } 175 176 /** 177 * Helper method to initialize this class. 178 */ 179 private void parse() 180 { 181 int versionStartIndex = userAgentString.indexOf("/"); 182 int versionEndIndex = userAgentString.indexOf(" "); 183 184 // Get the browser name and version. 185 browserName = userAgentString.substring(0, versionStartIndex); 186 try 187 { 188 // Not all user agents will have a space in the reported 189 // string. 190 String agentSubstring = null; 191 if (versionEndIndex < 0) 192 { 193 agentSubstring 194 = userAgentString.substring(versionStartIndex + 1); 195 } 196 else 197 { 198 agentSubstring = userAgentString 199 .substring(versionStartIndex + 1, versionEndIndex); 200 } 201 browserVersion = toFloat(agentSubstring); 202 } 203 catch (NumberFormatException e) 204 { 205 // Just use the default value. 206 } 207 208 // MSIE lies about its name. Of course... 209 if (userAgentString.indexOf(MSIE) != -1) 210 { 211 // Ex: Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt) 212 versionStartIndex = (userAgentString.indexOf(MSIE) 213 + MSIE.length() + 1); 214 versionEndIndex = userAgentString.indexOf(";", versionStartIndex); 215 216 browserName = MSIE; 217 try 218 { 219 browserVersion = toFloat(userAgentString 220 .substring(versionStartIndex, versionEndIndex)); 221 } 222 catch (NumberFormatException e) 223 { 224 // Just use the default value. 225 } 226 227 // PHP code 228 // $Browser_Name = "MSIE"; 229 // $Browser_Version = strtok("MSIE"); 230 // $Browser_Version = strtok(" "); 231 // $Browser_Version = strtok(";"); 232 } 233 234 // Opera isn't completely honest, either... 235 // Modificaton by Chris Mospaw <mospaw@polk-county.com> 236 if (userAgentString.indexOf(OPERA) != -1) 237 { 238 // Ex: Mozilla/4.0 (Windows NT 4.0;US) Opera 3.61 [en] 239 // Ex: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 8.02 240 versionStartIndex = (userAgentString.indexOf(OPERA) 241 + OPERA.length() + 1); 242 versionEndIndex = userAgentString.indexOf(" ", versionStartIndex); 243 if (versionEndIndex == -1) 244 { 245 versionEndIndex = userAgentString.length(); 246 } 247 248 browserName = OPERA; 249 try 250 { 251 browserVersion = toFloat(userAgentString 252 .substring(versionStartIndex, versionEndIndex)); 253 } 254 catch (NumberFormatException e) 255 { 256 // Just use the default value. 257 } 258 259 // PHP code 260 // $Browser_Name = "Opera"; 261 // $Browser_Version = strtok("Opera"); 262 // $Browser_Version = strtok("/"); 263 // $Browser_Version = strtok(";"); 264 } 265 266 267 // Try to figure out what platform. 268 if ((userAgentString.indexOf("Windows") != -1) 269 || (userAgentString.indexOf("WinNT") != -1) 270 || (userAgentString.indexOf("Win98") != -1) 271 || (userAgentString.indexOf("Win95") != -1)) 272 { 273 browserPlatform = WINDOWS; 274 } 275 276 if (userAgentString.indexOf("Mac") != -1) 277 { 278 browserPlatform = MACINTOSH; 279 } 280 281 if (userAgentString.indexOf("X11") != -1) 282 { 283 browserPlatform = UNIX; 284 } 285 286 if (browserPlatform == WINDOWS) 287 { 288 if (browserName.equals(MOZILLA)) 289 { 290 if (browserVersion >= 3.0) 291 { 292 javascriptOK = true; 293 fileUploadOK = true; 294 } 295 if (browserVersion >= 4.0) 296 { 297 cssOK = true; 298 } 299 } 300 else if (browserName == MSIE) 301 { 302 if (browserVersion >= 4.0) 303 { 304 javascriptOK = true; 305 fileUploadOK = true; 306 cssOK = true; 307 } 308 } 309 else if (browserName == OPERA) 310 { 311 if (browserVersion >= 3.0) 312 { 313 javascriptOK = true; 314 fileUploadOK = true; 315 cssOK = true; 316 } 317 } 318 } 319 else if (browserPlatform == MACINTOSH) 320 { 321 if (browserName.equals(MOZILLA)) 322 { 323 if (browserVersion >= 3.0) 324 { 325 javascriptOK = true; 326 fileUploadOK = true; 327 } 328 if (browserVersion >= 4.0) 329 { 330 cssOK = true; 331 } 332 } 333 else if (browserName == MSIE) 334 { 335 if (browserVersion >= 4.0) 336 { 337 javascriptOK = true; 338 fileUploadOK = true; 339 } 340 if (browserVersion > 4.0) 341 { 342 cssOK = true; 343 } 344 } 345 } 346 else if (browserPlatform == UNIX) 347 { 348 if (browserName.equals(MOZILLA)) 349 { 350 if (browserVersion >= 3.0) 351 { 352 javascriptOK = true; 353 fileUploadOK = true; 354 } 355 if (browserVersion >= 4.0) 356 { 357 cssOK = true; 358 } 359 } 360 } 361 } 362 363 /** 364 * Helper method to convert String to a float. 365 * 366 * @param s A String. 367 * @return The String converted to float. 368 */ 369 private static final float toFloat(String s) 370 { 371 return Float.valueOf(s).floatValue(); 372 } 373 374 }