/* **** This file permanently resides at <http://mikaels.net/archives/public/application/javascript/xb/v3.4/detect/xbDetect.3_4_1_0.js>
  
 *	(C) Lars P M <mailto:larspeemm@netscape.net>

 * This script is replacing both "ua.js" and "uax.js" which were being discontinued at version 3.3.4. However, a partly backwards 
   compatible version of this script goes for version 3.4.x of "uax.js". 
 
 * The initial version (3.4.0) of "xbDetect.js" was first published 2008-07-27. 
 * The latest version is named "xbDetect.js" and located in the same directory.
 * This is version 3.4.1, changed 2009-07-18, adding the "khtml" engine and renaming the "applewebkit" engine to "webkit". 
    
 * The script should be safe and fully accurate with JavaScript language versions from 1.1. For documentation, see
 * <http://mikaels.net/records/sitever3.4/meta/xb/detect/>.
 * 
 * **** */

function getVersionLimit(L,sforL,sPV){
//deciding on the end of a version string
eval (sforL);
return sPV;
}

function getVersion(L,sforL,sPV){
//conversion from a version string to a numeric version
eval (sforL);
var Z = 0 , R = new Array('.','_',',','-');
   for (var j=0;j<4;j++){
    var x=R[j];
    if (sPV.indexOf(x) > -1){sPV=sPV.split(x);break}
    else sPV=sPV+'-'
    }
    	var exp     = 1;
   for (var k = 0; k < sPV.length; k++){
    var val = parseInt(sPV[k]);
    if (isNaN(val)) break;
    else {
      	Z += val / exp;
      	exp *= 100;
    	}
    	}
return Math.round(Z*1000000)/1000000;
}

function fOSORCPU(ua){
 //detecting OS or CPU using a relevant part of the ua string

 this.winme= (ua.indexOf("win 9x 4.90")!=-1) || (ua.indexOf("windows me")!=-1);
 this.win2k= (ua.indexOf("windows 2000")!=-1);
 this.winxp= (ua.indexOf("windows xp")!=-1);
 this.winnt= (ua.indexOf("winnt")!=-1) || (ua.indexOf("windows nt")!=-1);
 this.win98= (ua.indexOf("win98")!=-1) || (ua.indexOf("windows 98")!=-1);
 this.win95= (ua.indexOf("win95")!=-1) || (ua.indexOf("windows 95")!=-1);

 if (this.win95 || this.win98 || this.winme) this.xos0='9x'; 
 else if (this.winnt || this.win2k || this.winxp) this.xos0='nt'; 

 else if (ua.indexOf("mac")!=-1 && ((ua.indexOf("68k")!=-1) || 
          (ua.indexOf("68000")!=-1))) this.xos0='68k'; 
 else if (ua.indexOf("mac")!=-1 && ((ua.indexOf("ppc")!=-1) || 
          (ua.indexOf("powerpc")!=-1))) this.xos0='ppc'; 
 else if (ua.indexOf("mac")!=-1 && ((ua.indexOf("intel")!=-1))) this.xos0='x86'; 

 else if (ua.indexOf("unix_system_v")!=-1) this.xos0='unixware'; 
 else if (ua.indexOf("reliantunix")!=-1) this.xos0='reliant'; 
 else if (ua.indexOf("sunos")!=-1) this.xos0='sun'; 
 else if (ua.indexOf("hp-ux")!=-1) this.xos0='hpux'; 
 else if ((ua.indexOf("osf1")!=-1) || 
          (ua.indexOf("dec_alpha")!=-1) || 
          (ua.indexOf("alphaserver")!=-1) || 
          (ua.indexOf("ultrix")!=-1) || 
          (ua.indexOf("alphastation")!=-1)) this.xos0='alpha'; 
 else if (ua.indexOf("sinix")!=-1) this.xos0='sinix'; 
 else if (ua.indexOf("freebsd")!=-1) this.xos0='freebsd'; 
 else if (ua.indexOf("irix") !=-1) this.xos0='irix'; // SGI 
 else if (ua.indexOf("inux")!=-1) this.xos0='linux'; 
 else if (ua.indexOf("aix") !=-1) this.xos0='aix'; // IBM 
 else if ((ua.indexOf("sco")!=-1) || 
               (ua.indexOf("unix_sv")!=-1)) this.xos0='sco'; 
 else if (ua.indexOf("ncr")!=-1) this.xos0='mpras'; 
 else if (ua.indexOf("bsd")!=-1) this.xos0='bsd'; 
 else if (ua.indexOf("dec")!=-1) this.xos0='dec';  

 if (this.xos0=='9x' || this.xos0=='nt') this.xos1='win';
 else if (this.xos0=='68k' || this.xos0=='ppc' || this.xos0=='x86') this.xos1='mac';
 else if ((ua.indexOf("x11")!=-1) || this.xos0) this.xos1='nix';
 else if ((ua.indexOf("os/2")!=-1) || 
          (navigator.appVersion.indexOf("OS/2")!=-1) || 
          (ua.indexOf("ibm-webexplorer")!=-1)) {this.xos0 = 'os2';this.xos1=''} 
 else if ((ua.indexOf("vax")!=-1) || 
          (ua.indexOf("openvms")!=-1)) {this.xos0 = 'vms';this.xos1=''} 
 else if ((ua.indexOf("x86")!=-1)) {this.xos0 = 'x86';this.xos1=''} 
 else {this.xos0='';this.xos1=''}

}

