Guest User

Untitled

a guest
Jul 13th, 2016
281
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 42.46 KB | None | 0 0
  1. var Fingerprinter = (function(){
  2. "use strict"
  3.  
  4. function fingerprinter()
  5. {
  6. this.FingerPrintHash = "";
  7.  
  8. // a super function to call everything else below, and compute the md5 of the concat output.
  9. // if you are trying to get a fingerprint of a user, this is the function to use.
  10. // ~82 bits entropy. =wow=
  11. this.superPrint = function()
  12. {
  13. var strConcat = "";
  14. var strSep = ";";
  15.  
  16. //if(this.FingerPrintHash)
  17. //{
  18. //if the fingerprint is requested twice on the same page, return whats stored in JS, this is the fastest method.
  19. //return this.FingerPrintHash;
  20. //}
  21.  
  22. strConcat += this.flashVersion() + strSep + this.browserVersion() + this.canvasFingerprint() + strSep + this.androidConnectType() + strSep + this.cookiesEnabled() + strSep;
  23. strConcat += this.screenInfo() + strSep + this.fontSmoothing() + strSep + this.html5LocalStorage() + strSep + this.fontsFingerprint() + strSep + this. javaEnabled() + strSep + this.language() + strSep;
  24. strConcat += this.silverlightVersion() + strSep + this.osDetect() + strSep + this.timeZone() + strSep + this.hasTouchScreen() + strSep + this.userAgentImproved() + strSep + this.pluginsFingerprint();
  25.  
  26. strConcat = md5(strConcat);
  27.  
  28. //check to see if the stored fingerprint differs, and if it does update.
  29. if(localStorage.getItem("fingerprint"))
  30. {
  31. if(localStorage.getItem("fingerprint") != strConcat)
  32. {
  33. //code to update the fingerprint on the userStore.
  34. console.log("fingerprint differs!, was: "+ localStorage.getItem("fingerprint")+" but is now: " + strConcat );
  35. }
  36. }
  37.  
  38. //save the fingerprint locally in case theres a bad bit of code that rapidly calls this.
  39. this.FingerPrintHash = strConcat;
  40. if(this.html5LocalStorage())
  41. {
  42. localStorage.setItem("fingerprint",strConcat);
  43. }
  44.  
  45. return strConcat;
  46. }
  47.  
  48.  
  49. //////////////////////////////////////////////////////////////////////
  50. // //
  51. // The below functions can be used for fingerprint corrilation. //
  52. // //
  53. //////////////////////////////////////////////////////////////////
  54.  
  55. // gets the client IP address.
  56. // Since an IP address can change ( most isp's use dhcp ) we DON'T use this in superPrint().
  57. this.getPublicIP = function()
  58. {
  59. //TODO: do stuff here!
  60. //curl -s http://whatismyip.akamai.com/
  61. }
  62.  
  63. // android connection type: returns N/A, UNKNOWN, ETHERNET, WIFI, CELL_2G, CELL_3G, CELL_4G or NONE.
  64. // ~2.8 bits of entropy. more useful for determining fingerprint relations from phone <--> computer
  65. // Used in superPrint
  66. this.androidConnectType = function()
  67. {
  68. var strOnError;
  69.  
  70. strOnError = "N/A";
  71.  
  72. try
  73. {
  74. // only on android
  75. return navigator.connection.type;
  76. }
  77. catch (err)
  78. {
  79. // return N/A if navigator.connection object does not apply to this device
  80. return strOnError;
  81. }
  82. }
  83.  
  84. // touch support (identifies if there is a digitizer). IE 11 falsely reports no touch screen if there is one present.
  85. // This can be used in conjunction with the user agent to detect iphones, ipads, and windows phones. android should be detected with androidConnectType()
  86. // Entropy: TBD, expected to be <1 bit
  87. // used in superPrint
  88. this.hasTouchScreen = function()
  89. {
  90. try
  91. {
  92. if (document.createEvent("TouchEvent"))
  93. {
  94. return true;
  95. }
  96. return false;
  97. }
  98. catch (ignore)
  99. {
  100. return false;
  101. }
  102. }
  103.  
  104. // get the time zone of the client.
  105. // entropy ~3.04 bits
  106. // adds a small ammount of entropy to the phone <--> computer corrilation.
  107. // used in superPrint
  108. this.timeZone = function()
  109. {
  110. var strOnError, dtDate, numOffset, numGMTHours;
  111.  
  112. strOnError = "Error";
  113. dtDate = null;
  114. numOffset = null;
  115. numGMTHours = null;
  116.  
  117. try
  118. {
  119. dtDate = new Date();
  120. numOffset = dtDate.getTimezoneOffset();
  121. numGMTHours = (numOffset / 60) * (-1);
  122. return numGMTHours;
  123. }
  124. catch (err)
  125. {
  126. return strOnError;
  127. }
  128. }
  129.  
  130. //////////////////////////////////////////////////////////////////////////////////////////
  131. // //
  132. // The below functions are used in superPrint, but are not useful for corrilation //
  133. // //
  134. //////////////////////////////////////////////////////////////////////////////////////
  135.  
  136. this.html5LocalStorage = function()
  137. {
  138. if(typeof(Storage) !== "undefined")
  139. {
  140. return true;
  141. }
  142. else
  143. {
  144. return false;
  145. }
  146. }
  147.  
  148. // returns if cookies are enabled or not.
  149. // ~0.4 bits of entropy. better used to see how to store the fingerprint accross pages.
  150. this.cookiesEnabled = function()
  151. {
  152. var strOnError, bolCookieEnabled;
  153.  
  154. strOnError = "Error";
  155. bolCookieEnabled = null;
  156.  
  157. try
  158. {
  159. bolCookieEnabled = (navigator.cookieEnabled) ? true : false;
  160.  
  161. //if not IE4+ nor NS6+
  162. if (typeof navigator.cookieEnabled === "undefined" && !bolCookieEnabled)
  163. {
  164. document.cookie = "testcookie";
  165. bolCookieEnabled = (document.cookie.indexOf("testcookie") !== -1) ? true : false;
  166. }
  167. return bolCookieEnabled;
  168. }
  169. catch (err)
  170. {
  171. return strOnError;
  172. }
  173. }
  174.  
  175. // gets the version of flash
  176. // entropy = ~4.3 bits
  177. this.flashVersion = function()
  178. {
  179. var StrOnError,
  180. ObjPlayerVersion,
  181. StrVersion,
  182.  
  183. StrOnError = "N/A";
  184. ObjPlayerVersion = null;
  185. StrVersion = null;
  186.  
  187. try
  188. {
  189. ObjPlayerVersion = swfobject.getFlashPlayerVersion();
  190. StrVersion = objPlayerVersion.major + "." + objPlayerVersion.minor + "." + objPlayerVersion.release;
  191. if (StrVersion === "0.0.0")
  192. {
  193. StrVersion = "N/A";
  194. }
  195. return StrVersion;
  196. }
  197. catch (err)
  198. {
  199. return StrOnError;
  200. }
  201. }
  202.  
  203. // gets the browser version / name from the browser user adgent, can be unreliable.
  204. // entropy TBD
  205. this.browserVersion = function()
  206. {
  207. var strOnError, strUserAgent, numVersion, strBrowser;
  208.  
  209. strOnError = "Error";
  210. strUserAgent = null;
  211. numVersion = null;
  212. strBrowser = null;
  213.  
  214. try
  215. {
  216. strUserAgent = navigator.userAgent.toLowerCase();
  217. if (/msie (\d+\.\d+);/.test(strUserAgent))
  218. { //test for MSIE x.x;
  219. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  220. if (strUserAgent.indexOf("trident/6") > -1)
  221. {
  222. numVersion = 10;
  223. }
  224. if (strUserAgent.indexOf("trident/5") > -1)
  225. {
  226. numVersion = 9;
  227. }
  228. if (strUserAgent.indexOf("trident/4") > -1)
  229. {
  230. numVersion = 8;
  231. }
  232. strBrowser = "Internet Explorer " + numVersion;
  233. }
  234. else if (strUserAgent.indexOf("trident/7") > -1)
  235. { //IE 11+ gets rid of the legacy 'MSIE' in the user-agent string;
  236. numVersion = 11;
  237. strBrowser = "Internet Explorer " + numVersion;
  238. }
  239. else if (/firefox[\/\s](\d+\.\d+)/.test(strUserAgent))
  240. { //test for Firefox/x.x or Firefox x.x (ignoring remaining digits);
  241. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  242. strBrowser = "Firefox " + numVersion;
  243. }
  244. else if (/opera[\/\s](\d+\.\d+)/.test(strUserAgent))
  245. { //test for Opera/x.x or Opera x.x (ignoring remaining decimal places);
  246. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  247. strBrowser = "Opera " + numVersion;
  248. }
  249. else if (/chrome[\/\s](\d+\.\d+)/.test(strUserAgent))
  250. { //test for Chrome/x.x or Chrome x.x (ignoring remaining digits);
  251. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  252. strBrowser = "Chrome " + numVersion;
  253. }
  254. else if (/version[\/\s](\d+\.\d+)/.test(strUserAgent))
  255. { //test for Version/x.x or Version x.x (ignoring remaining digits);
  256. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  257. strBrowser = "Safari " + numVersion;
  258. }
  259. else if (/rv[\/\s](\d+\.\d+)/.test(strUserAgent))
  260. { //test for rv/x.x or rv x.x (ignoring remaining digits);
  261. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  262. strBrowser = "Mozilla " + numVersion;
  263. }
  264. else if (/mozilla[\/\s](\d+\.\d+)/.test(strUserAgent))
  265. { //test for Mozilla/x.x or Mozilla x.x (ignoring remaining digits);
  266. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  267. strBrowser = "Mozilla " + numVersion;
  268. }
  269. else if (/binget[\/\s](\d+\.\d+)/.test(strUserAgent))
  270. { //test for BinGet/x.x or BinGet x.x (ignoring remaining digits);
  271. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  272. strBrowser = "Library (BinGet) " + numVersion;
  273. }
  274. else if (/curl[\/\s](\d+\.\d+)/.test(strUserAgent))
  275. { //test for Curl/x.x or Curl x.x (ignoring remaining digits);
  276. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  277. strBrowser = "Library (cURL) " + numVersion;
  278. }
  279. else if (/java[\/\s](\d+\.\d+)/.test(strUserAgent))
  280. { //test for Java/x.x or Java x.x (ignoring remaining digits);
  281. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  282. strBrowser = "Library (Java) " + numVersion;
  283. }
  284. else if (/libwww-perl[\/\s](\d+\.\d+)/.test(strUserAgent))
  285. { //test for libwww-perl/x.x or libwww-perl x.x (ignoring remaining digits);
  286. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  287. strBrowser = "Library (libwww-perl) " + numVersion;
  288. }
  289. else if (/microsoft url control -[\s](\d+\.\d+)/.test(strUserAgent))
  290. { //test for Microsoft URL Control - x.x (ignoring remaining digits);
  291. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  292. strBrowser = "Library (Microsoft URL Control) " + numVersion;
  293. }
  294. else if (/peach[\/\s](\d+\.\d+)/.test(strUserAgent))
  295. { //test for Peach/x.x or Peach x.x (ignoring remaining digits);
  296. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  297. strBrowser = "Library (Peach) " + numVersion;
  298. }
  299. else if (/php[\/\s](\d+\.\d+)/.test(strUserAgent))
  300. { //test for PHP/x.x or PHP x.x (ignoring remaining digits);
  301. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  302. strBrowser = "Library (PHP) " + numVersion;
  303. }
  304. else if (/pxyscand[\/\s](\d+\.\d+)/.test(strUserAgent))
  305. { //test for pxyscand/x.x or pxyscand x.x (ignoring remaining digits);
  306. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  307. strBrowser = "Library (pxyscand) " + numVersion;
  308. }
  309. else if (/pycurl[\/\s](\d+\.\d+)/.test(strUserAgent))
  310. { //test for pycurl/x.x or pycurl x.x (ignoring remaining digits);
  311. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  312. strBrowser = "Library (PycURL) " + numVersion;
  313. }
  314. else if (/python-urllib[\/\s](\d+\.\d+)/.test(strUserAgent))
  315. { //test for python-urllib/x.x or python-urllib x.x (ignoring remaining digits);
  316. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  317. strBrowser = "Library (Python URLlib) " + numVersion;
  318. }
  319. else if (/appengine-google/.test(strUserAgent))
  320. { //test for AppEngine-Google;
  321. numVersion = Number(RegExp.$1); // capture x.x portion and store as a number
  322. strBrowser = "Cloud (Google AppEngine) " + numVersion;
  323. }
  324. else
  325. {
  326. strBrowser = "Unknown";
  327. }
  328.  
  329. return strBrowser;
  330. }
  331. catch (err)
  332. {
  333. return strOnError;
  334. }
  335. }
  336.  
  337. // canvas - uses graphics driver and gpu.
  338. // generate a string and turn it into a 2d image, the base64 of the image will be slightly different based on hardware / render engine.
  339. // entropy ~10.8 bits
  340. this.canvasFingerprint = function()
  341. {
  342. var strOnError, canvas, strCText, strText;
  343.  
  344. strOnError = "Error";
  345. canvas = null;
  346. strCText = null;
  347. strText = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`~1!2@3#4$5%6^7&8*9(0)-_=+[{]}|;:',<.>/?";
  348.  
  349. try
  350. {
  351. canvas = document.createElement('canvas');
  352. strCText = canvas.getContext('2d');
  353. strCText.textBaseline = "top";
  354. strCText.font = "14px 'Arial'";
  355. strCText.textBaseline = "alphabetic";
  356. strCText.fillStyle = "#f60";
  357. strCText.fillRect(125, 1, 62, 20);
  358. strCText.fillStyle = "#069";
  359. strCText.fillText(strText, 2, 15);
  360. strCText.fillStyle = "rgba(102, 204, 0, 0.7)";
  361. strCText.fillText(strText, 4, 17);
  362.  
  363. return md5(canvas.toDataURL()); //return the base64 of the canvas image.
  364. }
  365. catch (err)
  366. {
  367. return strOnError;
  368. }
  369. }
  370.  
  371. // returns a concat string of numerical display data. <color depth>|<screen width>|<screen height>|<window width>|<window height>
  372. // entropy ~8.8 bits
  373. this.screenInfo = function()
  374. {
  375. var strSep, strPair, strOnError, strScreen, strDisplay;
  376.  
  377. strSep = "|";
  378. strPair = "=";
  379. strOnError = "Error";
  380. strScreen = null;
  381. strDisplay = null;
  382.  
  383. try
  384. {
  385. strScreen = window.screen;
  386. if (strScreen)
  387. {
  388. strDisplay = strScreen.colorDepth + strSep + strScreen.width + strSep + strScreen.height + strSep + strScreen.availWidth + strSep + strScreen.availHeight;
  389. }
  390. return strDisplay;
  391. }
  392. catch (err)
  393. {
  394. return strOnError;
  395. }
  396. }
  397.  
  398. // font smoothing, returns true if enabled. flase if disabled, or unknown if undeterministic.
  399. // entropy ~0.4 bits
  400. this.fontSmoothing = function()
  401. {
  402. var strFontSmoothing, canvasNode, ctx, i, j, imageData, alpha, strOnError;
  403.  
  404. strOnError = "Unknown";
  405. canvasNode = null;
  406. ctx = null;
  407. imageData = null;
  408. alpha = null;
  409.  
  410. if (typeof(screen.fontSmoothingEnabled) !== "undefined")
  411. {
  412. return screen.fontSmoothingEnabled;
  413. }
  414. //browser cant report back if smoothing is enabled, so we just test ourselves.
  415. else
  416. {
  417. try
  418. {
  419. fontsmoothing = "false";
  420.  
  421. //create a canvas element and put a 'O' in the top left.
  422. canvasNode = document.createElement('canvas');
  423. canvasNode.width = "35";
  424. canvasNode.height = "35";
  425. canvasNode.style.display = 'none';
  426. document.body.appendChild(canvasNode);
  427. ctx = canvasNode.getContext('2d');
  428. ctx.textBaseline = "top";
  429. ctx.font = "32px Arial";
  430. ctx.fillStyle = "black";
  431. ctx.strokeStyle = "black";
  432. ctx.fillText("O", 0, 0);
  433.  
  434. //Itterate over the 'O' pixel by pixel.
  435. for (j = 8; j <= 32; j = j + 1)
  436. {
  437. for (i = 1; i <= 32; i = i + 1)
  438. {
  439. imageData = ctx.getImageData(i, j, 1, 1).data;
  440. alpha = imageData[3];
  441.  
  442. //if a pixel has a value other than 0 or 255, the folt is being smoothed.
  443. if (alpha !== 255 && alpha !== 0)
  444. {
  445. return "true"; // font-smoothing must be on.
  446. }
  447. }
  448. }
  449.  
  450. //no font smoothing detected.
  451. return "false";
  452.  
  453. }
  454. catch (err)
  455. {
  456. return strOnError;
  457. }
  458. }
  459. }
  460.  
  461. // fonts - gets the md5 of the fonts installed.
  462. // entropy ~13.9 bits
  463. this.fontsFingerprint = function()
  464. {
  465. var strOnError, style, fonts, count, template, fragment, divs, i, font, div, body, result, e;
  466.  
  467. strOnError = "Error";
  468. style = null;
  469. fonts = null;
  470. font = null;
  471. count = 0;
  472. template = null;
  473. divs = null;
  474. e = null;
  475. div = null;
  476. body = null;
  477. i = 0;
  478.  
  479. try
  480. {
  481. style = "position: absolute; visibility: hidden; display: block !important";
  482. 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"];
  483. count = fonts.length;
  484.  
  485. 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>';
  486. fragment = document.createDocumentFragment();
  487. divs = [];
  488.  
  489. for (i = 0; i < count; i = i + 1)
  490. {
  491. font = fonts[i];
  492. div = document.createElement('div');
  493. 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
  494. div.innerHTML = template.replace(/X/g, font);
  495. div.style.cssText = style;
  496. fragment.appendChild(div);
  497. divs.push(div);
  498. }
  499.  
  500. body = document.body;
  501. body.insertBefore(fragment, body.firstChild);
  502. result = [];
  503.  
  504. for (i = 0; i < count; i = i + 1)
  505. {
  506. e = divs[i].getElementsByTagName('b');
  507. if (e[0].offsetWidth === e[1].offsetWidth)
  508. {
  509. result.push(fonts[i]);
  510. }
  511. }
  512. // do not combine these two loops, remove child will cause reflow
  513. // and induce severe performance hit
  514. for (i = 0; i < count; i = i + 1)
  515. {
  516. body.removeChild(divs[i]);
  517. }
  518. return md5(result.join('|'));
  519. }
  520. catch (err)
  521. {
  522. return strOnError;
  523. }
  524. }
  525.  
  526. // java enabled - returns a bool for if it is enabled.
  527. // entropy ~1 bit.
  528. this.javaEnabled = function()
  529. {
  530. if(navigator.javaEnabled === "function")
  531. {
  532. if (navigator.javaEnabled())
  533. {
  534. return "true";
  535. }
  536. else
  537. {
  538. return "false";
  539. }
  540. }
  541. else
  542. {
  543. return "false";
  544. }
  545. }
  546.  
  547. // gets the language of the user computer
  548. // entropy ~10 bits
  549. this.language = function()
  550. {
  551. var strSep, strPair, strOnError, strLang, strTypeLng, strTypeBrLng, strTypeSysLng, strTypeUsrLng;
  552.  
  553. strSep = "|";
  554. strPair = "=";
  555. strOnError = "Error";
  556. strLang = null;
  557. strTypeLng = null;
  558. strTypeBrLng = null;
  559. strTypeSysLng = null;
  560. strTypeUsrLng = null;
  561.  
  562. try
  563. {
  564. strTypeLng = typeof (navigator.language);
  565. strTypeBrLng = typeof (navigator.browserLanguage);
  566. strTypeSysLng = typeof (navigator.systemLanguage);
  567. strTypeUsrLng = typeof (navigator.userLanguage);
  568.  
  569. if (strTypeLng !== "undefined")
  570. {
  571. strLang = "lang" + strPair + navigator.language + strSep;
  572. }
  573. else if (strTypeBrLng !== "undefined")
  574. {
  575. strLang = "lang" + strPair + navigator.browserLanguage + strSep;
  576. }
  577. else
  578. {
  579. strLang = "lang" + strPair + strSep;
  580. }
  581.  
  582. if (strTypeSysLng !== "undefined")
  583. {
  584. strLang += "syslang" + strPair + navigator.systemLanguage + strSep;
  585. }
  586. else
  587. {
  588. strLang += "syslang" + strPair + strSep;
  589. }
  590.  
  591. if (strTypeUsrLng !== "undefined")
  592. {
  593. strLang += "userlang" + strPair + navigator.userLanguage;
  594. }
  595. else
  596. {
  597. strLang += "userlang" + strPair;
  598. }
  599.  
  600. return strLang;
  601. }
  602. catch (err)
  603. {
  604. return strOnError;
  605. }
  606. }
  607.  
  608. // find the version of silverlight. returns n/a if not installed.
  609. // entropy ~1.8 bits
  610. this.silverlightVersion = function()
  611. {
  612. var strOnError, objControl, objPlugin, strSilverlightVersion;
  613.  
  614. strOnError = "Error";
  615. objControl = null;
  616. objPlugin = null;
  617. strSilverlightVersion = null;
  618.  
  619. try
  620. {
  621. try
  622. {
  623. objControl = new ActiveXObject('AgControl.AgControl');
  624. if (objControl.IsVersionSupported("5.0"))
  625. {
  626. strSilverlightVersion = "5.x";
  627. }
  628. else if (objControl.IsVersionSupported("4.0"))
  629. {
  630. strSilverlightVersion = "4.x";
  631. }
  632. else if (objControl.IsVersionSupported("3.0"))
  633. {
  634. strSilverlightVersion = "3.x";
  635. }
  636. else if (objControl.IsVersionSupported("2.0"))
  637. {
  638. strSilverlightVersion = "2.x";
  639. }
  640. else
  641. {
  642. strSilverlightVersion = "1.x";
  643. }
  644. objControl = null;
  645. }
  646. catch (e)
  647. {
  648. objPlugin = navigator.plugins["Silverlight Plug-In"];
  649. if (objPlugin)
  650. {
  651. if (objPlugin.description === "1.0.30226.2")
  652. {
  653. strSilverlightVersion = "2.x";
  654. }
  655. else
  656. {
  657. strSilverlightVersion = parseInt(objPlugin.description[0], 10);
  658. }
  659. }
  660. else
  661. {
  662. strSilverlightVersion = "N/A";
  663. }
  664. }
  665. return strSilverlightVersion;
  666. }
  667. catch (err)
  668. {
  669. return strOnError;
  670. }
  671. }
  672.  
  673. // OS name and architecture.
  674. // entropy ~1.2 bits
  675. this.osDetect = function()
  676. {
  677. var strSep, strOnError, strUserAgent, strPlatform, strOS, strOSBits;
  678.  
  679. strSep = "|";
  680. strOnError = "Error";
  681. strUserAgent = null;
  682. strPlatform = null;
  683. strOS = null;
  684. strOSBits = null;
  685.  
  686. try
  687. {
  688. // navigator.userAgent is supported by all major browsers
  689. strUserAgent = navigator.userAgent.toLowerCase();
  690. // navigator.platform is supported by all major browsers
  691. strPlatform = navigator.platform.toLowerCase();
  692. if (strUserAgent.indexOf("windows nt 10.0") !== -1) { strOS = "Windows 10"; } //currently fails on IE11, it inaccurately reports it as nt 6.3
  693. else if (strUserAgent.indexOf("windows nt 6.3") !== -1) { strOS = "Windows 8.1"; }
  694. else if (strUserAgent.indexOf("windows nt 6.2") !== -1) { strOS = "Windows 8"; }
  695. else if (strUserAgent.indexOf("windows nt 6.1") !== -1) { strOS = "Windows 7"; }
  696. else if (strUserAgent.indexOf("windows nt 6.0") !== -1) { strOS = "Windows Vista/Windows Server 2008"; }
  697. else if (strUserAgent.indexOf("windows nt 5.2") !== -1) { strOS = "Windows XP x64/Windows Server 2003"; }
  698. else if (strUserAgent.indexOf("windows nt 5.1") !== -1) { strOS = "Windows XP"; }
  699. else if (strUserAgent.indexOf("windows nt 5.01") !== -1) { strOS = "Windows 2000, Service Pack 1 (SP1)"; }
  700. else if (strUserAgent.indexOf("windows xp") !== -1) { strOS = "Windows XP"; }
  701. else if (strUserAgent.indexOf("windows 2000") !== -1) { strOS = "Windows 2000"; }
  702. else if (strUserAgent.indexOf("windows nt 5.0") !== -1) { strOS = "Windows 2000"; }
  703. else if (strUserAgent.indexOf("windows nt 4.0") !== -1) { strOS = "Windows NT 4.0"; }
  704. else if (strUserAgent.indexOf("windows nt") !== -1) { strOS = "Windows NT 4.0"; }
  705. else if (strUserAgent.indexOf("winnt4.0") !== -1) { strOS = "Windows NT 4.0"; }
  706. else if (strUserAgent.indexOf("winnt") !== -1) { strOS = "Windows NT 4.0"; }
  707. else if (strUserAgent.indexOf("windows me") !== -1) { strOS = "Windows ME"; }
  708. else if (strUserAgent.indexOf("win 9x 4.90") !== -1) { strOS = "Windows ME"; }
  709. else if (strUserAgent.indexOf("windows 98") !== -1) { strOS = "Windows 98"; }
  710. else if (strUserAgent.indexOf("win98") !== -1) { strOS = "Windows 98"; }
  711. else if (strUserAgent.indexOf("windows 95") !== -1) { strOS = "Windows 95"; }
  712. else if (strUserAgent.indexOf("windows_95") !== -1) { strOS = "Windows 95"; }
  713. else if (strUserAgent.indexOf("win95") !== -1) { strOS = "Windows 95"; }
  714. else if (strUserAgent.indexOf("ce") !== -1) { strOS = "Windows CE"; }
  715. else if (strUserAgent.indexOf("win16") !== -1) { strOS = "Windows 3.11"; }
  716. else if (strUserAgent.indexOf("iemobile") !== -1) { strOS = "Windows Mobile"; }
  717. else if (strUserAgent.indexOf("wm5 pie") !== -1) { strOS = "Windows Mobile"; }
  718. else if (strUserAgent.indexOf("windows") !== -1) { strOS = "Windows (Unknown Version)"; }
  719. else if (strUserAgent.indexOf("openbsd") !== -1) { strOS = "Open BSD"; }
  720. else if (strUserAgent.indexOf("sunos") !== -1) { strOS = "Sun OS"; }
  721. else if (strUserAgent.indexOf("ubuntu") !== -1) { strOS = "Ubuntu"; }
  722. else if (strUserAgent.indexOf("ipad") !== -1) { strOS = "iOS (iPad)"; }
  723. else if (strUserAgent.indexOf("ipod") !== -1) { strOS = "iOS (iTouch)"; }
  724. else if (strUserAgent.indexOf("iphone") !== -1) { strOS = "iOS (iPhone)"; }
  725. else if (strUserAgent.indexOf("mac os x beta") !== -1) { strOS = "Mac OSX Beta (Kodiak)"; }
  726. else if (strUserAgent.indexOf("mac os x 10.0") !== -1) { strOS = "Mac OSX Cheetah"; }
  727. else if (strUserAgent.indexOf("mac os x 10.1") !== -1) { strOS = "Mac OSX Puma"; }
  728. else if (strUserAgent.indexOf("mac os x 10.2") !== -1) { strOS = "Mac OSX Jaguar"; }
  729. else if (strUserAgent.indexOf("mac os x 10.3") !== -1) { strOS = "Mac OSX Panther"; }
  730. else if (strUserAgent.indexOf("mac os x 10.4") !== -1) { strOS = "Mac OSX Tiger"; }
  731. else if (strUserAgent.indexOf("mac os x 10.5") !== -1) { strOS = "Mac OSX Leopard"; }
  732. else if (strUserAgent.indexOf("mac os x 10.6") !== -1) { strOS = "Mac OSX Snow Leopard"; }
  733. else if (strUserAgent.indexOf("mac os x 10.7") !== -1) { strOS = "Mac OSX Lion"; }
  734. else if (strUserAgent.indexOf("mac os x") !== -1) { strOS = "Mac OSX (Version Unknown)"; }
  735. else if (strUserAgent.indexOf("mac_68000") !== -1) { strOS = "Mac OS Classic (68000)"; }
  736. else if (strUserAgent.indexOf("68K") !== -1) { strOS = "Mac OS Classic (68000)";}
  737. else if (strUserAgent.indexOf("mac_powerpc") !== -1) { strOS = "Mac OS Classic (PowerPC)"; }
  738. else if (strUserAgent.indexOf("ppc mac") !== -1) { strOS = "Mac OS Classic (PowerPC)"; }
  739. else if (strUserAgent.indexOf("macintosh") !== -1) { strOS = "Mac OS Classic"; }
  740. else if (strUserAgent.indexOf("googletv") !== -1) { strOS = "Android (GoogleTV)"; }
  741. else if (strUserAgent.indexOf("xoom") !== -1) { strOS = "Android (Xoom)"; }
  742. else if (strUserAgent.indexOf("htc_flyer") !== -1) { strOS = "Android (HTC Flyer)"; }
  743. else if (strUserAgent.indexOf("android") !== -1) { strOS = "Android"; }
  744. else if (strUserAgent.indexOf("symbian") !== -1) { strOS = "Symbian"; }
  745. else if (strUserAgent.indexOf("series60") !== -1) { strOS = "Symbian (Series 60)"; }
  746. else if (strUserAgent.indexOf("series70") !== -1) { strOS = "Symbian (Series 70)"; }
  747. else if (strUserAgent.indexOf("series80") !== -1) { strOS = "Symbian (Series 80)"; }
  748. else if (strUserAgent.indexOf("series90") !== -1) { strOS = "Symbian (Series 90)"; }
  749. else if (strUserAgent.indexOf("x11") !== -1) { strOS = "UNIX"; }
  750. else if (strUserAgent.indexOf("nix") !== -1) { strOS = "UNIX"; }
  751. else if (strUserAgent.indexOf("linux") !== -1) { strOS = "Linux"; }
  752. else if (strUserAgent.indexOf("qnx") !== -1) { strOS = "QNX"; }
  753. else if (strUserAgent.indexOf("os/2") !== -1) { strOS = "IBM OS/2"; }
  754. else if (strUserAgent.indexOf("beos") !== -1) { strOS = "BeOS"; }
  755. else if (strUserAgent.indexOf("blackberry95") !== -1) { strOS = "Blackberry (Storm 1/2)"; }
  756. else if (strUserAgent.indexOf("blackberry97") !== -1) { strOS = "Blackberry (Bold)"; }
  757. else if (strUserAgent.indexOf("blackberry96") !== -1) { strOS = "Blackberry (Tour)"; }
  758. else if (strUserAgent.indexOf("blackberry89") !== -1) { strOS = "Blackberry (Curve 2)"; }
  759. else if (strUserAgent.indexOf("blackberry98") !== -1) { strOS = "Blackberry (Torch)"; }
  760. else if (strUserAgent.indexOf("playbook") !== -1) { strOS = "Blackberry (Playbook)"; }
  761. else if (strUserAgent.indexOf("wnd.rim") !== -1) { strOS = "Blackberry (IE/FF Emulator)"; }
  762. else if (strUserAgent.indexOf("blackberry") !== -1) { strOS = "Blackberry"; }
  763. else if (strUserAgent.indexOf("palm") !== -1) { strOS = "Palm OS"; }
  764. else if (strUserAgent.indexOf("webos") !== -1) { strOS = "WebOS"; }
  765. else if (strUserAgent.indexOf("hpwos") !== -1) { strOS = "WebOS (HP)"; }
  766. else if (strUserAgent.indexOf("blazer") !== -1) { strOS = "Palm OS (Blazer)"; }
  767. else if (strUserAgent.indexOf("xiino") !== -1) { strOS = "Palm OS (Xiino)"; }
  768. else if (strUserAgent.indexOf("kindle") !== -1) { strOS = "Kindle"; }
  769. else if (strUserAgent.indexOf("wii") !== -1) { strOS = "Nintendo (Wii)"; }
  770. else if (strUserAgent.indexOf("nintendo ds") !== -1) { strOS = "Nintendo (DS)"; }
  771. else if (strUserAgent.indexOf("playstation 3") !== -1) { strOS = "Sony (Playstation Console)"; }
  772. else if (strUserAgent.indexOf("playstation portable") !== -1) { strOS = "Sony (Playstation Portable)"; }
  773. else if (strUserAgent.indexOf("webtv") !== -1) { strOS = "MSN TV (WebTV)"; }
  774. else if (strUserAgent.indexOf("inferno") !== -1) { strOS = "Inferno"; }
  775. else { strOS = "Unknown"; }
  776.  
  777.  
  778.  
  779. if (strPlatform.indexOf("x64") !== -1) { strOSBits = "64 bits"; }
  780. else if (strPlatform.indexOf("wow64") !== -1) { strOSBits = "64 bits"; }
  781. else if (strPlatform.indexOf("win64") !== -1) { strOSBits = "64 bits"; }
  782. else if (strPlatform.indexOf("win32") !== -1) { strOSBits = "32 bits"; }
  783. else if (strPlatform.indexOf("x64") !== -1) { strOSBits = "64 bits"; }
  784. else if (strPlatform.indexOf("x32") !== -1) { strOSBits = "32 bits"; }
  785. else if (strPlatform.indexOf("x86") !== -1) { strOSBits = "32 bits*"; }
  786. else if (strPlatform.indexOf("ppc") !== -1) { strOSBits = "64 bits"; }
  787. else if (strPlatform.indexOf("alpha") !== -1) { strOSBits = "64 bits"; }
  788. else if (strPlatform.indexOf("68k") !== -1) { strOSBits = "64 bits"; }
  789. else if (strPlatform.indexOf("iphone") !== -1) { strOSBits = "32 bits"; }
  790. else if (strPlatform.indexOf("android") !== -1) { strOSBits = "32 bits"; }
  791. else { strOSBits = "Unknown"; }
  792.  
  793. return (strOS + strSep + strOSBits);
  794. }
  795. catch (err)
  796. {
  797. return strOnError;
  798. }
  799. }
  800.  
  801. // get the user agent and append other information such as the platform and language, and cpuClass info.
  802. // entropy: ~11.5 bits, some bits will be the same as above calls. however the composit nature leads to unique hashes.
  803. this.userAgentImproved = function()
  804. {
  805. var strSep, strTmp, strUserAgent;
  806.  
  807. strSep = "|";
  808. strTmp = null;
  809. strUserAgent = null;
  810.  
  811. // navigator.userAgent is supported by all major browsers
  812. strUserAgent = navigator.userAgent.toLowerCase();
  813. // navigator.platform is supported by all major browsers
  814. strTmp = strUserAgent + strSep + navigator.platform;
  815. // navigator.cpuClass only supported in IE
  816. if (navigator.cpuClass)
  817. {
  818. strTmp += strSep + navigator.cpuClass;
  819. }
  820. // navigator.browserLanguage only supported in IE, Safari and Chrome
  821. if (navigator.browserLanguage)
  822. {
  823. strTmp += strSep + navigator.browserLanguage;
  824. }
  825. else
  826. {
  827. strTmp += strSep + navigator.language;
  828. }
  829. return strTmp;
  830. }
  831.  
  832. //////////////////////////////////////////////////////////////////////////
  833. // //
  834. // THE BELOW FUNCTIONS ARE _ALL_ FOR PLUGIN FINGERPRINTING! //
  835. // //
  836. //////////////////////////////////////////////////////////////////////////
  837.  
  838. // plugin fingerprinting, self explanitory... just get a list of plugins.
  839. // IE can only query against a list, so its not as good, as it will only return a subset of the list below.
  840. // entropy: ~15.4 bits
  841. this.pluginsFingerprint = function()
  842. {
  843.  
  844. var strKey, strName, strVersion, strTemp, bolFirst, iCount, strMimeType;
  845. var strSep ="|";
  846. var strPair ="=";
  847.  
  848. //IE doesnt have a method to get plugins, so enumerate off a list of known ones.
  849. var pluginHash = {
  850. '7790769C-0471-11D2-AF11-00C04FA35D02': 'AddressBook', // Address Book
  851. '47F67D00-9E55-11D1-BAEF-00C04FC2D130': 'AolArtFormat', // AOL ART Image Format Support
  852. '76C19B38-F0C8-11CF-87CC-0020AFEECF20': 'ArabicDS', // Arabic Text Display Support
  853. '76C19B34-F0C8-11CF-87CC-0020AFEECF20': 'ChineseSDS', // Chinese (Simplified) Text Display Support
  854. '76C19B33-F0C8-11CF-87CC-0020AFEECF20': 'ChineseTDS', // Chinese (traditional) Text Display Support
  855. '238F6F83-B8B4-11CF-8771-00A024541EE3': 'CitrixICA', // Citrix ICA Client
  856. '283807B5-2C60-11D0-A31D-00AA00B92C03': 'DirectAnim', // DirectAnimation
  857. '44BBA848-CC51-11CF-AAFA-00AA00B6015C': 'DirectShow', // DirectShow
  858. '9381D8F2-0288-11D0-9501-00AA00B911A5': 'DynHTML', // Dynamic HTML Data Binding
  859. '4F216970-C90C-11D1-B5C7-0000F8051515': 'DynHTML4Java', // Dynamic HTML Data Binding for Java
  860. 'D27CDB6E-AE6D-11CF-96B8-444553540000': 'Flash', // Macromedia Flash
  861. '76C19B36-F0C8-11CF-87CC-0020AFEECF20': 'HebrewDS', // Hebrew Text Display Support
  862. '630B1DA0-B465-11D1-9948-00C04F98BBC9': 'IEBrwEnh', // Internet Explorer Browsing Enhancements
  863. '08B0E5C0-4FCB-11CF-AAA5-00401C608555': 'IEClass4Java', // Internet Explorer Classes for Java
  864. '45EA75A0-A269-11D1-B5BF-0000F8051515': 'IEHelp', // Internet Explorer Help
  865. 'DE5AED00-A4BF-11D1-9948-00C04F98BBC9': 'IEHelpEng', // Internet Explorer Help Engine
  866. '89820200-ECBD-11CF-8B85-00AA005B4383': 'IE5WebBrw', // Internet Explorer 5/6 Web Browser
  867. '5A8D6EE0-3E18-11D0-821E-444553540000': 'InetConnectionWiz', // Internet Connection Wizard
  868. '76C19B30-F0C8-11CF-87CC-0020AFEECF20': 'JapaneseDS', // Japanese Text Display Support
  869. '76C19B31-F0C8-11CF-87CC-0020AFEECF20': 'KoreanDS', // Korean Text Display Support
  870. '76C19B50-F0C8-11CF-87CC-0020AFEECF20': 'LanguageAS', // Language Auto-Selection
  871. '08B0E5C0-4FCB-11CF-AAA5-00401C608500': 'MsftVM', // Microsoft virtual machine
  872. '5945C046-LE7D-LLDL-BC44-00C04FD912BE': 'MSNMessengerSrv', // MSN Messenger Service
  873. '44BBA842-CC51-11CF-AAFA-00AA00B6015B': 'NetMeetingNT', // NetMeeting NT
  874. '3AF36230-A269-11D1-B5BF-0000F8051515': 'OfflineBrwPack', // Offline Browsing Pack
  875. '44BBA840-CC51-11CF-AAFA-00AA00B6015C': 'OutlookExpress', // Outlook Express
  876. '76C19B32-F0C8-11CF-87CC-0020AFEECF20': 'PanEuropeanDS', // Pan-European Text Display Support
  877. '4063BE15-3B08-470D-A0D5-B37161CFFD69': 'QuickTime', // Apple Quick Time
  878. 'DE4AF3B0-F4D4-11D3-B41A-0050DA2E6C21': 'QuickTimeCheck', // Apple Quick Time Check
  879. '3049C3E9-B461-4BC5-8870-4C09146192CA': 'RealPlayer', // RealPlayer Download and Record Plugin for IE
  880. '2A202491-F00D-11CF-87CC-0020AFEECF20': 'ShockwaveDir', // Macromedia Shockwave Director
  881. '3E01D8E0-A72B-4C9F-99BD-8A6E7B97A48D': 'Skype', // Skype
  882. 'CC2A9BA0-3BDD-11D0-821E-444553540000': 'TaskScheduler', // Task Scheduler
  883. '76C19B35-F0C8-11CF-87CC-0020AFEECF20': 'ThaiDS', // Thai Text Display Support
  884. '3BF42070-B3B1-11D1-B5C5-0000F8051515': 'Uniscribe', // Uniscribe
  885. '4F645220-306D-11D2-995D-00C04F98BBC9': 'VBScripting', // Visual Basic Scripting Support v5.6
  886. '76C19B37-F0C8-11CF-87CC-0020AFEECF20': 'VietnameseDS', // Vietnamese Text Display Support
  887. '10072CEC-8CC1-11D1-986E-00A0C955B42F': 'VML', // Vector Graphics Rendering (VML)
  888. '90E2BA2E-DD1B-4CDE-9134-7A8B86D33CA7': 'WebEx', // WebEx Productivity Tools
  889. '73FA19D0-2D75-11D2-995D-00C04F98BBC9': 'WebFolders', // Web Folders
  890. '89820200-ECBD-11CF-8B85-00AA005B4340': 'WinDesktopUpdateNT', // Windows Desktop Update NT
  891. '9030D464-4C02-4ABF-8ECC-5164760863C6': 'WinLive', // Windows Live ID Sign-in Helper
  892. '6BF52A52-394A-11D3-B153-00C04F79FAA6': 'WinMediaPlayer', // Windows Media Player (Versions 7, 8 or 9)
  893. '22D6F312-B0F6-11D0-94AB-0080C74C7E95': 'WinMediaPlayerTrad' // Windows Media Player (Traditional Versions)
  894. }
  895. strTemp = "";
  896. bolFirst = true;
  897.  
  898. //if the browser supports a list of plugins, just go though and append them to a list!
  899. if (navigator.plugins.length > 0)
  900. {
  901. for (iCount = 0; iCount < navigator.plugins.length; iCount++)
  902. {
  903. if (bolFirst === true)
  904. {
  905. strTemp += navigator.plugins[iCount].name;
  906. bolFirst = false;
  907. }
  908. else
  909. {
  910. strTemp += strSep + navigator.plugins[iCount].name;
  911. }
  912. }
  913. }
  914. //if we cant get plugins, just report back a list of mimeTypes.
  915. else if (navigator.mimeTypes.length > 0)
  916. {
  917. strMimeType = navigator.mimeTypes;
  918. for (iCount = 0; iCount < strMimeType.length; iCount++)
  919. {
  920. if (bolFirst === true)
  921. {
  922. strTemp += strMimeType[iCount].description;
  923. bolFirst = false;
  924. }
  925. else
  926. {
  927. strTemp += strSep + strMimeType[iCount].description;
  928. }
  929. }
  930. }
  931. //if none of that worked, the browser is IE, so we need to enumerate off the list above
  932. else if ("addBehavior" in document.body && typeof document.body.addBehavior === "function")
  933. {
  934. document.body.addBehavior("#default#clientCaps");
  935. for (var key in pluginHash)
  936. {
  937. strVersion = activeXDetect(key); //query the hash against activex
  938. strName = pluginHash[key];
  939. if (strVersion)
  940. {
  941. if (bolFirst === true)
  942. {
  943. strTemp = strName + strPair + strVersion;
  944. bolFirst = false;
  945. }
  946. else
  947. {
  948. strTemp += strSep + strName + strPair + strVersion;
  949. }
  950. }
  951. }
  952. strTemp = strTemp.replace(/,/g, ".");
  953. }
  954. else
  955. {
  956. return "None|phone";
  957. }
  958. strTemp = stripIllegalChars(strTemp);
  959. if (strTemp === "")
  960. {
  961. strTemp = "None";
  962. }
  963. return strTemp;
  964. }
  965. }
  966.  
  967. /////////////////////////////////////////////////////////////////////////////////////////////////////
  968. // //
  969. // Below functions are helper functions that are not exposed in the returned fingerprint object //
  970. // //
  971. /////////////////////////////////////////////////////////////////////////////////////////////////
  972.  
  973. // This function queries IE plugins though the getComponentVersion method, and returns if the plugin is active.
  974. // Called from pluginsFingerprint() and not exposed in the returned fingerprint object.
  975. function activeXDetect(componentClassID)
  976. {
  977. var strComponentVersion;
  978.  
  979. strComponentVersion = "";
  980.  
  981. try
  982. {
  983. strComponentVersion = document.body.getComponentVersion('{' + componentClassID + '}', 'ComponentID');
  984. if (strComponentVersion !== null)
  985. {
  986. return strComponentVersion;
  987. }
  988. else
  989. {
  990. return false;
  991. }
  992. }
  993. catch (err)
  994. {
  995. return err;
  996. }
  997. }
  998.  
  999. // This function will remove illegal characters from a string. (removes "\\" "/" and "\n". newlines are changed to 'n'
  1000. // Called from pluginsFingerprint() and not exposed in the returned fingerprint object.
  1001. function stripIllegalChars(strValue)
  1002. {
  1003. var iCounter, strOriginal, strOut;
  1004.  
  1005. iCounter = 0;
  1006. strOriginal = "";
  1007. strOut = "";
  1008.  
  1009. try
  1010. {
  1011. strOriginal = strValue.toLowerCase();
  1012.  
  1013. //itterate though the string.
  1014. for (iCounter = 0; iCounter < strOriginal.length; iCounter = iCounter + 1)
  1015. {
  1016. //if the character is allowed, add it to the string, else we will skip over it (unless its a new line).
  1017. if (strOriginal.charAt(iCounter) !== '\n' && strOriginal.charAt(iCounter) !== '/' && strOriginal.charAt(iCounter) !== "\\")
  1018. {
  1019. strOut = strOut + strOriginal.charAt(iCounter);
  1020. }
  1021. //replace the newlines with just an 'n'
  1022. else if (strOriginal.charAt(iCounter) === '\n')
  1023. {
  1024. strOut = strOut + "n";
  1025. }
  1026. }
  1027. return strOut;
  1028. }
  1029. catch (err)
  1030. {
  1031. return err;
  1032. }
  1033. }
  1034.  
  1035.  
  1036. return fingerprinter;
  1037. })();
Add Comment
Please, Sign In to add comment