/*
Copyright (c) 2003 eInnovation Inc. All rights reserved
This library is free software; you can redistribute it and/or modify it under the terms
of the GNU Lesser General Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
*/
package com.openedit.web;
import java.util.Locale;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
/**
* This interface represents a particular type of browser.
*
* @author cburkey
*/
public class Browser
{
public static final int UNKNOWN_BROWSER = 0;
public static final int MSIE_BROWSER = 1;
public static final int GECKO_BROWSER = 2;
public static final int NETSCAPE_BROWSER = 3;
public static final int CHROME_BROWSER = 4;
public static final int WEBKIT_BROWSER = 5;
public static final int OPERA_BROWSER = 7;
public static final int TEXT_BROWSER = 8;
protected int fieldBrowserType = UNKNOWN_BROWSER;
public static final int IE_EDIT_WIDTH = 83; // percentage width of edit iframe in IE
public static final int MOZILLA_EDIT_WIDTH = 100; // percentage width of edit iframe in Mozilla
protected int fieldMajorVersion = 0;
protected String fieldMinorVersion = "";
protected String fieldUserAgent;
protected String fieldVersion = "";
protected Locale fieldLocale;
protected HttpServletRequest fieldHttpServletRequest;
public Browser(String inUserAgent)
{
fieldUserAgent = inUserAgent;
parseUserAgent();
}
/**
* Retrieve the browser type.
*
* @return One of the <code>BROWSER</code> constants
*/
public int getBrowserType()
{
return fieldBrowserType;
}
/**
* Determine if the browser is a Microsoft browser.
*
* @return
*/
public boolean isMSIE()
{
return (getBrowserType() == MSIE_BROWSER);
}
/**
* Retrieve the major version (if one could be found).
*
* @return
*/
public int getMajorVersion()
{
return fieldMajorVersion;
}
/**
* Retrieve the minor version (if one could be found).
*
* @return
*/
public String getMinorVersion()
{
return fieldMinorVersion;
}
/**
* Determine whether the browser is a Mozilla derivative (including Netscape 6 and 7).
*
* @return
*/
public boolean isGecko()
{
return (getBrowserType() == GECKO_BROWSER);
}
public boolean isHtml5VideoOnly()
{
return (getBrowserType() == WEBKIT_BROWSER);
}
public boolean isHtml5Browser()
{
if ( isMSIE() )
{
int major = getMajorVersion();
if( major != 0 && major < 9)
{
return false;
}
}
return true;
}
/**
* Retrieve the user agent string that we used to determine the information in this browser.
*
* @return
*/
public String getUserAgent()
{
return fieldUserAgent;
}
/**
* Retrieve the browser version.
*
* @return
*/
public String getVersion()
{
return fieldVersion;
}
/**
* FIXME: This is a temporary method needed because Velocity can't handle static fields (it
* would seem). This should disappear when we fix bug WSP35.
*
* @return
*/
public boolean isXMLEditorCompatible()
{
return (getBrowserType() == GECKO_BROWSER) ||
((getBrowserType() == MSIE_BROWSER) &&
(getVersion().compareTo("5.5") >= 0));
}
protected void setBrowserType(int inBrowserType)
{
fieldBrowserType = inBrowserType;
}
protected void setMajorVersion(int inMajorVersion)
{
fieldMajorVersion = inMajorVersion;
}
protected void setMajorVersion(String inMajorVersion)
{
if( inMajorVersion != null && inMajorVersion.length() > 0 )
{
try
{
fieldMajorVersion = Integer.parseInt(inMajorVersion);
}
catch( NumberFormatException ex )
{
//Fail?
}
}
}
protected void setMinorVersion(String inMinorVersion)
{
fieldMinorVersion = inMinorVersion;
}
protected void setVersion(String inVersion)
{
fieldVersion = inVersion;
}
protected void parseUserAgent()
{
//Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; en-US)
//Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3) Gecko/20100423 Ubuntu/10.04 (lucid) Firefox/3.6.3
//Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10
if (getUserAgent() == null)
{
setBrowserType(UNKNOWN_BROWSER);
return;
}
String[] details = getUserAgent().split(" ");
int found = UNKNOWN_BROWSER;
//start at the end and work upwards
for (int j = details.length - 1; j >= 0; j--)
{
String browser = details[j].trim();
found = findBrowser(browser);
if( found != UNKNOWN_BROWSER)
{
//get the version numbers and break out
setBrowserType(found);
if( !browser.contains("/") && j < details.length -1)
{
browser = browser + "/" + details[j+1];
}
setVersions(browser);
return;
}
}
//Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25
if( getUserAgent().contains("AppleWebKit"))
{
setBrowserType(WEBKIT_BROWSER);
}
}
protected void setVersions(String inBrowser)
{
// # Try to get version info out of leftover stuff
int split = inBrowser.indexOf("/");
if( split > -1 )
{
String version = inBrowser.substring(split + 1);
version = extractNumber(version);
setVersion(version);
int j = getVersion().indexOf(".");
if (j >= 0)
{
setMajorVersion(getVersion().substring(0, j));
int k = getVersion().indexOf(".", j + 1);
if (k < 0)
{
k = getVersion().length();
}
setMinorVersion(getVersion().substring(j + 1, k));
}
else
{
setMajorVersion(getVersion());
setMinorVersion("0");
}
}
else
{
//look for any version numbers?
}
}
protected String extractNumber(String inVersion)
{
StringBuffer out = new StringBuffer(inVersion.length());
boolean founddot = false;
for (int i = 0; i < inVersion.length(); i++)
{
char c = inVersion.charAt(i);
if( Character.isDigit(c) )
{
out.append(c);
}
else if( founddot == false && c == '.' )
{
founddot = true; //one dot only please
out.append(c);
}
}
String result = out.toString().toLowerCase();
return result;
}
private int findBrowser(String browVer)
{
//from more specific to more generic
if( browVer.startsWith("("))
{
browVer = browVer.substring(1);
}
if (browVer.startsWith("Firefox"))
{
return GECKO_BROWSER;
}
if (browVer.startsWith("Safari") )
{
return WEBKIT_BROWSER;
}
else if (browVer.startsWith("Gecko"))
{
return GECKO_BROWSER;
}
else if (browVer.startsWith("Lynx"))
{
return TEXT_BROWSER;
}
else if (browVer.startsWith("MSIE"))
{
return MSIE_BROWSER;
}
else if (browVer.startsWith("Opera"))
{
return OPERA_BROWSER;
}
else if (browVer.startsWith("Mozilla"))
{
return NETSCAPE_BROWSER;
}
return UNKNOWN_BROWSER;
}
public int getEditWidth()
{
if ( getBrowserType() == MSIE_BROWSER )
{
return IE_EDIT_WIDTH;
}
else
{
return MOZILLA_EDIT_WIDTH;
}
}
public Locale getLocale()
{
return fieldLocale;
}
public void setLocale(Locale inLocale)
{
fieldLocale = inLocale;
}
public String getCookieListing()
{
if( fieldHttpServletRequest == null)
{
return null;
}
StringBuffer all = new StringBuffer();
Cookie[] cookies = getHttpServletRequest().getCookies();
for (int i = 0; i < cookies.length; i++)
{
all.append( cookies[i].getName());
all.append('=');
all.append(cookies[i].getValue());
all.append(';');
}
return all.toString();
}
public HttpServletRequest getHttpServletRequest()
{
return fieldHttpServletRequest;
}
public void setHttpServletRequest(HttpServletRequest inHttpServletRequest)
{
fieldHttpServletRequest = inHttpServletRequest;
}
}