function xbDetectAndAddxbArray()
{ 
  var L = new Array(';',')',' ','(');
  var sforL='for(var l=0;l<4;l++){var q=L[l];if(sPV.indexOf(q)>-1){sPV=sPV.substring(0,sPV.indexOf(q))}}';
  var rv ='', JScript ='', nVersion =0.01, sPVersion ='0.01', sPName =window.navigator.appCodeName;  
  //shorthands
   var uAg = window.navigator.userAgent;
  var appV = window.navigator.appVersion;
  var appN = window.navigator.appName;
    var ua = uAg.toLowerCase();

  navigator['xb'] = new Array(13); navigator.xb[12] = false; //12 is spoofing
  //fallbacks and decision on the browser kinship
  navigator.xb[1] = sPName.toLowerCase(); //1 is engine
  navigator.xb[7] = parseFloat('0'+appV, 10); //7 is devVersion (sub to engine)
  navigator.xb[8] = 0; navigator.xb[5] = ''; //8 is releaseVersion, 5 is prettyVersion
  var h=uAg.indexOf('/'); if (h>-1){ 
  	sPName = uAg.substring(0,h); 
  	var sb = uAg.substring(h+1)+' ';
	navigator.xb[5]=sb.substring(0, sb.indexOf(' '))
  	}
  if (appN == 'Microsoft Internet Explorer') appN = 'MSIE';
  navigator.xb[0] = appN+'/'+parseInt(appV, 10); //0 is kinship

  //identifying JS1.0 browsers
  var nav_js = 0; if (!Array('test')) nav_js = 1.0
  
  //preliminary decision on the browser engine, trying to use navigator.product 
  if (navigator.product) navigator.xb[1] = navigator.product.toLowerCase() 
  if (navigator.productSub) navigator.xb[7] = parseFloat(navigator.productSub.substring(0,8), 10);

  var nav_family; //detecting the families and preparing for pretty names and versions 
  if (ua.indexOf("khtml") != -1 || ua.indexOf("konqueror") != -1 || ua.indexOf("applewebkit") != -1){
  	nav_family='kde'; //KDE products
  	if( ua.indexOf("konqueror") != -1 )
    	{ //Konqueror
          i = ua.indexOf('konqueror');
          sPName = 'konqueror'; 
    	  sPVersion = ua.substring(i+10);
    	}
    	else if( ua.indexOf("omniweb") != -1 )
    	{ //OmniWeb
          sPName = 'omniWeb';
          sPVersion = ua.substring(ua.lastIndexOf('/')+2); 
    	}
    	else if( ua.indexOf('safari/') != -1 )
    	{ //Safari
          sPName = 'safari';
          sPVersion = ua.substring(ua.lastIndexOf('/')+1); 
    	}
  	}
  else if (navigator.xb[1] == 'gecko'){
  	nav_family='gecko'; //Gecko products
    	if (ua.indexOf("galeon") != -1 )
    	{ //Galeon
          sPName = 'galeon';
          sPVersion = ua.substring(ua.indexOf('galeon') + 7);
    	}
    	//according to the proposal at http://www.mozilla.org/build/revised-user-agent-strings.html
    	else if (ua.indexOf('mozilla') != -1 && ua.lastIndexOf('/')-5 != ua.indexOf('gecko') && ua.lastIndexOf('/')-7 != 0)
    	{ //branded browsers based on Mozilla
          var gecko_r = uAg.substring(ua.indexOf('gecko')+6);
          var nPName_begins=getVersionLimit(L,sforL,gecko_r).length;
          sPName = gecko_r.substring(nPName_begins+1,gecko_r.indexOf('/'));
          sPVersion = gecko_r.substring(gecko_r.indexOf('/')+1);
          if (gecko_r.indexOf('/') != gecko_r.lastIndexOf('/') && gecko_r.indexOf('Firefox')!=-1)
	  { //grabbing the second vendor name if 'Firefox' is in the ua
            var nvendor_begins=getVersionLimit(L,sforL,sPVersion).length;
            if (sPVersion.charAt(nvendor_begins+1)=='(' && sPVersion.indexOf(')')>0)
	    	{ // if a VendorComment is applied
	    	  nvendor_begins=sPVersion.indexOf(')');
	    	}
            sPName = sPVersion.substring(nvendor_begins+1,sPVersion.indexOf('/'));
            sPVersion = sPVersion.substring(sPVersion.indexOf('/')+1);
	  }
    	} 
	else if (ua.indexOf("msie") != -1) 
	{ //making version number spoof friendly if the real vendor is unavailable 	
	  navigator.xb[5]=ua.substring(ua.indexOf("msie") + 5, ua.indexOf("msie") + 8)
	} 
  	}
  else if (ua.indexOf('opera') != -1){ //Opera products
  	nav_family='opera'; i = ua.indexOf('opera');
    	sPName    = 'opera';
    	sPVersion = ua.substring(i+6);
    	}
  else if (ua.indexOf('compatible') != -1 && ua.indexOf('msie') != -1 && !navigator.language){
  	nav_family='ie'; i = ua.indexOf('msie'); //Internet Explorer and the Trident engine
    	sPName = 'internet Explorer'; 
    	sPVersion = ua.substring(i+5); 
  	//detecting JScript
    	if (navigator.xb[7] < 4)
    	{ //IE 3
   	  if(nav_js > 0) JScript = '1.0';
    	  else JScript = '2.0';
    	}
    	else
    	{ //IE 4
	  JScript = '3.0';
	  if (typeof(ScriptEngine) =='function'){
	  JScript = ScriptEngineMajorVersion() + ".";
	  JScript += ScriptEngineMinorVersion();
	  }
   	  if (ua.indexOf('netscape') != -1) 
    		{ //Netscape Browser
      		sPName = 'netscape'; 
      		sPVersion = ua.substring(ua.indexOf('netscape')+9);
      		}
    	  else if (ua.indexOf('america online browser') != -1)
    		{ //AOL
    		sPName = 'aOL Explorer';
    		sPVersion = ua.substring(ua.indexOf('rev')+3);
    		}
	}
  	}
  else if (ua.indexOf("icab") != -1 ){
    	sPName = " iCab";
    	sPVersion = ua.substring(ua.indexOf("icab") + 5);
  	}
  else if (ua.indexOf('java') != -1 ){ //java browsers
    	if (ua.indexOf('ice') != -1 )
    	{ // ICEbrowser
    	  sPName = appN;
    	  sPVersion = ua.substring(ua.indexOf('/') + 2);
    	}
    	else if (ua.indexOf('hotjava') != -1 )
    	{ // HotJava
    	  sPName = 'hotJava';
    	}
  	}
  else if (appN == 'Netscape' && (ua.indexOf('spoofer')==-1) && (ua.indexOf('compatible')==-1) && (ua.indexOf('webtv')==-1) && (ua.indexOf('gecko')==-1)){
  	nav_family='nn'; i = ua.lastIndexOf('/'); //Netscape Navigator and Communicator
    	sPName = 'netscape';
    	sPVersion = ua.substring(i+1);
  	}
  else if ((ua.indexOf('compatible') != -1 && ua.indexOf('msie') != -1) || 
           (ua.indexOf('gecko/') != -1)) navigator.xb[12] = true;

  //We need to convert version strings into numbers and a pretty look, thereby calling predefined functions. 
  if (nav_js != 1.0){
	nVersion= getVersion(L,sforL,sPVersion); 
	if (nVersion != 0.01){
	  navigator.xb[5] = getVersionLimit(L,sforL,sPVersion);
	  navigator.xb[8] = nVersion;
	  }
  	//create an internal navigator property (array)
  	navigator._exami = new Array(3); navigator._exami[0] = parseFloat('0'+JScript);
	js1_1 = (typeof(Date.prototype.getTimezoneOffset)); //checking core syntax

	//fallbacks
	navigator.xb[10] = navigator.xb[9] = 0; //10 is screenSize, 9 is screenColor
	var dialect = navigator.xb[6] = ''; //6 is language

 	if (js1_1){
 	//TIMEZONE 
 	  var today = new Date(); 
 	  var OffsetToday = today.getTimezoneOffset(); 
 	  navigator.xb[11] = OffsetToday/-60; //11 is timezone relative to GMT
 	  var d1 = new Date(2009, 0, 1);
 	  var d2 = new Date(2009, 6, 1);
 	  var bSupportsDaylightSavingTime = d1.getTimezoneOffset() != d2.getTimezoneOffset();
 	  if (bSupportsDaylightSavingTime){
		if ((OffsetToday < d1.getTimezoneOffset()) || (OffsetToday < d2.getTimezoneOffset()))
		{navigator.xb[11] = navigator.xb[11]-1}; //DST taken into account
	  }
	//checking client-side scripting
	  if (((navigator._exami[0] >= 2) || (typeof(navigator.javaEnabled) !='undefined')) &&
          (typeof(navigator.mimeTypes) !='undefined') && (typeof(navigator.plugins) !='undefined')){
          nav_js = 1.1;
          }  
	//checking core scripting
	  delete js1_1; navigator._exami[1] = /* checking ECMAScript edition 1 */
          (typeof(js1_1) == 'undefined' && (typeof(Infinity) =='number') && (typeof(NaN) =='number') && 
          (typeof(isFinite) !='undefined') && (typeof(Date.prototype.getMilliseconds) !='undefined') && 
          (typeof(Date.prototype.setFullYear) !='undefined') && (typeof(Date.prototype.toUTCString) !='undefined') && 
          (typeof(arguments) !='null'));
 	}

  	//detecting engines and versions
      	if (nav_family=='kde')
	{ if (ua.indexOf("khtml") != -1)
	  {
	  i = ua.indexOf('khtml');
          navigator.xb[1] = 'khtml'; 
    	  //the version property is the KHTML build version converted to double floating points
          navigator.xb[7] = getVersion(L,sforL,ua.substring(i+6,ua.lastIndexOf('(')))
	  }
	  if (ua.indexOf('applewebkit') != -1 )
    	  { //OmniWeb and Safari use the AppleWebKit engine
          j = ua.indexOf('applewebkit');
          navigator.xb[1] = 'webkit'; 
    	  //the version property is the AppleWebKit build version converted to double floating points
          navigator.xb[7] = getVersion(L,sforL,ua.substring(j+12,i-1))
	  //correcting the prettyVersion property for Safari 3
	  i = ua.indexOf("version/");
	  if (i != -1) navigator.xb[5]=getVersionLimit(L,sforL,ua.substring(i+8));
	  }
    	}
    	else if (nav_family=='gecko' && ua.indexOf("rv:") != -1)
    	{
    	  var rvStart = ua.indexOf('rv:');
    	  var rvEnd   = ua.indexOf(')', rvStart);
    	  rv = ua.substring(rvStart+3, rvEnd);
    	  //the rversion property is the /rv/ converted to double floating points (e.g. 1.090001)
    	  navigator.xb[8] = getVersion(L,sforL,rv);
    	}
    	else if (nav_family=='opera' && parseFloat('0' + sPVersion) >= 7)
    	{
     	  navigator.xb[1] = 'presto';
     	  navigator.xb[7]  = parseFloat('0' + sPVersion);
    	}
  	else if (nav_family=='ie' && window.clientInformation)
  	{
      	  navigator.xb[1] = 'trident';
    	  navigator.xb[7]  = parseFloat('0' + JScript);
    	}

  	//detecting OS or CPU
	var osOrCpu=''; if (navigator.oscpu){
       	  osOrCpu=navigator.oscpu.toLowerCase() }
       	else osOrCpu=ua.substring(ua.indexOf('(')+1,ua.indexOf(')'));
	var xos= new fOSORCPU(osOrCpu);
  	//3 is OS variant
  	if (navigator.cpuClass && navigator.cpuClass!='Other'){
       	  navigator.xb[3]=navigator.cpuClass.toLowerCase() }
	else navigator.xb[3]=xos.xos0;
	
	//fallbacks if navigator.platform is undefined
	var platform=''; navigator.xb[2]=xos.xos1; //2 is OS platform

  //NOTE: ending the /not js 1.0/ clause
   	}
  else navigator._exami=new Object();
  //decision on the pretty name
  var prettyfirst=sPName.charAt(0).toUpperCase();
  navigator.xb[4] = prettyfirst+sPName.substring(1); //4 is prettyName

  //final decision on the pretty name and version
  if (nVersion == 0.01 && navigator.xb[1]=='gecko')
	{ //correcting pretty names and versions
	if (rv.length > 0){navigator.xb[5] = rv}
 	else if (ua.indexOf("msie") != -1){navigator.xb[4]='Internet Explorer'}
 	}

  if (nav_js ==1.1){
  //checking readiness for SUN JAVA
  	if ((navigator._exami[0] >=5 || !navigator._exami[0])
   	&& typeof(navigator.javaEnabled) =='function'){
  	var nav_strictjava = (navigator.javaEnabled());
  	}
  	
  //checking client-side scripting
	if ((typeof(navigator.language) != 'undefined' || typeof(navigator.userLanguage) != 'undefined'
        || typeof(navigator.browserLanguage) != 'undefined') && (typeof(navigator.platform) != 'undefined')
        && (typeof(screen) != 'undefined') && (typeof(screen) != 'null')){
        nav_js = 1.2;
        }  
  //checking core scripting; NOTE that getVersion was defined far above
	var FMethods = (typeof(getVersion.call) !='undefined' && typeof(getVersion.apply) !='undefined');
	if (FMethods && navigator._exami[1]){ navigator._exami[2] = /* checking ECMAScript edition 3 */
        (typeof(Error) != 'undefined') && (typeof(Number.prototype.toExponential) =='function') &&
        (typeof(Number.prototype.toFixed) =='function') && (typeof(Number.prototype.toPrecision) =='function');
        }  
  
  	var screensizecolor, screensizewidth, screensizeheight;
  	if (nav_js >= 1.2){

  	//LANGUAGE
  	//e.g. British English will be "en-GB" or most often only English "en"
  	if (navigator.language){
       	  dialect=navigator.language }
  	else if (navigator.userLanguage){
       	  dialect=navigator.userLanguage }
  	else if (navigator.browserLanguage) {
       	  dialect=navigator.browserLanguage }; 
       	//removing the COUNTRY  
  	if (dialect.length >=2) navigator.xb[6] =dialect.charAt(0)+dialect.charAt(1);
  	navigator.xb[6] = navigator.xb[6].toLowerCase();

  	//detecting OS as 'win', 'mac' or 'nix'
  	platform = navigator.platform.toLowerCase();
  	//spoofing counter-measure
  	if (navigator.oscpu && xos.xos1=='win') platform=osOrCpu;

  	if (platform.indexOf('mac') != -1){
  		navigator.xb[2] = 'mac';
     		}
  	else if (platform.indexOf('x11') != -1 || platform.indexOf('unix') != -1
          || platform.indexOf('linux') != -1 || platform.indexOf('sun') != -1){
        	navigator.xb[2] = 'nix'; 
     		}
  	else if (platform.indexOf('win') != -1 || platform.indexOf('x86') != -1){
  	  	navigator.xb[2] = 'win';
  	  	//adjusting the IE cpuClass
  	  	navigator.xb[3] = xos.xos0;
     		}
	
  	//SCREEN 
  	if (screen.pixelDepth) screensizecolor = screen.pixelDepth;
  	else screensizecolor = screen.colorDepth; 

  	if (screen.width) screensizewidth = screen.width;
  	else screensizewidth = screen.availWidth+4; 
  	if (screen.height) screensizeheight = screen.height;
  	else screensizeheight = screen.availHeight+32; 
  	}
  //NOTE: js1.1 clause continues
  	else if(nav_strictjava && typeof(java)!='undefined' && typeof(java)!='null'){
  	  if (java.awt){
  	  	var toolkit = java.awt.Toolkit.getDefaultToolkit(); 
  	  	var model = toolkit.getColorModel();
  	  	var screen_size = toolkit.getScreenSize(); 
  	  	screensizewidth = screen_size.width;  
  	  	screensizeheight = screen_size.height; 
  	  	screensizecolor = model.getPixelSize();
	  	}
  	  }
  	//checking number of colours
  	if (screensizecolor){
  	navigator.xb[9]= Math.floor(Math.round(screensizecolor) * .125);
  	}
  	//checking number of pixels
  	if (screensizewidth && screensizeheight){
  	var func= screensizewidth * .0025
  	if (screensizeheight < 300 * func){
  		func= screensizeheight / 300
  		} 
  	navigator.xb[10]= Math.floor(func);  	
  	}
  //end of js1.1 clause
  }
} 
xbDetectAndAddxbArray(); //function call