function Sniffer() {
	// ************************************
	// LOCAL VARIABLES
	var t = this;
	var w = window;
	var d = document;
	var agt=navigator.userAgent.toLowerCase();
	var appVer = navigator.appVersion.toLowerCase();
	
	// ****************************************************************************
	// PUBLIC FUNCTIONS

	t.getBrowser = function() { return getBrowser(); }
	t.getOS = function() { return getOS(); }
	t.getFlashVersion = function() { return getFlashVersion(); }

	// ****************************************************************************
	// PRIVATE FUNCTIONS
	
	var getBrowser = function() {
		// Opera
		var browser = (agt.indexOf("opera") != -1) ? "Opera" : null;
		if(browser) { return browser; }
		// Konqueror
		var browser = (agt.indexOf('konqueror') != -1) ? "konqueror" : null;
		if(browser) { return browser; }
		// Safari
		var browser = ((agt.indexOf('safari')!=-1)&&(agt.indexOf('mac')!=-1)) ? "Safari" : null;
		if(browser) { return browser; }
		// Gecko
		var is_gecko = ((navigator.product)&&(navigator.product.toLowerCase()=="gecko"))?true:false;
		var is_gver  = 0;
		if (is_gecko) is_gver=navigator.productSub;
		// Mozilla
		var is_moz   = ((agt.indexOf('mozilla/5')!=-1) && (agt.indexOf('spoofer')==-1) &&
						(agt.indexOf('compatible')==-1) && (agt.indexOf('opera')==-1)  &&
						(agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1)     &&
						(is_gecko) &&
						((navigator.vendor=="")||(navigator.vendor=="Mozilla")||(navigator.vendor=="Debian")));
		// Firebird
		var is_fb = ((agt.indexOf('mozilla/5')!=-1) && (agt.indexOf('spoofer')==-1) &&
					 (agt.indexOf('compatible')==-1) && (agt.indexOf('opera')==-1)  &&
					 (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1)     &&
					 (is_gecko) && (navigator.vendor=="Firebird"));
		// Firefox
		var is_fx = ((agt.indexOf('mozilla/5')!=-1) && (agt.indexOf('spoofer')==-1) &&
					 (agt.indexOf('compatible')==-1) && (agt.indexOf('opera')==-1)  &&
					 (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1)     &&
					 (is_gecko) && (navigator.vendor=="Firefox"));

		var browser = (is_gecko) ? "Gecko" : null;
		var browser = (is_moz) ? "Mozilla" : null;
		var browser = (is_fb) ? "Firebird" : null;
		var browser = (is_fx) ? "Firefox" : null;
		if(browser) { return browser; }

		// Netscape
		var is_nav  = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
					&& (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
					&& (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1)
					&& (!(is_moz)) && (!is_fb) && (!is_fx));

		var browser = (is_nav) ? "Netscape" : null;
		if(browser) { return browser; }
		// Internet Explorer
		var browser = ((appVer.indexOf('msie')!=-1)) ? "Internet Explorer" : null;
		if(browser) { return browser; }
		// AOL
		var browser = (agt.indexOf("aol") != -1) ? "AOL" : null;
		if(browser) { return browser; }
		// TV Browsers
		var browser = (agt.indexOf("webtv") != -1) ? "WebTV" : null;
		if(browser) { return browser; }
		var browser = ((agt.indexOf("navio") != -1) || (agt.indexOf("navio_aoltv") != -1)) ? "AOL TV" : null;
		if(browser) { return browser; }
		// Hot Java
		var browser = (agt.indexOf("hotjava") != -1) ? "Hot Java" : null;
		if(browser) { return browser; }

		return browser;
	}

	var getOS = function() {
		var is_win   = ( (agt.indexOf("win")!=-1) || (agt.indexOf("16bit")!=-1) );
		var is_mac    = (agt.indexOf("mac")!=-1);
		var is_sun   = (agt.indexOf("sunos")!=-1);
		var is_irix  = (agt.indexOf("irix") !=-1);    // SGI
		var is_hpux  = (agt.indexOf("hp-ux")!=-1);
		var is_aix   = (agt.indexOf("aix") !=-1);      // IBM
		var is_linux = (agt.indexOf("inux")!=-1);
		var is_sco   = (agt.indexOf("sco")!=-1) || (agt.indexOf("unix_sv")!=-1);
		var is_unixware = (agt.indexOf("unix_system_v")!=-1);
		var is_mpras    = (agt.indexOf("ncr")!=-1);
		var is_reliant  = (agt.indexOf("reliantunix")!=-1);
		var is_dec   = ((agt.indexOf("dec")!=-1) || (agt.indexOf("osf1")!=-1) ||
			   (agt.indexOf("dec_alpha")!=-1) || (agt.indexOf("alphaserver")!=-1) ||
			   (agt.indexOf("ultrix")!=-1) || (agt.indexOf("alphastation")!=-1));
		var is_sinix = (agt.indexOf("sinix")!=-1);
		var is_freebsd = (agt.indexOf("freebsd")!=-1);
		var is_bsd = (agt.indexOf("bsd")!=-1);
		var is_unix  = ((agt.indexOf("x11")!=-1) || is_sun || is_irix || is_hpux ||
					 is_sco ||is_unixware || is_mpras || is_reliant ||
					 is_dec || is_sinix || is_aix || is_linux || is_bsd || is_freebsd);

		var is_vms   = ((agt.indexOf("vax")!=-1) || (agt.indexOf("openvms")!=-1));

		// Windows
		if(is_win == true){ is_os = "Windows"; }
		// Macintosh
		else if(is_mac == true){ is_os = "Macintosh"; }
		// Others
		else if(is_linux == true){ is_os = "Linux"; }
		else if(is_unix == true){ is_os = "UNIX"; }
		else if(is_sun == true){ is_os = "Sun OS"; }
		else if(is_irix == true){ is_os = "Irix - SGI"; }
		else if(is_hpux == true){ is_os = "Hp-ux"; }
		else if(is_aix == true){ is_os = "Aix - IBM"; }
		else if(is_sco == true){ is_os = "SCO"; }
		else if(is_unixware == true){ is_os = "Unixware"; }
		else if(is_mpras == true){ is_os = "MPras"; }
		else if(is_reliant == true){ is_os = "Reliant"; }
		else if(is_dec == true){ is_os = "DEC Alpha"; }
		else if(is_sinix == true){ is_os = "Sinix"; }
		else if(is_freebsd == true){ is_os = "Free BSD"; }
		else if(is_bsd == true){ is_os = "BSD"; }
		else if(is_vms == true){ is_os = "VMS"; }
		else{ is_os = "Other"; }

		return is_os;
	}

	var getFlashVersion = function() {

		var self = this;
		self.installed = false;
		self.raw = "";
		self.major = -1;
		self.minor = -1;
		self.revision = -1;
		self.revisionStr = "";
		var activeXDetectRules = [
			{
				"name":"ShockwaveFlash.ShockwaveFlash.7",
				"version":function(obj){
					return getActiveXVersion(obj);
				}
			},
			{
				"name":"ShockwaveFlash.ShockwaveFlash.6",
				"version":function(obj){
					var version = "6,0,21";
					try{
						obj.AllowScriptAccess = "always";
						version = getActiveXVersion(obj);
					}catch(err){}
					return version;
				}
			},
			{
				"name":"ShockwaveFlash.ShockwaveFlash",
				"version":function(obj){
					return getActiveXVersion(obj);
				}
			}
		];
		var getActiveXVersion = function(activeXObj){
			var version = -1;
			try{
				version = activeXObj.GetVariable("$version");
			}catch(err){}
			return version;
		};
		var getActiveXObject = function(name){
			var obj = -1;
			try{
				obj = new ActiveXObject(name);
			}catch(err){}
			return obj;
		};
		var parseActiveXVersion = function(str){
			var versionArray = str.split(",");//replace with regex
			return {
				"raw":str,
				"major":parseInt(versionArray[0].split(" ")[1], 10),
				"minor":parseInt(versionArray[1], 10),
				"revision":parseInt(versionArray[2], 10),
				"revisionStr":versionArray[2]
			};
		};
		var parseStandardVersion = function(str){
			var descParts = str.split(/ +/);
			var majorMinor = descParts[2].split(/\./);
			var revisionStr = descParts[3];
			return {
				"raw":str,
				"major":parseInt(majorMinor[0], 10),
				"minor":parseInt(majorMinor[1], 10), 
				"revisionStr":revisionStr,
				"revision":parseRevisionStrToInt(revisionStr)
			};
		};
		var parseRevisionStrToInt = function(str){
			return parseInt(str.replace(/[a-zA-Z]/g, ""), 10) || self.revision;
		};
		self.majorAtLeast = function(version){
			return self.major >= version;
		};
		self.FlashDetect = function(){
			if(navigator.plugins && navigator.plugins.length>0){
				var type = 'application/x-shockwave-flash';
				var mimeTypes = navigator.mimeTypes;
				if(mimeTypes && mimeTypes[type] && mimeTypes[type].enabledPlugin && mimeTypes[type].enabledPlugin.description){
					var version = mimeTypes[type].enabledPlugin.description;
					var versionObj = parseStandardVersion(version);
					self.raw = versionObj.raw;
					self.major = versionObj.major;
					self.minor = versionObj.minor; 
					self.revisionStr = versionObj.revisionStr;
					self.revision = versionObj.revision;
					self.installed = true;
				}
			}else if(navigator.appVersion.indexOf("Mac")==-1 && window.execScript){
				var version = -1;
				for(var i=0; i<activeXDetectRules.length && version==-1; i++){
					var obj = getActiveXObject(activeXDetectRules[i].name);
					if(typeof obj == "object"){
						self.installed = true;
						version = activeXDetectRules[i].version(obj);
						if(version!=-1){
							var versionObj = parseActiveXVersion(version);
							self.raw = versionObj.raw;
							self.major = versionObj.major;
							self.minor = versionObj.minor; 
							self.revision = versionObj.revision;
							self.revisionStr = versionObj.revisionStr;
						}
					}
				}
			}
		}();
	}
}
sniffer = new Sniffer();
