001package 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 1706239 2015-10-01 13:18:35Z tv $ 047 */ 048public class BrowserDetector 049{ 050 /** Internet Explorer */ 051 public static final String MSIE = "MSIE"; 052 /** Opera */ 053 public static final String OPERA = "Opera"; 054 /** Mozilla, Firefox and friends */ 055 public static final String MOZILLA = "Mozilla"; 056 057 /** Running on Windows */ 058 public static final String WINDOWS = "Windows"; 059 /** Running on Unix */ 060 public static final String UNIX = "Unix"; 061 /** Running on Mac OS X */ 062 public static final String MACINTOSH = "Macintosh"; 063 064 /** The user agent string. */ 065 private String userAgentString = ""; 066 067 /** The browser name specified in the user agent string. */ 068 private String browserName = ""; 069 070 /** 071 * The browser version specified in the user agent string. If we 072 * can't parse the version just assume an old browser. 073 */ 074 private float browserVersion = (float) 1.0; 075 076 /** 077 * The browser platform specified in the user agent string. 078 */ 079 private String browserPlatform = "unknown"; 080 081 /** Whether or not javascript works in this browser. */ 082 private boolean javascriptOK = false; 083 084 /** Whether or not CSS works in this browser. */ 085 private boolean cssOK = false; 086 087 /** Whether or not file upload works in this browser. */ 088 private boolean fileUploadOK = false; 089 090 /** 091 * Constructor used to initialize this class. 092 * 093 * @param userAgentString A String with the user agent field. 094 */ 095 public BrowserDetector(String userAgentString) 096 { 097 this.userAgentString = userAgentString; 098 parse(); 099 } 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}