pull/3/head
iotcat 5 years ago
parent c8f02cd20c
commit a9fa72d1db
  1. 40
      demo.html
  2. 73
      fp.js
  3. 2
      fp.min.js
  4. 2
      fp.min.js.map
  5. 265
      fp_.js

@ -1,10 +1,11 @@
<!doctype html>
<html>
<head>
<title>fp</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body{
body {
font-family: sans-serif;
max-width: 48em;
margin: auto;
@ -12,12 +13,15 @@
background: #222;
color: #fff;
}
h1 {
margin: 2em 0 0;
}
p {
font-size: 1.2em
}
button {
border: none;
color: #fff;
@ -28,52 +32,58 @@
box-shadow: 0 3px 0 #05c;
outline: none;
}
button:active {
transform: translateY(3px);
box-shadow: none;
}
strong {
display: block;
letter-spacing: 1px;
word-wrap: break-word;
}
@media (min-width: 32em) {
h1 {
font-size: 4em;
}
strong {
font-size: 1.5em;
}
}
</style>
</head>
<body>
<div id="container"></div>
<h1>fp</h1>
<p> <button type="button" id="btn">Your fp: <strong id="fp"></strong></button></p>
<p>Time Used: <var id="time"></var> ms &nbsp;Accuracy: <var id="acc"></var> %</p>
<p> <button type="button" id="btn">Your fp: <strong id="fp"></strong></button></p>
<p>Time Used: <var id="time"></var> ms &nbsp;Accuracy: <var id="acc"></var> %</p>
<p>Created Time: <var id="cTime"></var></p>
<p><strong>Detailed information: </strong></p>
<pre id="details"></pre>
<script src="fp.min.js"></script>
<script>
document.querySelector("#btn").addEventListener("click", function () {
location.reload();
})
document.querySelector("#btn").addEventListener("click", function () {
location.reload();
})
fp((f, acc, detail, CreateTime, TimeUsed)=>{
document.querySelector("#acc").textContent = String(acc * 100).substr(0, 6);
document.querySelector("#time").textContent = TimeUsed
document.querySelector("#fp").textContent = f
document.querySelector("#details").textContent = detail;
})
fp((f, acc, detail, CreateTime, TimeUsed, detailObj) => {
document.querySelector("#acc").textContent = String(acc * 100).substr(0, 6);
document.querySelector("#time").textContent = TimeUsed
document.querySelector("#fp").textContent = f
document.querySelector("#details").textContent = detail;
document.querySelector("#cTime").textContent = CreateTime;
console.log(detailObj);
})
</script>
</body>
</html>

73
fp.js

@ -1,3 +1,9 @@
/*
* @Author: IoTcat (https://iotcat.me)
* @Date: 2019-06-26 11:34:32
* @Last Modified by:
* @Last Modified time: 2019-06-26 11:38:03
*/
var cookie = {
set: function (name, value) {
@ -38,7 +44,6 @@ var cookie = {
var MaxDiff = 0.94;
var x64Add = function (m, n) {
m = [m[0] >>> 16, m[0] & 0xffff, m[1] >>> 16, m[1] & 0xffff]
n = [n[0] >>> 16, n[0] & 0xffff, n[1] >>> 16, n[1] & 0xffff]
@ -1402,70 +1407,69 @@ var cookie = {
newComponents.push({ key: component.key, value: component.value })
}
}
}
var murmur = x64hash128(map(newComponents, function (component) { return component.value }).join('~~~'), 31)
callback(murmur, newComponents)
})
}
};
var murmur = x64hash128(map(newComponents, function (component) { return component.value }).join('~~~'), 31);
callback(murmur, newComponents);
});
};
var _fp_val = null;
var _fp_detail = null;
var _fp_detail = "";
var _fp_acc = null;
var _fp_LastChangeTime = null;
var _fp_TimeUsed = null;
var _fp_detailObj = {};
var d1 = new Date();
Fingerprint2.get(function (components) {
var murmur = x64hash128(components.map(function (pair) { return pair.value }).join(), 15)
var murmur = x64hash128(components.map(function (pair) { return pair.value }).join(), 15);
murmur = murmur.substr(0, 8);
var rate = 0;
for (var index in components) {
var obj = components[index]
var line = obj.key + " = " + String(obj.value).substr(0, 100);
details += line + "\n"
line = window.btoa(line);
if (cookie.get('_fp_ref_' + index)) rate = rate + 1 - levenshteinenator(line, cookie.get('_fp_ref_' + index));
else {
cookie.set('_fp_ref_' + index, line);
rate += 1;
}
_fp_detail += line + "\n";
_fp_detailObj[obj.key] = String(obj.value).substr(0, 100);
}
if (cookie.get('_fp_ref_')) rate = levenshteinenator(Compress(window.btoa(JSON.stringify(_fp_detailObj))), cookie.get('_fp_ref_'));
else {
rate = 0;
}
rate = 1 - rate / index;
rate = (rate < 0) ? 0 : rate;
//rate = (rate < 0) ? 0 : rate;
_fp_acc = rate;
_fp_detail = details;
if (rate < MaxDiff) {
for (var index in components) {
var obj = components[index]
var line = obj.key + " = " + String(obj.value).substr(0, 100);
line = window.btoa(line);
cookie.set('_fp_ref_' + index, line);
}
cookie.set('_fp_ref_', Compress(window.btoa(JSON.stringify(_fp_detailObj))));
}
var d2 = new Date()
var d2 = new Date();
var time = d2 - d1;
_fp_TimeUsed = time;
if (rate < MaxDiff) {
cookie.set('_fp', murmur);
cookie.set('_fp_LastChangeTime', d2);
cookie.set('_fp_LastChangeTime', Date.parse(d2) / 1000);
_fp_LastChangeTime = d2;
_fp_val = murmur;
}
else {
_fp_LastChangeTime = cookie.get('_fp_LastChangeTime');
_fp_LastChangeTime = new Date(cookie.get('_fp_LastChangeTime') * 1000);
_fp_val = cookie.get('_fp');
}
var details = "";
console.log('\n' + ' %c fp v2.0.1 %c ' + _fp_val + '::' + String(_fp_acc).substr(0, 4) + '::' + _fp_TimeUsed + 'ms %c https://fp.yimian.xyz \n', 'color: #00FFFF; background: #030307; padding:5px 0;','color: #fadfa3; background: #030307; padding:5px 0;', 'background: #4682B4; padding:5px 0;');
console.log('\n' + ' %c fp v2.0.1 %c ' + _fp_val + '::' + String(_fp_acc * 100).substr(0, 4) + '%::' + _fp_TimeUsed + 'ms %c https://fp.yimian.xyz \n', 'color: #00FFFF; background: #030307; padding:5px 0;', 'color: #fadfa3; background: #030307; padding:5px 0;', 'background: #4682B4; padding:5px 0;');
})
function Compress(strNormalString) {
var strCompressedString = "";
for (var i = 0; i < strNormalString.length; i += Math.round(strNormalString.length / 289)) {
strCompressedString += strNormalString.charAt(i);
}
return strCompressedString;
}
var levenshteinenator = (function () {
function levenshteinenator(a, b) {
var cost;
@ -1504,9 +1508,8 @@ var cookie = {
setTimeout(fp, 1, f);
return;
}
f(_fp_val, _fp_acc, _fp_detail, _fp_LastChangeTime, _fp_TimeUsed);
f(_fp_val, _fp_acc, _fp_detail, _fp_LastChangeTime, _fp_TimeUsed, _fp_detailObj);
};
return fp;
})
});

