PageRenderTime 62ms CodeModel.GetById 42ms RepoModel.GetById 0ms app.codeStats 0ms

/ajax/libs/fingerprintjs/v0.5.1/fingerprint.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 263 lines | 210 code | 28 blank | 25 comment | 42 complexity | fa46f4be83ec5a2090be72c5cd155a22 MD5 | raw file
  1. /*
  2. * fingerprintJS 0.5.1 - Fast browser fingerprint library
  3. * https://github.com/Valve/fingerprintjs
  4. * Copyright (c) 2013 Valentin Vasilyev (iamvalentin@gmail.com)
  5. * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
  6. */
  7. (function (scope) {
  8. 'use strict';
  9. var Fingerprint = function (options) {
  10. var nativeForEach, nativeMap;
  11. nativeForEach = Array.prototype.forEach;
  12. nativeMap = Array.prototype.map;
  13. this.each = function (obj, iterator, context) {
  14. if (obj === null) {
  15. return;
  16. }
  17. if (nativeForEach && obj.forEach === nativeForEach) {
  18. obj.forEach(iterator, context);
  19. } else if (obj.length === +obj.length) {
  20. for (var i = 0, l = obj.length; i < l; i++) {
  21. if (iterator.call(context, obj[i], i, obj) === {}) return;
  22. }
  23. } else {
  24. for (var key in obj) {
  25. if (obj.hasOwnProperty(key)) {
  26. if (iterator.call(context, obj[key], key, obj) === {}) return;
  27. }
  28. }
  29. }
  30. };
  31. this.map = function(obj, iterator, context) {
  32. var results = [];
  33. // Not using strict equality so that this acts as a
  34. // shortcut to checking for `null` and `undefined`.
  35. if (obj == null) return results;
  36. if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
  37. this.each(obj, function(value, index, list) {
  38. results[results.length] = iterator.call(context, value, index, list);
  39. });
  40. return results;
  41. };
  42. if (typeof options == 'object'){
  43. this.hasher = options.hasher;
  44. this.screen_resolution = options.screen_resolution;
  45. this.canvas = options.canvas;
  46. this.ie_activex = options.ie_activex;
  47. } else if(typeof options == 'function'){
  48. this.hasher = options;
  49. }
  50. };
  51. Fingerprint.prototype = {
  52. get: function(){
  53. var keys = [];
  54. keys.push(navigator.userAgent);
  55. keys.push(navigator.language);
  56. keys.push(screen.colorDepth);
  57. if (this.screen_resolution) {
  58. var resolution = this.getScreenResolution();
  59. if (typeof resolution !== 'undefined'){ // headless browsers, such as phantomjs
  60. keys.push(this.getScreenResolution().join('x'));
  61. }
  62. }
  63. keys.push(new Date().getTimezoneOffset());
  64. keys.push(this.hasSessionStorage());
  65. keys.push(this.hasLocalStorage());
  66. keys.push(!!window.indexedDB);
  67. //body might not be defined at this point or removed programmatically
  68. if(document.body){
  69. keys.push(typeof(document.body.addBehavior));
  70. } else {
  71. keys.push(typeof undefined);
  72. }
  73. keys.push(typeof(window.openDatabase));
  74. keys.push(navigator.cpuClass);
  75. keys.push(navigator.platform);
  76. keys.push(navigator.doNotTrack);
  77. keys.push(this.getPluginsString());
  78. if(this.canvas && this.isCanvasSupported()){
  79. keys.push(this.getCanvasFingerprint());
  80. }
  81. if(this.hasher){
  82. return this.hasher(keys.join('###'), 31);
  83. } else {
  84. return this.murmurhash3_32_gc(keys.join('###'), 31);
  85. }
  86. },
  87. /**
  88. * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011)
  89. *
  90. * @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
  91. * @see http://github.com/garycourt/murmurhash-js
  92. * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a>
  93. * @see http://sites.google.com/site/murmurhash/
  94. *
  95. * @param {string} key ASCII only
  96. * @param {number} seed Positive integer only
  97. * @return {number} 32-bit positive integer hash
  98. */
  99. murmurhash3_32_gc: function(key, seed) {
  100. var remainder, bytes, h1, h1b, c1, c2, k1, i;
  101. remainder = key.length & 3; // key.length % 4
  102. bytes = key.length - remainder;
  103. h1 = seed;
  104. c1 = 0xcc9e2d51;
  105. c2 = 0x1b873593;
  106. i = 0;
  107. while (i < bytes) {
  108. k1 =
  109. ((key.charCodeAt(i) & 0xff)) |
  110. ((key.charCodeAt(++i) & 0xff) << 8) |
  111. ((key.charCodeAt(++i) & 0xff) << 16) |
  112. ((key.charCodeAt(++i) & 0xff) << 24);
  113. ++i;
  114. k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
  115. k1 = (k1 << 15) | (k1 >>> 17);
  116. k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
  117. h1 ^= k1;
  118. h1 = (h1 << 13) | (h1 >>> 19);
  119. h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
  120. h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
  121. }
  122. k1 = 0;
  123. switch (remainder) {
  124. case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
  125. case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
  126. case 1: k1 ^= (key.charCodeAt(i) & 0xff);
  127. k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
  128. k1 = (k1 << 15) | (k1 >>> 17);
  129. k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
  130. h1 ^= k1;
  131. }
  132. h1 ^= key.length;
  133. h1 ^= h1 >>> 16;
  134. h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
  135. h1 ^= h1 >>> 13;
  136. h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff;
  137. h1 ^= h1 >>> 16;
  138. return h1 >>> 0;
  139. },
  140. // https://bugzilla.mozilla.org/show_bug.cgi?id=781447
  141. hasLocalStorage: function () {
  142. try{
  143. return !!scope.localStorage;
  144. } catch(e) {
  145. return true; // SecurityError when referencing it means it exists
  146. }
  147. },
  148. hasSessionStorage: function () {
  149. try{
  150. return !!scope.sessionStorage;
  151. } catch(e) {
  152. return true; // SecurityError when referencing it means it exists
  153. }
  154. },
  155. isCanvasSupported: function () {
  156. var elem = document.createElement('canvas');
  157. return !!(elem.getContext && elem.getContext('2d'));
  158. },
  159. isIE: function () {
  160. if(navigator.appName === 'Microsoft Internet Explorer') {
  161. return true;
  162. } else if(navigator.appName === 'Netscape' && /Trident/.test(navigator.userAgent)){// IE 11
  163. return true;
  164. }
  165. return false;
  166. },
  167. getPluginsString: function () {
  168. if(this.isIE()){
  169. return this.getIEPluginsString();
  170. } else {
  171. return this.getRegularPluginsString();
  172. }
  173. },
  174. getRegularPluginsString: function () {
  175. return this.map(navigator.plugins, function (p) {
  176. var mimeTypes = this.map(p, function(mt){
  177. return [mt.type, mt.suffixes].join('~');
  178. }).join(',');
  179. return [p.name, p.description, mimeTypes].join('::');
  180. }, this).join(';');
  181. },
  182. getIEPluginsString: function () {
  183. var names = ['ShockwaveFlash.ShockwaveFlash',//flash plugin
  184. 'AcroPDF.PDF', // Adobe PDF reader 7+
  185. 'PDF.PdfCtrl', // Adobe PDF reader 6 and earlier, brrr
  186. 'QuickTime.QuickTime', // QuickTime
  187. // 5 versions of real players
  188. 'rmocx.RealPlayer G2 Control',
  189. 'rmocx.RealPlayer G2 Control.1',
  190. 'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)',
  191. 'RealVideo.RealVideo(tm) ActiveX Control (32-bit)',
  192. 'RealPlayer',
  193. 'SWCtl.SWCtl', // ShockWave player
  194. 'WMPlayer.OCX', // Windows media player
  195. 'AgControl.AgControl', // Silverlight
  196. 'Skype.Detection'];
  197. if(this.ie_activex && scope.ActiveXObject){
  198. // starting to detect plugins in IE
  199. return this.map(names, function(name){
  200. try{
  201. new ActiveXObject(name);
  202. return name;
  203. } catch(e){
  204. return null;
  205. }
  206. }).join(';');
  207. } else {
  208. return ""; // behavior prior version 0.5.0, not breaking backwards compat.
  209. }
  210. },
  211. getScreenResolution: function () {
  212. return [screen.height, screen.width];
  213. },
  214. getCanvasFingerprint: function () {
  215. var canvas = document.createElement('canvas');
  216. var ctx = canvas.getContext('2d');
  217. // https://www.browserleaks.com/canvas#how-does-it-work
  218. var txt = 'http://valve.github.io';
  219. ctx.textBaseline = "top";
  220. ctx.font = "14px 'Arial'";
  221. ctx.textBaseline = "alphabetic";
  222. ctx.fillStyle = "#f60";
  223. ctx.fillRect(125,1,62,20);
  224. ctx.fillStyle = "#069";
  225. ctx.fillText(txt, 2, 15);
  226. ctx.fillStyle = "rgba(102, 204, 0, 0.7)";
  227. ctx.fillText(txt, 4, 17);
  228. return canvas.toDataURL();
  229. }
  230. };
  231. if (typeof module === 'object' && typeof exports === 'object') {
  232. module.exports = Fingerprint;
  233. }
  234. scope.Fingerprint = Fingerprint;
  235. })(window);