Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- var Fingerprinter = (function(){
- "use strict"
- function fingerprinter()
- {
- this.FingerPrintHash = "";
- // a super function to call everything else below, and compute the md5 of the concat output.
- // if you are trying to get a fingerprint of a user, this is the function to use.
- // ~82 bits entropy. =wow=
- this.superPrint = function()
- {
- var strConcat = "";
- var strSep = ";";
- //if(this.FingerPrintHash)
- //{
- //if the fingerprint is requested twice on the same page, return whats stored in JS, this is the fastest method.
- //return this.FingerPrintHash;
- //}
- strConcat += this.flashVersion() + strSep + this.browserVersion() + this.canvasFingerprint() + strSep + this.androidConnectType() + strSep + this.cookiesEnabled() + strSep;
- strConcat += this.screenInfo() + strSep + this.fontSmoothing() + strSep + this.html5LocalStorage() + strSep + this.fontsFingerprint() + strSep + this. javaEnabled() + strSep + this.language() + strSep;
- strConcat += this.silverlightVersion() + strSep + this.osDetect() + strSep + this.timeZone() + strSep + this.hasTouchScreen() + strSep + this.userAgentImproved() + strSep + this.pluginsFingerprint();
- strConcat = md5(strConcat);
- //check to see if the stored fingerprint differs, and if it does update.
- if(localStorage.getItem("fingerprint"))
- {
- if(localStorage.getItem("fingerprint") != strConcat)
- {
- //code to update the fingerprint on the userStore.
- console.log("fingerprint differs!, was: "+ localStorage.getItem("fingerprint")+" but is now: " + strConcat );
- }
- }
- //save the fingerprint locally in case theres a bad bit of code that rapidly calls this.
- this.FingerPrintHash = strConcat;
- if(this.html5LocalStorage())
- {
- localStorage.setItem("fingerprint",strConcat);
- }
- return strConcat;
- }
- //////////////////////////////////////////////////////////////////////
- // //
- // The below functions can be used for fingerprint corrilation. //
- // //
- //////////////////////////////////////////////////////////////////
- // gets the client IP address.
- // Since an IP address can change ( most isp's use dhcp ) we DON'T use this in superPrint().
- this.getPublicIP = function()
- {
- //TODO: do stuff here!
- //curl -s http://whatismyip.akamai.com/
- }
- // android connection type: returns N/A, UNKNOWN, ETHERNET, WIFI, CELL_2G, CELL_3G, CELL_4G or NONE.
- // ~2.8 bits of entropy. more useful for determining fingerprint relations from phone <--> computer
- // Used in superPrint
- this.androidConnectType = function()
- {
- var strOnError;
- strOnError = "N/A";
- try
- {
- // only on android
- return navigator.connection.type;
- }
- catch (err)
- {
- // return N/A if navigator.connection object does not apply to this device
- return strOnError;
- }
- }
- // touch support (identifies if there is a digitizer). IE 11 falsely reports no touch screen if there is one present.
- // This can be used in conjunction with the user agent to detect iphones, ipads, and windows phones. android should be detected with androidConnectType()
- // Entropy: TBD, expected to be <1 bit
- // used in superPrint
- this.hasTouchScreen = function()
- {
- try
- {
- if (document.createEvent("TouchEvent"))
- {
- return true;
- }
- return false;
- }
- catch (ignore)
- {
- return false;
- }
- }
- // get the time zone of the client.
- // entropy ~3.04 bits
- // adds a small ammount of entropy to the phone <--> computer corrilation.
- // used in superPrint
- this.timeZone = function()
- {
- var strOnError, dtDate, numOffset, numGMTHours;
- strOnError = "Error";
- dtDate = null;
- numOffset = null;
- numGMTHours = null;
- try
- {
- dtDate = new Date();
- numOffset = dtDate.getTimezoneOffset();
- numGMTHours = (numOffset / 60) * (-1);
- return numGMTHours;
- }
- catch (err)
- {
- return strOnError;
- }
- }
- //////////////////////////////////////////////////////////////////////////////////////////
- // //
- // The below functions are used in superPrint, but are not useful for corrilation //
- // //
- //////////////////////////////////////////////////////////////////////////////////////
- this.html5LocalStorage = function()
- {
- if(typeof(Storage) !== "undefined")
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- // returns if cookies are enabled or not.
- // ~0.4 bits of entropy. better used to see how to store the fingerprint accross pages.
- this.cookiesEnabled = function()
- {
- var strOnError, bolCookieEnabled;
- strOnError = "Error";
- bolCookieEnabled = null;
- try
- {
- bolCookieEnabled = (navigator.cookieEnabled) ? true : false;
- //if not IE4+ nor NS6+
- if (typeof navigator.cookieEnabled === "undefined" && !bolCookieEnabled)
- {
- document.cookie = "testcookie";
- bolCookieEnabled = (document.cookie.indexOf("testcookie") !== -1) ? true : false;
- }
- return bolCookieEnabled;
- }
- catch (err)
- {
- return strOnError;
- }
- }
- // gets the version of flash
- // entropy = ~4.3 bits
- this.flashVersion = function()
- {
- var StrOnError,
- ObjPlayerVersion,
- StrVersion,
- StrOnError = "N/A";
- ObjPlayerVersion = null;
- StrVersion = null;
- try
- {
- ObjPlayerVersion = swfobject.getFlashPlayerVersion();
- StrVersion = objPlayerVersion.major + "." + objPlayerVersion.minor + "." + objPlayerVersion.release;
- if (StrVersion === "0.0.0")
- {
- StrVersion = "N/A";
- }
- return StrVersion;
- }
- catch (err)
- {
- return StrOnError;
- }
- }
- // gets the browser version / name from the browser user adgent, can be unreliable.
- // entropy TBD
- this.browserVersion = function()
- {
- var strOnError, strUserAgent, numVersion, strBrowser;
- strOnError = "Error";
- strUserAgent = null;
- numVersion = null;
- strBrowser = null;
- try
- {
- strUserAgent = navigator.userAgent.toLowerCase();
- if (/msie (\d+\.\d+);/.test(strUserAgent))
- { //test for MSIE x.x;
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- if (strUserAgent.indexOf("trident/6") > -1)
- {
- numVersion = 10;
- }
- if (strUserAgent.indexOf("trident/5") > -1)
- {
- numVersion = 9;
- }
- if (strUserAgent.indexOf("trident/4") > -1)
- {
- numVersion = 8;
- }
- strBrowser = "Internet Explorer " + numVersion;
- }
- else if (strUserAgent.indexOf("trident/7") > -1)
- { //IE 11+ gets rid of the legacy 'MSIE' in the user-agent string;
- numVersion = 11;
- strBrowser = "Internet Explorer " + numVersion;
- }
- else if (/firefox[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for Firefox/x.x or Firefox x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Firefox " + numVersion;
- }
- else if (/opera[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for Opera/x.x or Opera x.x (ignoring remaining decimal places);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Opera " + numVersion;
- }
- else if (/chrome[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for Chrome/x.x or Chrome x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Chrome " + numVersion;
- }
- else if (/version[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for Version/x.x or Version x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Safari " + numVersion;
- }
- else if (/rv[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for rv/x.x or rv x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Mozilla " + numVersion;
- }
- else if (/mozilla[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for Mozilla/x.x or Mozilla x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Mozilla " + numVersion;
- }
- else if (/binget[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for BinGet/x.x or BinGet x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Library (BinGet) " + numVersion;
- }
- else if (/curl[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for Curl/x.x or Curl x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Library (cURL) " + numVersion;
- }
- else if (/java[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for Java/x.x or Java x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Library (Java) " + numVersion;
- }
- else if (/libwww-perl[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for libwww-perl/x.x or libwww-perl x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Library (libwww-perl) " + numVersion;
- }
- else if (/microsoft url control -[\s](\d+\.\d+)/.test(strUserAgent))
- { //test for Microsoft URL Control - x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Library (Microsoft URL Control) " + numVersion;
- }
- else if (/peach[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for Peach/x.x or Peach x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Library (Peach) " + numVersion;
- }
- else if (/php[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for PHP/x.x or PHP x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Library (PHP) " + numVersion;
- }
- else if (/pxyscand[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for pxyscand/x.x or pxyscand x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Library (pxyscand) " + numVersion;
- }
- else if (/pycurl[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for pycurl/x.x or pycurl x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Library (PycURL) " + numVersion;
- }
- else if (/python-urllib[\/\s](\d+\.\d+)/.test(strUserAgent))
- { //test for python-urllib/x.x or python-urllib x.x (ignoring remaining digits);
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Library (Python URLlib) " + numVersion;
- }
- else if (/appengine-google/.test(strUserAgent))
- { //test for AppEngine-Google;
- numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
- strBrowser = "Cloud (Google AppEngine) " + numVersion;
- }
- else
- {
- strBrowser = "Unknown";
- }
- return strBrowser;
- }
- catch (err)
- {
- return strOnError;
- }
- }
- // canvas - uses graphics driver and gpu.
- // generate a string and turn it into a 2d image, the base64 of the image will be slightly different based on hardware / render engine.
- // entropy ~10.8 bits
- this.canvasFingerprint = function()
- {
- var strOnError, canvas, strCText, strText;
- strOnError = "Error";
- canvas = null;
- strCText = null;
- strText = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`~1!2@3#4$5%6^7&8*9(0)-_=+[{]}|;:',<.>/?";
- try
- {
- canvas = document.createElement('canvas');
- strCText = canvas.getContext('2d');
- strCText.textBaseline = "top";
- strCText.font = "14px 'Arial'";
- strCText.textBaseline = "alphabetic";
- strCText.fillStyle = "#f60";
- strCText.fillRect(125, 1, 62, 20);
- strCText.fillStyle = "#069";
- strCText.fillText(strText, 2, 15);
- strCText.fillStyle = "rgba(102, 204, 0, 0.7)";
- strCText.fillText(strText, 4, 17);
- return md5(canvas.toDataURL()); //return the base64 of the canvas image.
- }
- catch (err)
- {
- return strOnError;
- }
- }
- // returns a concat string of numerical display data. <color depth>|<screen width>|<screen height>|<window width>|<window height>
- // entropy ~8.8 bits
- this.screenInfo = function()
- {
- var strSep, strPair, strOnError, strScreen, strDisplay;
- strSep = "|";
- strPair = "=";
- strOnError = "Error";
- strScreen = null;
- strDisplay = null;
- try
- {
- strScreen = window.screen;
- if (strScreen)
- {
- strDisplay = strScreen.colorDepth + strSep + strScreen.width + strSep + strScreen.height + strSep + strScreen.availWidth + strSep + strScreen.availHeight;
- }
- return strDisplay;
- }
- catch (err)
- {
- return strOnError;
- }
- }
- // font smoothing, returns true if enabled. flase if disabled, or unknown if undeterministic.
- // entropy ~0.4 bits
- this.fontSmoothing = function()
- {
- var strFontSmoothing, canvasNode, ctx, i, j, imageData, alpha, strOnError;
- strOnError = "Unknown";
- canvasNode = null;
- ctx = null;
- imageData = null;
- alpha = null;
- if (typeof(screen.fontSmoothingEnabled) !== "undefined")
- {
- return screen.fontSmoothingEnabled;
- }
- //browser cant report back if smoothing is enabled, so we just test ourselves.
- else
- {
- try
- {
- fontsmoothing = "false";
- //create a canvas element and put a 'O' in the top left.
- canvasNode = document.createElement('canvas');
- canvasNode.width = "35";
- canvasNode.height = "35";
- canvasNode.style.display = 'none';
- document.body.appendChild(canvasNode);
- ctx = canvasNode.getContext('2d');
- ctx.textBaseline = "top";
- ctx.font = "32px Arial";
- ctx.fillStyle = "black";
- ctx.strokeStyle = "black";
- ctx.fillText("O", 0, 0);
- //Itterate over the 'O' pixel by pixel.
- for (j = 8; j <= 32; j = j + 1)
- {
- for (i = 1; i <= 32; i = i + 1)
- {
- imageData = ctx.getImageData(i, j, 1, 1).data;
- alpha = imageData[3];
- //if a pixel has a value other than 0 or 255, the folt is being smoothed.
- if (alpha !== 255 && alpha !== 0)
- {
- return "true"; // font-smoothing must be on.
- }
- }
- }
- //no font smoothing detected.
- return "false";
- }
- catch (err)
- {
- return strOnError;
- }
- }
- }
- // fonts - gets the md5 of the fonts installed.
- // entropy ~13.9 bits
- this.fontsFingerprint = function()
- {
- var strOnError, style, fonts, count, template, fragment, divs, i, font, div, body, result, e;
- strOnError = "Error";
- style = null;
- fonts = null;
- font = null;
- count = 0;
- template = null;
- divs = null;
- e = null;
- div = null;
- body = null;
- i = 0;
- try
- {
- style = "position: absolute; visibility: hidden; display: block !important";
- fonts = ["Abadi MT Condensed Light", "Adobe Fangsong Std", "Adobe Hebrew", "Adobe Ming Std", "Agency FB", "Aharoni", "Andalus", "Angsana New", "AngsanaUPC", "Aparajita", "Arab", "Arabic Transparent", "Arabic Typesetting", "Arial Baltic", "Arial Black", "Arial CE", "Arial CYR", "Arial Greek", "Arial TUR", "Arial", "Batang", "BatangChe", "Bauhaus 93", "Bell MT", "Bitstream Vera Serif", "Bodoni MT", "Bookman Old Style", "Braggadocio", "Broadway", "Browallia New", "BrowalliaUPC", "Calibri Light", "Calibri", "Californian FB", "Cambria Math", "Cambria", "Candara", "Castellar", "Casual", "Centaur", "Century Gothic", "Chalkduster", "Colonna MT", "Comic Sans MS", "Consolas", "Constantia", "Copperplate Gothic Light", "Corbel", "Cordia New", "CordiaUPC", "Courier New Baltic", "Courier New CE", "Courier New CYR", "Courier New Greek", "Courier New TUR", "Courier New", "DFKai-SB", "DaunPenh", "David", "DejaVu LGC Sans Mono", "Desdemona", "DilleniaUPC", "DokChampa", "Dotum", "DotumChe", "Ebrima", "Engravers MT", "Eras Bold ITC", "Estrangelo Edessa", "EucrosiaUPC", "Euphemia", "Eurostile", "FangSong", "Forte", "FrankRuehl", "Franklin Gothic Heavy", "Franklin Gothic Medium", "FreesiaUPC", "French Script MT", "Gabriola", "Gautami", "Georgia", "Gigi", "Gisha", "Goudy Old Style", "Gulim", "GulimChe", "GungSeo", "Gungsuh", "GungsuhChe", "Haettenschweiler", "Harrington", "Hei S", "HeiT", "Heisei Kaku Gothic", "Hiragino Sans GB", "Impact", "Informal Roman", "IrisUPC", "Iskoola Pota", "JasmineUPC", "KacstOne", "KaiTi", "Kalinga", "Kartika", "Khmer UI", "Kino MT", "KodchiangUPC", "Kokila", "Kozuka Gothic Pr6N", "Lao UI", "Latha", "Leelawadee", "Levenim MT", "LilyUPC", "Lohit Gujarati", "Loma", "Lucida Bright", "Lucida Console", "Lucida Fax", "Lucida Sans Unicode", "MS Gothic", "MS Mincho", "MS PGothic", "MS PMincho", "MS Reference Sans Serif", "MS UI Gothic", "MV Boli", "Magneto", "Malgun Gothic", "Mangal", "Marlett", "Matura MT Script Capitals", "Meiryo UI", "Meiryo", "Menlo", "Microsoft Himalaya", "Microsoft JhengHei", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Sans Serif", "Microsoft Tai Le", "Microsoft Uighur", "Microsoft YaHei", "Microsoft Yi Baiti", "MingLiU", "MingLiU-ExtB", "MingLiU_HKSCS", "MingLiU_HKSCS-ExtB", "Miriam Fixed", "Miriam", "Mongolian Baiti", "MoolBoran", "NSimSun", "Narkisim", "News Gothic MT", "Niagara Solid", "Nyala", "PMingLiU", "PMingLiU-ExtB", "Palace Script MT", "Palatino Linotype", "Papyrus", "Perpetua", "Plantagenet Cherokee", "Playbill", "Prelude Bold", "Prelude Condensed Bold", "Prelude Condensed Medium", "Prelude Medium", "PreludeCompressedWGL Black", "PreludeCompressedWGL Bold", "PreludeCompressedWGL Light", "PreludeCompressedWGL Medium", "PreludeCondensedWGL Black", "PreludeCondensedWGL Bold", "PreludeCondensedWGL Light", "PreludeCondensedWGL Medium", "PreludeWGL Black", "PreludeWGL Bold", "PreludeWGL Light", "PreludeWGL Medium", "Raavi", "Rachana", "Rockwell", "Rod", "Sakkal Majalla", "Sawasdee", "Script MT Bold", "Segoe Print", "Segoe Script", "Segoe UI Light", "Segoe UI Semibold", "Segoe UI Symbol", "Segoe UI", "Shonar Bangla", "Showcard Gothic", "Shruti", "SimHei", "SimSun", "SimSun-ExtB", "Simplified Arabic Fixed", "Simplified Arabic", "Snap ITC", "Sylfaen", "Symbol", "Tahoma", "Times New Roman Baltic", "Times New Roman CE", "Times New Roman CYR", "Times New Roman Greek", "Times New Roman TUR", "Times New Roman", "TlwgMono", "Traditional Arabic", "Trebuchet MS", "Tunga", "Tw Cen MT Condensed Extra Bold", "Ubuntu", "Umpush", "Univers", "Utopia", "Utsaah", "Vani", "Verdana", "Vijaya", "Vladimir Script", "Vrinda", "Webdings", "Wide Latin", "Wingdings"];
- count = fonts.length;
- template = '<b style="display:inline !important; width:auto !important; font:normal 10px/1 \'X\',sans-serif !important">ww</b>' + '<b style="display:inline !important; width:auto !important; font:normal 10px/1 \'X\',monospace !important">ww</b>';
- fragment = document.createDocumentFragment();
- divs = [];
- for (i = 0; i < count; i = i + 1)
- {
- font = fonts[i];
- div = document.createElement('div');
- font = font.replace(/[\u0027\u0022<>]/g, ''); //Code flow can not distinguish escaped " or '. so use escape codes. u0022 = " and u0027 = ' TODO: replace in final version
- div.innerHTML = template.replace(/X/g, font);
- div.style.cssText = style;
- fragment.appendChild(div);
- divs.push(div);
- }
- body = document.body;
- body.insertBefore(fragment, body.firstChild);
- result = [];
- for (i = 0; i < count; i = i + 1)
- {
- e = divs[i].getElementsByTagName('b');
- if (e[0].offsetWidth === e[1].offsetWidth)
- {
- result.push(fonts[i]);
- }
- }
- // do not combine these two loops, remove child will cause reflow
- // and induce severe performance hit
- for (i = 0; i < count; i = i + 1)
- {
- body.removeChild(divs[i]);
- }
- return md5(result.join('|'));
- }
- catch (err)
- {
- return strOnError;
- }
- }
- // java enabled - returns a bool for if it is enabled.
- // entropy ~1 bit.
- this.javaEnabled = function()
- {
- if(navigator.javaEnabled === "function")
- {
- if (navigator.javaEnabled())
- {
- return "true";
- }
- else
- {
- return "false";
- }
- }
- else
- {
- return "false";
- }
- }
- // gets the language of the user computer
- // entropy ~10 bits
- this.language = function()
- {
- var strSep, strPair, strOnError, strLang, strTypeLng, strTypeBrLng, strTypeSysLng, strTypeUsrLng;
- strSep = "|";
- strPair = "=";
- strOnError = "Error";
- strLang = null;
- strTypeLng = null;
- strTypeBrLng = null;
- strTypeSysLng = null;
- strTypeUsrLng = null;
- try
- {
- strTypeLng = typeof (navigator.language);
- strTypeBrLng = typeof (navigator.browserLanguage);
- strTypeSysLng = typeof (navigator.systemLanguage);
- strTypeUsrLng = typeof (navigator.userLanguage);
- if (strTypeLng !== "undefined")
- {
- strLang = "lang" + strPair + navigator.language + strSep;
- }
- else if (strTypeBrLng !== "undefined")
- {
- strLang = "lang" + strPair + navigator.browserLanguage + strSep;
- }
- else
- {
- strLang = "lang" + strPair + strSep;
- }
- if (strTypeSysLng !== "undefined")
- {
- strLang += "syslang" + strPair + navigator.systemLanguage + strSep;
- }
- else
- {
- strLang += "syslang" + strPair + strSep;
- }
- if (strTypeUsrLng !== "undefined")
- {
- strLang += "userlang" + strPair + navigator.userLanguage;
- }
- else
- {
- strLang += "userlang" + strPair;
- }
- return strLang;
- }
- catch (err)
- {
- return strOnError;
- }
- }
- // find the version of silverlight. returns n/a if not installed.
- // entropy ~1.8 bits
- this.silverlightVersion = function()
- {
- var strOnError, objControl, objPlugin, strSilverlightVersion;
- strOnError = "Error";
- objControl = null;
- objPlugin = null;
- strSilverlightVersion = null;
- try
- {
- try
- {
- objControl = new ActiveXObject('AgControl.AgControl');
- if (objControl.IsVersionSupported("5.0"))
- {
- strSilverlightVersion = "5.x";
- }
- else if (objControl.IsVersionSupported("4.0"))
- {
- strSilverlightVersion = "4.x";
- }
- else if (objControl.IsVersionSupported("3.0"))
- {
- strSilverlightVersion = "3.x";
- }
- else if (objControl.IsVersionSupported("2.0"))
- {
- strSilverlightVersion = "2.x";
- }
- else
- {
- strSilverlightVersion = "1.x";
- }
- objControl = null;
- }
- catch (e)
- {
- objPlugin = navigator.plugins["Silverlight Plug-In"];
- if (objPlugin)
- {
- if (objPlugin.description === "1.0.30226.2")
- {
- strSilverlightVersion = "2.x";
- }
- else
- {
- strSilverlightVersion = parseInt(objPlugin.description[0], 10);
- }
- }
- else
- {
- strSilverlightVersion = "N/A";
- }
- }
- return strSilverlightVersion;
- }
- catch (err)
- {
- return strOnError;
- }
- }
- // OS name and architecture.
- // entropy ~1.2 bits
- this.osDetect = function()
- {
- var strSep, strOnError, strUserAgent, strPlatform, strOS, strOSBits;
- strSep = "|";
- strOnError = "Error";
- strUserAgent = null;
- strPlatform = null;
- strOS = null;
- strOSBits = null;
- try
- {
- // navigator.userAgent is supported by all major browsers
- strUserAgent = navigator.userAgent.toLowerCase();
- // navigator.platform is supported by all major browsers
- strPlatform = navigator.platform.toLowerCase();
- if (strUserAgent.indexOf("windows nt 10.0") !== -1) { strOS = "Windows 10"; } //currently fails on IE11, it inaccurately reports it as nt 6.3
- else if (strUserAgent.indexOf("windows nt 6.3") !== -1) { strOS = "Windows 8.1"; }
- else if (strUserAgent.indexOf("windows nt 6.2") !== -1) { strOS = "Windows 8"; }
- else if (strUserAgent.indexOf("windows nt 6.1") !== -1) { strOS = "Windows 7"; }
- else if (strUserAgent.indexOf("windows nt 6.0") !== -1) { strOS = "Windows Vista/Windows Server 2008"; }
- else if (strUserAgent.indexOf("windows nt 5.2") !== -1) { strOS = "Windows XP x64/Windows Server 2003"; }
- else if (strUserAgent.indexOf("windows nt 5.1") !== -1) { strOS = "Windows XP"; }
- else if (strUserAgent.indexOf("windows nt 5.01") !== -1) { strOS = "Windows 2000, Service Pack 1 (SP1)"; }
- else if (strUserAgent.indexOf("windows xp") !== -1) { strOS = "Windows XP"; }
- else if (strUserAgent.indexOf("windows 2000") !== -1) { strOS = "Windows 2000"; }
- else if (strUserAgent.indexOf("windows nt 5.0") !== -1) { strOS = "Windows 2000"; }
- else if (strUserAgent.indexOf("windows nt 4.0") !== -1) { strOS = "Windows NT 4.0"; }
- else if (strUserAgent.indexOf("windows nt") !== -1) { strOS = "Windows NT 4.0"; }
- else if (strUserAgent.indexOf("winnt4.0") !== -1) { strOS = "Windows NT 4.0"; }
- else if (strUserAgent.indexOf("winnt") !== -1) { strOS = "Windows NT 4.0"; }
- else if (strUserAgent.indexOf("windows me") !== -1) { strOS = "Windows ME"; }
- else if (strUserAgent.indexOf("win 9x 4.90") !== -1) { strOS = "Windows ME"; }
- else if (strUserAgent.indexOf("windows 98") !== -1) { strOS = "Windows 98"; }
- else if (strUserAgent.indexOf("win98") !== -1) { strOS = "Windows 98"; }
- else if (strUserAgent.indexOf("windows 95") !== -1) { strOS = "Windows 95"; }
- else if (strUserAgent.indexOf("windows_95") !== -1) { strOS = "Windows 95"; }
- else if (strUserAgent.indexOf("win95") !== -1) { strOS = "Windows 95"; }
- else if (strUserAgent.indexOf("ce") !== -1) { strOS = "Windows CE"; }
- else if (strUserAgent.indexOf("win16") !== -1) { strOS = "Windows 3.11"; }
- else if (strUserAgent.indexOf("iemobile") !== -1) { strOS = "Windows Mobile"; }
- else if (strUserAgent.indexOf("wm5 pie") !== -1) { strOS = "Windows Mobile"; }
- else if (strUserAgent.indexOf("windows") !== -1) { strOS = "Windows (Unknown Version)"; }
- else if (strUserAgent.indexOf("openbsd") !== -1) { strOS = "Open BSD"; }
- else if (strUserAgent.indexOf("sunos") !== -1) { strOS = "Sun OS"; }
- else if (strUserAgent.indexOf("ubuntu") !== -1) { strOS = "Ubuntu"; }
- else if (strUserAgent.indexOf("ipad") !== -1) { strOS = "iOS (iPad)"; }
- else if (strUserAgent.indexOf("ipod") !== -1) { strOS = "iOS (iTouch)"; }
- else if (strUserAgent.indexOf("iphone") !== -1) { strOS = "iOS (iPhone)"; }
- else if (strUserAgent.indexOf("mac os x beta") !== -1) { strOS = "Mac OSX Beta (Kodiak)"; }
- else if (strUserAgent.indexOf("mac os x 10.0") !== -1) { strOS = "Mac OSX Cheetah"; }
- else if (strUserAgent.indexOf("mac os x 10.1") !== -1) { strOS = "Mac OSX Puma"; }
- else if (strUserAgent.indexOf("mac os x 10.2") !== -1) { strOS = "Mac OSX Jaguar"; }
- else if (strUserAgent.indexOf("mac os x 10.3") !== -1) { strOS = "Mac OSX Panther"; }
- else if (strUserAgent.indexOf("mac os x 10.4") !== -1) { strOS = "Mac OSX Tiger"; }
- else if (strUserAgent.indexOf("mac os x 10.5") !== -1) { strOS = "Mac OSX Leopard"; }
- else if (strUserAgent.indexOf("mac os x 10.6") !== -1) { strOS = "Mac OSX Snow Leopard"; }
- else if (strUserAgent.indexOf("mac os x 10.7") !== -1) { strOS = "Mac OSX Lion"; }
- else if (strUserAgent.indexOf("mac os x") !== -1) { strOS = "Mac OSX (Version Unknown)"; }
- else if (strUserAgent.indexOf("mac_68000") !== -1) { strOS = "Mac OS Classic (68000)"; }
- else if (strUserAgent.indexOf("68K") !== -1) { strOS = "Mac OS Classic (68000)";}
- else if (strUserAgent.indexOf("mac_powerpc") !== -1) { strOS = "Mac OS Classic (PowerPC)"; }
- else if (strUserAgent.indexOf("ppc mac") !== -1) { strOS = "Mac OS Classic (PowerPC)"; }
- else if (strUserAgent.indexOf("macintosh") !== -1) { strOS = "Mac OS Classic"; }
- else if (strUserAgent.indexOf("googletv") !== -1) { strOS = "Android (GoogleTV)"; }
- else if (strUserAgent.indexOf("xoom") !== -1) { strOS = "Android (Xoom)"; }
- else if (strUserAgent.indexOf("htc_flyer") !== -1) { strOS = "Android (HTC Flyer)"; }
- else if (strUserAgent.indexOf("android") !== -1) { strOS = "Android"; }
- else if (strUserAgent.indexOf("symbian") !== -1) { strOS = "Symbian"; }
- else if (strUserAgent.indexOf("series60") !== -1) { strOS = "Symbian (Series 60)"; }
- else if (strUserAgent.indexOf("series70") !== -1) { strOS = "Symbian (Series 70)"; }
- else if (strUserAgent.indexOf("series80") !== -1) { strOS = "Symbian (Series 80)"; }
- else if (strUserAgent.indexOf("series90") !== -1) { strOS = "Symbian (Series 90)"; }
- else if (strUserAgent.indexOf("x11") !== -1) { strOS = "UNIX"; }
- else if (strUserAgent.indexOf("nix") !== -1) { strOS = "UNIX"; }
- else if (strUserAgent.indexOf("linux") !== -1) { strOS = "Linux"; }
- else if (strUserAgent.indexOf("qnx") !== -1) { strOS = "QNX"; }
- else if (strUserAgent.indexOf("os/2") !== -1) { strOS = "IBM OS/2"; }
- else if (strUserAgent.indexOf("beos") !== -1) { strOS = "BeOS"; }
- else if (strUserAgent.indexOf("blackberry95") !== -1) { strOS = "Blackberry (Storm 1/2)"; }
- else if (strUserAgent.indexOf("blackberry97") !== -1) { strOS = "Blackberry (Bold)"; }
- else if (strUserAgent.indexOf("blackberry96") !== -1) { strOS = "Blackberry (Tour)"; }
- else if (strUserAgent.indexOf("blackberry89") !== -1) { strOS = "Blackberry (Curve 2)"; }
- else if (strUserAgent.indexOf("blackberry98") !== -1) { strOS = "Blackberry (Torch)"; }
- else if (strUserAgent.indexOf("playbook") !== -1) { strOS = "Blackberry (Playbook)"; }
- else if (strUserAgent.indexOf("wnd.rim") !== -1) { strOS = "Blackberry (IE/FF Emulator)"; }
- else if (strUserAgent.indexOf("blackberry") !== -1) { strOS = "Blackberry"; }
- else if (strUserAgent.indexOf("palm") !== -1) { strOS = "Palm OS"; }
- else if (strUserAgent.indexOf("webos") !== -1) { strOS = "WebOS"; }
- else if (strUserAgent.indexOf("hpwos") !== -1) { strOS = "WebOS (HP)"; }
- else if (strUserAgent.indexOf("blazer") !== -1) { strOS = "Palm OS (Blazer)"; }
- else if (strUserAgent.indexOf("xiino") !== -1) { strOS = "Palm OS (Xiino)"; }
- else if (strUserAgent.indexOf("kindle") !== -1) { strOS = "Kindle"; }
- else if (strUserAgent.indexOf("wii") !== -1) { strOS = "Nintendo (Wii)"; }
- else if (strUserAgent.indexOf("nintendo ds") !== -1) { strOS = "Nintendo (DS)"; }
- else if (strUserAgent.indexOf("playstation 3") !== -1) { strOS = "Sony (Playstation Console)"; }
- else if (strUserAgent.indexOf("playstation portable") !== -1) { strOS = "Sony (Playstation Portable)"; }
- else if (strUserAgent.indexOf("webtv") !== -1) { strOS = "MSN TV (WebTV)"; }
- else if (strUserAgent.indexOf("inferno") !== -1) { strOS = "Inferno"; }
- else { strOS = "Unknown"; }
- if (strPlatform.indexOf("x64") !== -1) { strOSBits = "64 bits"; }
- else if (strPlatform.indexOf("wow64") !== -1) { strOSBits = "64 bits"; }
- else if (strPlatform.indexOf("win64") !== -1) { strOSBits = "64 bits"; }
- else if (strPlatform.indexOf("win32") !== -1) { strOSBits = "32 bits"; }
- else if (strPlatform.indexOf("x64") !== -1) { strOSBits = "64 bits"; }
- else if (strPlatform.indexOf("x32") !== -1) { strOSBits = "32 bits"; }
- else if (strPlatform.indexOf("x86") !== -1) { strOSBits = "32 bits*"; }
- else if (strPlatform.indexOf("ppc") !== -1) { strOSBits = "64 bits"; }
- else if (strPlatform.indexOf("alpha") !== -1) { strOSBits = "64 bits"; }
- else if (strPlatform.indexOf("68k") !== -1) { strOSBits = "64 bits"; }
- else if (strPlatform.indexOf("iphone") !== -1) { strOSBits = "32 bits"; }
- else if (strPlatform.indexOf("android") !== -1) { strOSBits = "32 bits"; }
- else { strOSBits = "Unknown"; }
- return (strOS + strSep + strOSBits);
- }
- catch (err)
- {
- return strOnError;
- }
- }
- // get the user agent and append other information such as the platform and language, and cpuClass info.
- // entropy: ~11.5 bits, some bits will be the same as above calls. however the composit nature leads to unique hashes.
- this.userAgentImproved = function()
- {
- var strSep, strTmp, strUserAgent;
- strSep = "|";
- strTmp = null;
- strUserAgent = null;
- // navigator.userAgent is supported by all major browsers
- strUserAgent = navigator.userAgent.toLowerCase();
- // navigator.platform is supported by all major browsers
- strTmp = strUserAgent + strSep + navigator.platform;
- // navigator.cpuClass only supported in IE
- if (navigator.cpuClass)
- {
- strTmp += strSep + navigator.cpuClass;
- }
- // navigator.browserLanguage only supported in IE, Safari and Chrome
- if (navigator.browserLanguage)
- {
- strTmp += strSep + navigator.browserLanguage;
- }
- else
- {
- strTmp += strSep + navigator.language;
- }
- return strTmp;
- }
- //////////////////////////////////////////////////////////////////////////
- // //
- // THE BELOW FUNCTIONS ARE _ALL_ FOR PLUGIN FINGERPRINTING! //
- // //
- //////////////////////////////////////////////////////////////////////////
- // plugin fingerprinting, self explanitory... just get a list of plugins.
- // IE can only query against a list, so its not as good, as it will only return a subset of the list below.
- // entropy: ~15.4 bits
- this.pluginsFingerprint = function()
- {
- var strKey, strName, strVersion, strTemp, bolFirst, iCount, strMimeType;
- var strSep ="|";
- var strPair ="=";
- //IE doesnt have a method to get plugins, so enumerate off a list of known ones.
- var pluginHash = {
- '7790769C-0471-11D2-AF11-00C04FA35D02': 'AddressBook', // Address Book
- '47F67D00-9E55-11D1-BAEF-00C04FC2D130': 'AolArtFormat', // AOL ART Image Format Support
- '76C19B38-F0C8-11CF-87CC-0020AFEECF20': 'ArabicDS', // Arabic Text Display Support
- '76C19B34-F0C8-11CF-87CC-0020AFEECF20': 'ChineseSDS', // Chinese (Simplified) Text Display Support
- '76C19B33-F0C8-11CF-87CC-0020AFEECF20': 'ChineseTDS', // Chinese (traditional) Text Display Support
- '238F6F83-B8B4-11CF-8771-00A024541EE3': 'CitrixICA', // Citrix ICA Client
- '283807B5-2C60-11D0-A31D-00AA00B92C03': 'DirectAnim', // DirectAnimation
- '44BBA848-CC51-11CF-AAFA-00AA00B6015C': 'DirectShow', // DirectShow
- '9381D8F2-0288-11D0-9501-00AA00B911A5': 'DynHTML', // Dynamic HTML Data Binding
- '4F216970-C90C-11D1-B5C7-0000F8051515': 'DynHTML4Java', // Dynamic HTML Data Binding for Java
- 'D27CDB6E-AE6D-11CF-96B8-444553540000': 'Flash', // Macromedia Flash
- '76C19B36-F0C8-11CF-87CC-0020AFEECF20': 'HebrewDS', // Hebrew Text Display Support
- '630B1DA0-B465-11D1-9948-00C04F98BBC9': 'IEBrwEnh', // Internet Explorer Browsing Enhancements
- '08B0E5C0-4FCB-11CF-AAA5-00401C608555': 'IEClass4Java', // Internet Explorer Classes for Java
- '45EA75A0-A269-11D1-B5BF-0000F8051515': 'IEHelp', // Internet Explorer Help
- 'DE5AED00-A4BF-11D1-9948-00C04F98BBC9': 'IEHelpEng', // Internet Explorer Help Engine
- '89820200-ECBD-11CF-8B85-00AA005B4383': 'IE5WebBrw', // Internet Explorer 5/6 Web Browser
- '5A8D6EE0-3E18-11D0-821E-444553540000': 'InetConnectionWiz', // Internet Connection Wizard
- '76C19B30-F0C8-11CF-87CC-0020AFEECF20': 'JapaneseDS', // Japanese Text Display Support
- '76C19B31-F0C8-11CF-87CC-0020AFEECF20': 'KoreanDS', // Korean Text Display Support
- '76C19B50-F0C8-11CF-87CC-0020AFEECF20': 'LanguageAS', // Language Auto-Selection
- '08B0E5C0-4FCB-11CF-AAA5-00401C608500': 'MsftVM', // Microsoft virtual machine
- '5945C046-LE7D-LLDL-BC44-00C04FD912BE': 'MSNMessengerSrv', // MSN Messenger Service
- '44BBA842-CC51-11CF-AAFA-00AA00B6015B': 'NetMeetingNT', // NetMeeting NT
- '3AF36230-A269-11D1-B5BF-0000F8051515': 'OfflineBrwPack', // Offline Browsing Pack
- '44BBA840-CC51-11CF-AAFA-00AA00B6015C': 'OutlookExpress', // Outlook Express
- '76C19B32-F0C8-11CF-87CC-0020AFEECF20': 'PanEuropeanDS', // Pan-European Text Display Support
- '4063BE15-3B08-470D-A0D5-B37161CFFD69': 'QuickTime', // Apple Quick Time
- 'DE4AF3B0-F4D4-11D3-B41A-0050DA2E6C21': 'QuickTimeCheck', // Apple Quick Time Check
- '3049C3E9-B461-4BC5-8870-4C09146192CA': 'RealPlayer', // RealPlayer Download and Record Plugin for IE
- '2A202491-F00D-11CF-87CC-0020AFEECF20': 'ShockwaveDir', // Macromedia Shockwave Director
- '3E01D8E0-A72B-4C9F-99BD-8A6E7B97A48D': 'Skype', // Skype
- 'CC2A9BA0-3BDD-11D0-821E-444553540000': 'TaskScheduler', // Task Scheduler
- '76C19B35-F0C8-11CF-87CC-0020AFEECF20': 'ThaiDS', // Thai Text Display Support
- '3BF42070-B3B1-11D1-B5C5-0000F8051515': 'Uniscribe', // Uniscribe
- '4F645220-306D-11D2-995D-00C04F98BBC9': 'VBScripting', // Visual Basic Scripting Support v5.6
- '76C19B37-F0C8-11CF-87CC-0020AFEECF20': 'VietnameseDS', // Vietnamese Text Display Support
- '10072CEC-8CC1-11D1-986E-00A0C955B42F': 'VML', // Vector Graphics Rendering (VML)
- '90E2BA2E-DD1B-4CDE-9134-7A8B86D33CA7': 'WebEx', // WebEx Productivity Tools
- '73FA19D0-2D75-11D2-995D-00C04F98BBC9': 'WebFolders', // Web Folders
- '89820200-ECBD-11CF-8B85-00AA005B4340': 'WinDesktopUpdateNT', // Windows Desktop Update NT
- '9030D464-4C02-4ABF-8ECC-5164760863C6': 'WinLive', // Windows Live ID Sign-in Helper
- '6BF52A52-394A-11D3-B153-00C04F79FAA6': 'WinMediaPlayer', // Windows Media Player (Versions 7, 8 or 9)
- '22D6F312-B0F6-11D0-94AB-0080C74C7E95': 'WinMediaPlayerTrad' // Windows Media Player (Traditional Versions)
- }
- strTemp = "";
- bolFirst = true;
- //if the browser supports a list of plugins, just go though and append them to a list!
- if (navigator.plugins.length > 0)
- {
- for (iCount = 0; iCount < navigator.plugins.length; iCount++)
- {
- if (bolFirst === true)
- {
- strTemp += navigator.plugins[iCount].name;
- bolFirst = false;
- }
- else
- {
- strTemp += strSep + navigator.plugins[iCount].name;
- }
- }
- }
- //if we cant get plugins, just report back a list of mimeTypes.
- else if (navigator.mimeTypes.length > 0)
- {
- strMimeType = navigator.mimeTypes;
- for (iCount = 0; iCount < strMimeType.length; iCount++)
- {
- if (bolFirst === true)
- {
- strTemp += strMimeType[iCount].description;
- bolFirst = false;
- }
- else
- {
- strTemp += strSep + strMimeType[iCount].description;
- }
- }
- }
- //if none of that worked, the browser is IE, so we need to enumerate off the list above
- else if ("addBehavior" in document.body && typeof document.body.addBehavior === "function")
- {
- document.body.addBehavior("#default#clientCaps");
- for (var key in pluginHash)
- {
- strVersion = activeXDetect(key); //query the hash against activex
- strName = pluginHash[key];
- if (strVersion)
- {
- if (bolFirst === true)
- {
- strTemp = strName + strPair + strVersion;
- bolFirst = false;
- }
- else
- {
- strTemp += strSep + strName + strPair + strVersion;
- }
- }
- }
- strTemp = strTemp.replace(/,/g, ".");
- }
- else
- {
- return "None|phone";
- }
- strTemp = stripIllegalChars(strTemp);
- if (strTemp === "")
- {
- strTemp = "None";
- }
- return strTemp;
- }
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////////
- // //
- // Below functions are helper functions that are not exposed in the returned fingerprint object //
- // //
- /////////////////////////////////////////////////////////////////////////////////////////////////
- // This function queries IE plugins though the getComponentVersion method, and returns if the plugin is active.
- // Called from pluginsFingerprint() and not exposed in the returned fingerprint object.
- function activeXDetect(componentClassID)
- {
- var strComponentVersion;
- strComponentVersion = "";
- try
- {
- strComponentVersion = document.body.getComponentVersion('{' + componentClassID + '}', 'ComponentID');
- if (strComponentVersion !== null)
- {
- return strComponentVersion;
- }
- else
- {
- return false;
- }
- }
- catch (err)
- {
- return err;
- }
- }
- // This function will remove illegal characters from a string. (removes "\\" "/" and "\n". newlines are changed to 'n'
- // Called from pluginsFingerprint() and not exposed in the returned fingerprint object.
- function stripIllegalChars(strValue)
- {
- var iCounter, strOriginal, strOut;
- iCounter = 0;
- strOriginal = "";
- strOut = "";
- try
- {
- strOriginal = strValue.toLowerCase();
- //itterate though the string.
- for (iCounter = 0; iCounter < strOriginal.length; iCounter = iCounter + 1)
- {
- //if the character is allowed, add it to the string, else we will skip over it (unless its a new line).
- if (strOriginal.charAt(iCounter) !== '\n' && strOriginal.charAt(iCounter) !== '/' && strOriginal.charAt(iCounter) !== "\\")
- {
- strOut = strOut + strOriginal.charAt(iCounter);
- }
- //replace the newlines with just an 'n'
- else if (strOriginal.charAt(iCounter) === '\n')
- {
- strOut = strOut + "n";
- }
- }
- return strOut;
- }
- catch (err)
- {
- return err;
- }
- }
- return fingerprinter;
- })();
Add Comment
Please, Sign In to add comment