2
fp.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

265
fp_.js

@ -1,265 +0,0 @@
/**
* fp.js
*
* @category fp
* @package fp.js
* @copyright IoTcat(https://iotcat.me) developed from Valve/fingerprintjs(https://github.com/Valve/fingerprintjs)
* @license MIT
* @version 0.2.1
*/
;(function (name, context, definition) {
if (typeof module !== 'undefined' && module.exports) { module.exports = definition(); }
else if (typeof define === 'function' && define.amd) { define(definition); }
else { context[name] = definition(); }
})('fp', this, function () {
'use strict';
var Fingerprint = function (options) {
var nativeForEach, nativeMap;
nativeForEach = Array.prototype.forEach;
nativeMap = Array.prototype.map;
this.each = function (obj, iterator, context) {
if (obj === null) {
return;
}
if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator, context);
} else if (obj.length === +obj.length) {
for (var i = 0, l = obj.length; i < l; i++) {
if (iterator.call(context, obj[i], i, obj) === {}) return;
}
} else {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
if (iterator.call(context, obj[key], key, obj) === {}) return;
}
}
}
};
this.map = function(obj, iterator, context) {
var results = [];
// Not using strict equality so that this acts as a
// shortcut to checking for `null` and `undefined`.
if (obj == null) return results;
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
this.each(obj, function(value, index, list) {
results[results.length] = iterator.call(context, value, index, list);
});
return results;
};
this.screen_resolution = true;
this.screen_orientation = true;
this.ie_activex = true;
};
Fingerprint.prototype = {
get: function(){
var keys = [];
keys.push(navigator.userAgent);
keys.push(navigator.language);
keys.push(screen.colorDepth);
if (this.screen_resolution) {
var resolution = this.getScreenResolution();
if (typeof resolution !== 'undefined'){ // headless browsers, such as phantomjs
keys.push(resolution.join('x'));
}
}
keys.push(new Date().getTimezoneOffset());
keys.push(this.hasSessionStorage());
keys.push(this.hasLocalStorage());
keys.push(this.hasIndexDb());
//body might not be defined at this point or removed programmatically
if(document.body){
keys.push(typeof(document.body.addBehavior));
} else {
keys.push(typeof undefined);
}
keys.push(typeof(window.openDatabase));
keys.push(navigator.cpuClass);
keys.push(navigator.platform);
keys.push(navigator.doNotTrack);
keys.push(this.getPluginsString());
if(this.isCanvasSupported()){
keys.push(this.getCanvasFingerprint());
}
return this.murmurhash3_32_gc(keys.join('###'), 31);
},
murmurhash3_32_gc: function(key, seed) {
var remainder, bytes, h1, h1b, c1, c2, k1, i;
remainder = key.length & 3; // key.length % 4
bytes = key.length - remainder;
h1 = seed;
c1 = 0xcc9e2d51;
c2 = 0x1b873593;
i = 0;
while (i < bytes) {
k1 =
((key.charCodeAt(i) & 0xff)) |
((key.charCodeAt(++i) & 0xff) << 8) |
((key.charCodeAt(++i) & 0xff) << 16) |
((key.charCodeAt(++i) & 0xff) << 24);
++i;
k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff;
h1 ^= k1;
h1 = (h1 << 13) | (h1 >>> 19);
h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff;
h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16));
}
k1 = 0;
switch (remainder) {
case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16;
case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8;
case 1: k1 ^= (key.charCodeAt(i) & 0xff);
k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff;
k1 = (k1 << 15) | (k1 >>> 17);
k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff;
h1 ^= k1;
}
h1 ^= key.length;
h1 ^= h1 >>> 16;
h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff;
h1 ^= h1 >>> 13;
h1 = ((((h1 & 0xffff) * 0xd2b2ae35) + ((((h1 >>> 16) * 0xd2b2ae35) & 0xffff) << 16))) & 0xffffffff;
h1 ^= h1 >>> 16;
//transfer result to 8 words
var r = ['1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','f','g','h','i','g','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
return h1, r[h1 & 31 + 2] + r[(h1 & (31 << 6))>>>6] + r[(h1 & (31 << 13)) >>> 13 + 4] + r[(h1 & (31 << 20)) >>> 20]+ r[(h1 & (31 << 27)) >>> 27 + 1]+ r[(h1 & (31 << 35)) >>> 35]+ r[(h1 & (31 << 42)) >>> 42 +2]+ r[(h1 & (31 << 51)) >>> 51 + 3];
},
// https://bugzilla.mozilla.org/show_bug.cgi?id=781447
hasLocalStorage: function () {
try{
return !!window.localStorage;
} catch(e) {
return true; // SecurityError when referencing it means it exists
}
},
hasSessionStorage: function () {
try{
return !!window.sessionStorage;
} catch(e) {
return true; // SecurityError when referencing it means it exists
}
},
hasIndexDb: function () {
try{
return !!window.indexedDB;
} catch(e) {
return true; // SecurityError when referencing it means it exists
}
},
isCanvasSupported: function () {
var elem = document.createElement('canvas');
return !!(elem.getContext && elem.getContext('2d'));
},
isIE: function () {
if(navigator.appName === 'Microsoft Internet Explorer') {
return true;
} else if(navigator.appName === 'Netscape' && /Trident/.test(navigator.userAgent)){// IE 11
return true;
}
return false;
},
getPluginsString: function () {
if(this.isIE() && this.ie_activex){
return this.getIEPluginsString();
} else {
return this.getRegularPluginsString();
}
},
getRegularPluginsString: function () {
return this.map(navigator.plugins, function (p) {
var mimeTypes = this.map(p, function(mt){
return [mt.type, mt.suffixes].join('~');
}).join(',');
return [p.name, p.description, mimeTypes].join('::');
}, this).join(';');
},
getIEPluginsString: function () {
if(window.ActiveXObject){
var names = ['ShockwaveFlash.ShockwaveFlash',//flash plugin
'AcroPDF.PDF', // Adobe PDF reader 7+
'PDF.PdfCtrl', // Adobe PDF reader 6 and earlier, brrr
'QuickTime.QuickTime', // QuickTime
// 5 versions of real players
'rmocx.RealPlayer G2 Control',
'rmocx.RealPlayer G2 Control.1',
'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)',
'RealVideo.RealVideo(tm) ActiveX Control (32-bit)',
'RealPlayer',
'SWCtl.SWCtl', // ShockWave player
'WMPlayer.OCX', // Windows media player
'AgControl.AgControl', // Silverlight
'Skype.Detection'];
// starting to detect plugins in IE
return this.map(names, function(name){
try{
new ActiveXObject(name);
return name;
} catch(e){
return null;
}
}).join(';');
} else {
return ""; // behavior prior version 0.5.0, not breaking backwards compat.
}
},
getScreenResolution: function () {
var resolution;
if(this.screen_orientation){
resolution = (screen.height > screen.width) ? [screen.height, screen.width] : [screen.width, screen.height];
}else{
resolution = [screen.height, screen.width];
}
return resolution;
},
getCanvasFingerprint: function () {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var txt = 'https://fp.yimian.xyz';
ctx.textBaseline = "top";
ctx.font = "14px 'Arial'";
ctx.textBaseline = "alphabetic";
ctx.fillStyle = "#f60";
ctx.fillRect(125,1,62,20);
ctx.fillStyle = "#069";
ctx.fillText(txt, 2, 15);
ctx.fillStyle = "rgba(102, 204, 0, 0.7)";
ctx.fillText(txt, 4, 17);
return canvas.toDataURL();
}
};
return Fingerprint;
});
var fp = new fp().get();
Loading…
Cancel
Save