Made much smarter, store to DB, use epiphany etc.
This commit is contained in:
parent
538c1158de
commit
0736e4c45c
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "gulp"]
|
||||
path = gulp
|
||||
url = git@github.com:thecodebureau/gulp.git
|
||||
25
app.js
25
app.js
@ -1,25 +0,0 @@
|
||||
var express = require('express');
|
||||
var UAParser = require('ua-parser-js');
|
||||
var app = express();
|
||||
var parser = new UAParser();
|
||||
var dust = require('dustjs-linkedin');
|
||||
var fs = require('fs');
|
||||
|
||||
fs.readFile('./index.dust', function(error, data){
|
||||
dust.loadSource(dust.compile(data.toString(), 'index'));
|
||||
});
|
||||
|
||||
var modern = '<html><head><script src="//cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script></head>';
|
||||
|
||||
app.use(function(request, response){
|
||||
parser.setUA(request.get('user-agent'));
|
||||
dust.render('index', {ua: JSON.stringify(parser.getResult(), null, 2)}, function(error, out){
|
||||
response.write(out);
|
||||
response.end();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
app.listen(3993, function(){
|
||||
console.log("App listening on port 3993.");
|
||||
});
|
||||
1
gulp
Submodule
1
gulp
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 05881fd4a1af2f0ab2983d52605e28db643c3fc3
|
||||
112
gulpconfig.js
Normal file
112
gulpconfig.js
Normal file
@ -0,0 +1,112 @@
|
||||
module.exports = {
|
||||
"autoprefixer": {
|
||||
"browsers": [
|
||||
"safari >= 5",
|
||||
"ie >= 8",
|
||||
"ios >= 6",
|
||||
"opera >= 12.1",
|
||||
"firefox >= 17",
|
||||
"chrome >= 30",
|
||||
"android >= 4"
|
||||
],
|
||||
"cascade": true
|
||||
},
|
||||
"bower": {
|
||||
"src": "/home/sup3rman/dev/browser/bower_components",
|
||||
"dest": "/home/sup3rman/dev/browser/public/js/bower"
|
||||
},
|
||||
"browserSync": {
|
||||
"browser": "chromium",
|
||||
"ghostMode": false,
|
||||
"proxy": "localhost:3810",
|
||||
"files": [
|
||||
"/home/sup3rman/dev/browser/public/css/**/*.css",
|
||||
"/home/sup3rman/dev/browser/public/js/**/*.js"
|
||||
]
|
||||
},
|
||||
"browserify": {
|
||||
"debug": true,
|
||||
"dest": "/home/sup3rman/dev/browser/public/js",
|
||||
"entries": [
|
||||
"app.js",
|
||||
"admin.js"
|
||||
],
|
||||
"paths": [
|
||||
"/home/sup3rman/dev/browser/node_modules",
|
||||
"/home/sup3rman/dev/browser/modules"
|
||||
],
|
||||
"outputs": [
|
||||
"app.js",
|
||||
"admin.js"
|
||||
],
|
||||
"src": "/home/sup3rman/dev/browser/src/js"
|
||||
},
|
||||
"fonts": {
|
||||
"src": "/home/sup3rman/dev/browser/src/fonts/**/*.{eot,ttf,woff}",
|
||||
"dest": "/home/sup3rman/dev/browser/public/fonts"
|
||||
},
|
||||
"nodemon": {
|
||||
"ext": "js,dust",
|
||||
"ignore": [
|
||||
"bower_components",
|
||||
"gulp",
|
||||
"node_modules",
|
||||
"public",
|
||||
"samples",
|
||||
"src"
|
||||
],
|
||||
"reloadDelay": 300,
|
||||
"script": "./server/server.js"
|
||||
},
|
||||
"raster": {
|
||||
"src": "/home/sup3rman/dev/browser/src/raster/**/*.{png,gif,jpg}",
|
||||
"dest": "/home/sup3rman/dev/browser/public/img"
|
||||
},
|
||||
"sass": {
|
||||
"src": "/home/sup3rman/dev/browser/src/sass/**/*.{sass,scss}",
|
||||
"dest": "/home/sup3rman/dev/browser/public/css",
|
||||
"options": {
|
||||
"outputStyle": "nested",
|
||||
"includePaths": [
|
||||
"./node_modules/spysass/sass"
|
||||
],
|
||||
"imagePath": "../img"
|
||||
}
|
||||
},
|
||||
"static": {
|
||||
"src": "/home/sup3rman/dev/browser/src/static/**/*",
|
||||
"dest": "/home/sup3rman/dev/browser/public"
|
||||
},
|
||||
"tasks": {
|
||||
"default": [
|
||||
"wipe",
|
||||
[
|
||||
"bower",
|
||||
"browserify",
|
||||
"fonts",
|
||||
"nodemon",
|
||||
"raster",
|
||||
"sass",
|
||||
"static",
|
||||
"svg"
|
||||
],
|
||||
[
|
||||
"watch",
|
||||
"browser-sync"
|
||||
]
|
||||
]
|
||||
},
|
||||
"svg": {
|
||||
"src": "/home/sup3rman/dev/browser/src/svg/**/*.svg",
|
||||
"dest": "/home/sup3rman/dev/browser/public/img"
|
||||
},
|
||||
"watch": {
|
||||
"browserify": "/home/sup3rman/dev/browser/src/js/**/*.js",
|
||||
"sass": "/home/sup3rman/dev/browser/src/sass/**/*.{sass,scss}"
|
||||
},
|
||||
"wipe": {
|
||||
"src": [
|
||||
"/home/sup3rman/dev/browser/public"
|
||||
]
|
||||
}
|
||||
}
|
||||
1
gulpfile.js
Symbolic link
1
gulpfile.js
Symbolic link
@ -0,0 +1 @@
|
||||
gulp/gulpfile.js
|
||||
12
index.dust
12
index.dust
@ -1,12 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="mod"></div>
|
||||
<pre>
|
||||
{ua}
|
||||
</pre>
|
||||
<script>document.getElementById("mod").textContent = document.querySelector("html").classList;</script>
|
||||
</body>
|
||||
</html>
|
||||
11
nodemon.json
Normal file
11
nodemon.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"ext": "js,dust",
|
||||
"ignore": [
|
||||
"bower_components",
|
||||
"gulp",
|
||||
"node_modules",
|
||||
"public",
|
||||
"samples",
|
||||
"src"
|
||||
]
|
||||
}
|
||||
20
package.json
20
package.json
@ -2,18 +2,14 @@
|
||||
"name": "browser",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"main": "app.js",
|
||||
"dependencies": {
|
||||
"dustjs-linkedin": "^2.7.2",
|
||||
"express": "^4.13.3",
|
||||
"ua-parser-js": "^0.7.9"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"scripts": {},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "gituser@git.thecodebureau.com:tcb/browser"
|
||||
"main": "./server/server.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "The Code Bureau <info@thecodebureau.com> (https://thecodebureau.com)",
|
||||
"license": "MIT"
|
||||
"dependencies": {
|
||||
"epiphany": "^0.5.3",
|
||||
"jquery-jsonify": "^0.1.2",
|
||||
"ua-parser-js": "^0.7.9"
|
||||
}
|
||||
}
|
||||
|
||||
111
public/js/admin.js
Normal file
111
public/js/admin.js
Normal file
File diff suppressed because one or more lines are too long
101
public/js/app.js
Normal file
101
public/js/app.js
Normal file
@ -0,0 +1,101 @@
|
||||
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({2:[function(require,module,exports){
|
||||
$(function() {
|
||||
var device = {};
|
||||
|
||||
var nav = _.clone(window.navigator);
|
||||
|
||||
nav.plugins = _.map(navigator.plugins, function(obj, key) {
|
||||
return obj.name + ' (' + obj.filename + ')';
|
||||
});
|
||||
|
||||
//device.navigator = _.omit(nav, [
|
||||
// 'appCodeName',
|
||||
// 'appMinorVersion',
|
||||
// 'appName',
|
||||
// 'appVersion',
|
||||
// 'battery',
|
||||
// 'cpuClass',
|
||||
// 'geolocation',
|
||||
// 'mimeTypes',
|
||||
// 'oscpu',
|
||||
// 'platform',
|
||||
// 'product',
|
||||
// 'vendor',
|
||||
// 'vendorSub'
|
||||
//]);
|
||||
device.navigator = _.pick(nav, [
|
||||
'cookieEnabled',
|
||||
'doNotTrack',
|
||||
'hardwareConcurrency',
|
||||
'language',
|
||||
'languages',
|
||||
'maxTouchPoints',
|
||||
'onLine',
|
||||
'plugins',
|
||||
'productSub',
|
||||
'browserLanguage',
|
||||
'systemLanguage',
|
||||
'userLanguage',
|
||||
'userAgent'
|
||||
]);
|
||||
|
||||
device.screen = _.pick(window.screen, [
|
||||
"availHeight",
|
||||
"availLeft",
|
||||
"availTop",
|
||||
"availWidth",
|
||||
"colorDepth",
|
||||
"height",
|
||||
"pixelDepth",
|
||||
"width"
|
||||
]);
|
||||
|
||||
device.screen.body = _.pick(document.body, 'clientWidth', 'clientHeight', 'offsetWidth', 'offsetHeight', 'scrollWidth', 'scrollHeight');
|
||||
device.screen.pixelRatio = window.devicePixelRatio;
|
||||
|
||||
var orientation = window.screen.orientation || window.screen.mozOrientation || window.screen.msOrientation;
|
||||
|
||||
if(!_.isString(orientation))
|
||||
orientation = _.pick(orientation, [ 'type', 'angle' ]);
|
||||
|
||||
device.screen.orientation = orientation;
|
||||
|
||||
device.modernizr = _.compact($(document.documentElement).attr('class').split(' '));
|
||||
|
||||
//nav.javaEnabled = nav.javaEnabled();
|
||||
var $div = $('#content');
|
||||
_.each(device, function(value, key) {
|
||||
$div.append($('<h2>' + key + '</h2>'));
|
||||
var $pre = $('<pre id="' + key + '">');
|
||||
$pre.text(JSON.stringify(value, null, 2));
|
||||
$div.append($pre);
|
||||
});
|
||||
|
||||
|
||||
// TODO maybe have server send Headers from AJAX request
|
||||
var id = window.location.search ? window.location.search.split('=')[1] : 'null';
|
||||
|
||||
var path = window.location.protocol + '//' + window.location.host + '/api/fingerprints/' + id;
|
||||
|
||||
console.log(path);
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
dataType: 'json',
|
||||
data: device,
|
||||
url: path,
|
||||
success: function(res) {
|
||||
var key = 'headers';
|
||||
$div.append($('<h2>' + key + '</h2>'));
|
||||
var $pre = $('<pre id="' + key + '">');
|
||||
$pre.text(JSON.stringify(res.headers, null, 2));
|
||||
$div.append($pre);
|
||||
console.log('success');
|
||||
},
|
||||
error: function() {
|
||||
console.log('error');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
},{}]},{},[2])
|
||||
//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9mYWN0b3ItYnVuZGxlL25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJzcmMvanMvYXBwLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIkKGZ1bmN0aW9uKCkge1xuXHR2YXIgZGV2aWNlID0ge307XG5cblx0dmFyIG5hdiA9IF8uY2xvbmUod2luZG93Lm5hdmlnYXRvcik7XG5cblx0bmF2LnBsdWdpbnMgPSBfLm1hcChuYXZpZ2F0b3IucGx1Z2lucywgZnVuY3Rpb24ob2JqLCBrZXkpIHtcblx0XHRyZXR1cm4gb2JqLm5hbWUgKyAnICgnICsgb2JqLmZpbGVuYW1lICsgJyknO1xuXHR9KTtcblxuXHQvL2RldmljZS5uYXZpZ2F0b3IgPSBfLm9taXQobmF2LCBbXG5cdC8vXHQnYXBwQ29kZU5hbWUnLFxuXHQvL1x0J2FwcE1pbm9yVmVyc2lvbicsXG5cdC8vXHQnYXBwTmFtZScsXG5cdC8vXHQnYXBwVmVyc2lvbicsXG5cdC8vXHQnYmF0dGVyeScsXG5cdC8vXHQnY3B1Q2xhc3MnLFxuXHQvL1x0J2dlb2xvY2F0aW9uJyxcblx0Ly9cdCdtaW1lVHlwZXMnLFxuXHQvL1x0J29zY3B1Jyxcblx0Ly9cdCdwbGF0Zm9ybScsXG5cdC8vXHQncHJvZHVjdCcsXG5cdC8vXHQndmVuZG9yJyxcblx0Ly9cdCd2ZW5kb3JTdWInXG5cdC8vXSk7XG5cdGRldmljZS5uYXZpZ2F0b3IgPSBfLnBpY2sobmF2LCBbXG5cdFx0J2Nvb2tpZUVuYWJsZWQnLFxuXHRcdCdkb05vdFRyYWNrJyxcblx0XHQnaGFyZHdhcmVDb25jdXJyZW5jeScsXG5cdFx0J2xhbmd1YWdlJyxcblx0XHQnbGFuZ3VhZ2VzJyxcblx0XHQnbWF4VG91Y2hQb2ludHMnLFxuXHRcdCdvbkxpbmUnLFxuXHRcdCdwbHVnaW5zJyxcblx0XHQncHJvZHVjdFN1YicsXG5cdFx0J2Jyb3dzZXJMYW5ndWFnZScsXG5cdFx0J3N5c3RlbUxhbmd1YWdlJyxcblx0XHQndXNlckxhbmd1YWdlJyxcblx0XHQndXNlckFnZW50J1xuXHRdKTtcblxuXHRkZXZpY2Uuc2NyZWVuID0gXy5waWNrKHdpbmRvdy5zY3JlZW4sIFtcblx0XHRcImF2YWlsSGVpZ2h0XCIsXG5cdFx0XCJhdmFpbExlZnRcIixcblx0XHRcImF2YWlsVG9wXCIsXG5cdFx0XCJhdmFpbFdpZHRoXCIsXG5cdFx0XCJjb2xvckRlcHRoXCIsXG5cdFx0XCJoZWlnaHRcIixcblx0XHRcInBpeGVsRGVwdGhcIixcblx0XHRcIndpZHRoXCJcblx0XSk7XG5cblx0ZGV2aWNlLnNjcmVlbi5ib2R5ID0gXy5waWNrKGRvY3VtZW50LmJvZHksICdjbGllbnRXaWR0aCcsICdjbGllbnRIZWlnaHQnLCAnb2Zmc2V0V2lkdGgnLCAnb2Zmc2V0SGVpZ2h0JywgJ3Njcm9sbFdpZHRoJywgJ3Njcm9sbEhlaWdodCcpO1xuXHRkZXZpY2Uuc2NyZWVuLnBpeGVsUmF0aW8gPSB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbztcblxuXHR2YXIgb3JpZW50YXRpb24gPSB3aW5kb3cuc2NyZWVuLm9yaWVudGF0aW9uIHx8IHdpbmRvdy5zY3JlZW4ubW96T3JpZW50YXRpb24gfHwgd2luZG93LnNjcmVlbi5tc09yaWVudGF0aW9uO1xuXG5cdGlmKCFfLmlzU3RyaW5nKG9yaWVudGF0aW9uKSlcblx0XHRvcmllbnRhdGlvbiA9IF8ucGljayhvcmllbnRhdGlvbiwgWyAndHlwZScsICdhbmdsZScgXSk7XG5cblx0ZGV2aWNlLnNjcmVlbi5vcmllbnRhdGlvbiA9IG9yaWVudGF0aW9uO1xuXG5cdGRldmljZS5tb2Rlcm5penIgPSBfLmNvbXBhY3QoJChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLmF0dHIoJ2NsYXNzJykuc3BsaXQoJyAnKSk7XG5cblx0Ly9uYXYuamF2YUVuYWJsZWQgPSBuYXYuamF2YUVuYWJsZWQoKTtcblx0dmFyICRkaXYgPSAkKCcjY29udGVudCcpO1xuXHRfLmVhY2goZGV2aWNlLCBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG5cdFx0JGRpdi5hcHBlbmQoJCgnPGgyPicgKyBrZXkgKyAnPC9oMj4nKSk7XG5cdFx0dmFyICRwcmUgPSAkKCc8cHJlIGlkPVwiJyArIGtleSArICdcIj4nKTtcblx0XHQkcHJlLnRleHQoSlNPTi5zdHJpbmdpZnkodmFsdWUsIG51bGwsIDIpKTtcblx0XHQkZGl2LmFwcGVuZCgkcHJlKTtcblx0fSk7XG5cblxuXHQvLyBUT0RPIG1heWJlIGhhdmUgc2VydmVyIHNlbmQgSGVhZGVycyBmcm9tIEFKQVggcmVxdWVzdFxuXHR2YXIgaWQgPSB3aW5kb3cubG9jYXRpb24uc2VhcmNoID8gd2luZG93LmxvY2F0aW9uLnNlYXJjaC5zcGxpdCgnPScpWzFdIDogJ251bGwnO1xuXG5cdHZhciBwYXRoID0gd2luZG93LmxvY2F0aW9uLnByb3RvY29sICsgJy8vJyArIHdpbmRvdy5sb2NhdGlvbi5ob3N0ICsgJy9hcGkvZmluZ2VycHJpbnRzLycgKyBpZDtcblxuXHRjb25zb2xlLmxvZyhwYXRoKTtcblx0JC5hamF4KHtcblx0XHRtZXRob2Q6ICdQT1NUJyxcblx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdGRhdGE6IGRldmljZSxcblx0XHR1cmw6IHBhdGgsXG5cdFx0c3VjY2VzczogZnVuY3Rpb24ocmVzKSB7XG5cdFx0XHR2YXIga2V5ID0gJ2hlYWRlcnMnO1xuXHRcdFx0JGRpdi5hcHBlbmQoJCgnPGgyPicgKyBrZXkgKyAnPC9oMj4nKSk7XG5cdFx0XHR2YXIgJHByZSA9ICQoJzxwcmUgaWQ9XCInICsga2V5ICsgJ1wiPicpO1xuXHRcdFx0JHByZS50ZXh0KEpTT04uc3RyaW5naWZ5KHJlcy5oZWFkZXJzLCBudWxsLCAyKSk7XG5cdFx0XHQkZGl2LmFwcGVuZCgkcHJlKTtcblx0XHRcdGNvbnNvbGUubG9nKCdzdWNjZXNzJyk7XG5cdFx0fSxcblx0XHRlcnJvcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRjb25zb2xlLmxvZygnZXJyb3InKTtcblx0XHR9XG5cdH0pO1xufSk7XG4iXX0=
|
||||
1
public/js/common.js
Normal file
1
public/js/common.js
Normal file
@ -0,0 +1 @@
|
||||
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({},{},[]);
|
||||
5
server/config/details.js
Normal file
5
server/config/details.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
title: 'Epiphany',
|
||||
name: 'epiphany'
|
||||
};
|
||||
|
||||
47
server/config/dir.js
Normal file
47
server/config/dir.js
Normal file
@ -0,0 +1,47 @@
|
||||
// MODULES
|
||||
|
||||
// modules : NATIVE
|
||||
|
||||
var path = require('path');
|
||||
|
||||
var PWD = process.env.PWD;
|
||||
|
||||
// Server folders. All folder related to the Node server handling most things.
|
||||
module.exports = {
|
||||
// Any code that needs to a "middle landing spot" while built, place it anywhere here
|
||||
build: {
|
||||
root: path.join(PWD, 'build')
|
||||
},
|
||||
|
||||
// public directories. Where all static/built/live content goes.
|
||||
public: {
|
||||
css: path.join(PWD, 'public', 'css'),
|
||||
fonts: path.join(PWD, 'public', 'fonts'),
|
||||
img: path.join(PWD, 'public', 'img'),
|
||||
root: path.join(PWD, 'public'),
|
||||
scripts: path.join(PWD, 'public', 'js')
|
||||
},
|
||||
|
||||
root: PWD,
|
||||
|
||||
server: {
|
||||
middleware: path.join(PWD, 'server', 'middleware'),
|
||||
models: path.join(PWD, 'server', 'models'),
|
||||
routes: path.join(PWD, 'server', 'routes'),
|
||||
root: path.join(PWD, 'server'),
|
||||
schemas: path.join(PWD, 'server', 'schema.org'),
|
||||
templates: path.join(PWD, 'server', 'templates'),
|
||||
uploads: path.join(PWD, 'server', 'uploads')
|
||||
},
|
||||
|
||||
// Source directories. This is where you put all content that needs to be built before use.
|
||||
src: {
|
||||
fonts: path.join(PWD, 'src', 'fonts'),
|
||||
raster: path.join(PWD, 'src', 'raster'),
|
||||
root: path.join(PWD, 'src'),
|
||||
sass: path.join(PWD, 'src', 'sass'),
|
||||
static: path.join(PWD, 'src', 'static'),
|
||||
scripts: path.join(PWD, 'src', 'js'),
|
||||
svg: path.join(PWD, 'src', 'svg'),
|
||||
}
|
||||
};
|
||||
12
server/config/domain.js
Normal file
12
server/config/domain.js
Normal file
@ -0,0 +1,12 @@
|
||||
var _ = require('lodash');
|
||||
|
||||
module.exports = function(config) {
|
||||
if(!config.port || !_.isNumber(config.port)) throw new Error('Port undefined or not a number');
|
||||
|
||||
return {
|
||||
development: 'localhost:' + config.port,
|
||||
testing: 'changeThisFool.testing.thecodebureau.com',
|
||||
staging: 'changeThisFool.thecodebureau.com',
|
||||
production: 'www.changeThisFool.se'
|
||||
}[ENV];
|
||||
};
|
||||
23
server/config/error-handler.js
Normal file
23
server/config/error-handler.js
Normal file
@ -0,0 +1,23 @@
|
||||
module.exports = {
|
||||
defaults: {
|
||||
mystify: {
|
||||
properties: [ 'message', 'name', 'status', 'statusText' ]
|
||||
},
|
||||
log: {
|
||||
// if database = true there has to be a mongoose model name ErrorModel
|
||||
ignore: [],
|
||||
}
|
||||
},
|
||||
development: {
|
||||
log: {
|
||||
database: false,
|
||||
console: true,
|
||||
}
|
||||
},
|
||||
production: {
|
||||
log: {
|
||||
database: true,
|
||||
console: false,
|
||||
}
|
||||
},
|
||||
};
|
||||
13
server/config/globals.js
Normal file
13
server/config/globals.js
Normal file
@ -0,0 +1,13 @@
|
||||
var path = require('path');
|
||||
|
||||
module.exports = function(bind) {
|
||||
bind = bind || global;
|
||||
|
||||
bind.ENV = process.env.NODE_ENV || 'development';
|
||||
bind.PWD = process.env.PWD;
|
||||
bind.DEBUG_ERROR_HANDLER = false;
|
||||
bind.DEBUG_RESPONDER = false;
|
||||
bind.LOGIN_USER = false;
|
||||
//bind.LOGIN_USER = 'username';
|
||||
//bind.LOGIN_USER = 'linus.miller@thecodebureau.com';
|
||||
};
|
||||
12
server/config/gulp.js
Normal file
12
server/config/gulp.js
Normal file
@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
browserify: {
|
||||
entries: [
|
||||
'app.js',
|
||||
'admin.js'
|
||||
],
|
||||
outputs: [
|
||||
'app.js',
|
||||
'admin.js'
|
||||
]
|
||||
}
|
||||
};
|
||||
8
server/config/mongo.js
Normal file
8
server/config/mongo.js
Normal file
@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
defaults: {
|
||||
uri: 'mongodb://localhost/fingerprint'
|
||||
},
|
||||
production: {
|
||||
uri: 'mongodb://fpSupreme:weIzTouching--Peeps@localhost/fingerprint'
|
||||
}
|
||||
};
|
||||
8
server/config/port.js
Normal file
8
server/config/port.js
Normal file
@ -0,0 +1,8 @@
|
||||
var basePort = 3810;
|
||||
|
||||
module.exports = {
|
||||
development: basePort,
|
||||
testing: basePort + 1,
|
||||
staging: basePort + 2,
|
||||
production: basePort + 3
|
||||
}[ENV];
|
||||
14
server/config/session.js
Normal file
14
server/config/session.js
Normal file
@ -0,0 +1,14 @@
|
||||
module.exports = {
|
||||
defaults: {
|
||||
secret: 'changeThisFool',
|
||||
resave: true,
|
||||
saveUninitialized: true
|
||||
},
|
||||
production: {
|
||||
redis: {
|
||||
port: 6379,
|
||||
host: 'localhost'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
66
server/middleware/api/fingerprints.js
Normal file
66
server/middleware/api/fingerprints.js
Normal file
@ -0,0 +1,66 @@
|
||||
var UAParser = require('ua-parser-js');
|
||||
var parser = new UAParser();
|
||||
|
||||
module.exports = function(config, mongoose) {
|
||||
var Fingerprint = mongoose.model('Fingerprint');
|
||||
|
||||
return {
|
||||
create: function(req, res, next) {
|
||||
Fingerprint.create(req.body, function(err, fp) {
|
||||
if(err) return next(err);
|
||||
|
||||
res.status(200).data.fingerprint = fp;
|
||||
next();
|
||||
});
|
||||
},
|
||||
|
||||
findAll: function(req, res, next) {
|
||||
|
||||
},
|
||||
|
||||
push: function(req, res, next) {
|
||||
var ua = req.get('user-agent');
|
||||
parser.setUA(ua);
|
||||
var uaParsed = _.omit(parser.getResult(), 'ua');
|
||||
var headers = _.omit(req.headers, [ 'cookie', 'user-agent' ]);
|
||||
var ip = req.ip;
|
||||
|
||||
var clientFingerprint = _.extend({
|
||||
ip: ip,
|
||||
ua: ua,
|
||||
uaParsed: uaParsed,
|
||||
headers: headers
|
||||
}, req.body);
|
||||
|
||||
res.data.clientFingerprint = clientFingerprint;
|
||||
|
||||
if(req.params.id !== 'null') {
|
||||
Fingerprint.findById( req.params.id, function(err, fp) {
|
||||
if(err) return next(err);
|
||||
|
||||
if(fp) {
|
||||
if(!_.find(fp.client, { ua: ua })) {
|
||||
|
||||
fp.client.push(clientFingerprint);
|
||||
|
||||
fp.save(function(err, fp) {
|
||||
if(err) console.error(err);
|
||||
|
||||
res.status(201);
|
||||
|
||||
next();
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
res.status(200);
|
||||
next();
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
49
server/middleware/ua.js
Normal file
49
server/middleware/ua.js
Normal file
@ -0,0 +1,49 @@
|
||||
var UAParser = require('ua-parser-js');
|
||||
var parser = new UAParser();
|
||||
|
||||
module.exports = function(config, mongoose) {
|
||||
var Fingerprint = mongoose.model('Fingerprint');
|
||||
|
||||
return function userAgent(req, res, next){
|
||||
var ua = req.get('user-agent');
|
||||
|
||||
parser.setUA(ua);
|
||||
|
||||
var uaParsed = _.omit(parser.getResult(), 'ua');
|
||||
var headers = _.omit(req.headers, [ 'cookie', 'user-agent' ]);
|
||||
|
||||
if(!_.isEmpty(req.query))
|
||||
var ip = req.ip;
|
||||
|
||||
Fingerprint.findById( req.query.id, function(err, fp) {
|
||||
if(err) return next(err);
|
||||
|
||||
if(fp) {
|
||||
if(!_.find(fp.server, { ua: ua })) {
|
||||
var obj = {
|
||||
ip: ip,
|
||||
ua: ua,
|
||||
uaParsed: uaParsed,
|
||||
headers: headers
|
||||
};
|
||||
|
||||
fp.server.push(obj);
|
||||
|
||||
fp.save(function(err, fp) {
|
||||
if(err) console.error(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
res.locals = {
|
||||
ua: ua,
|
||||
uaParsed: uaParsed,
|
||||
headers: headers
|
||||
};
|
||||
|
||||
next();
|
||||
};
|
||||
};
|
||||
|
||||
31
server/models/fingerprint.js
Normal file
31
server/models/fingerprint.js
Normal file
@ -0,0 +1,31 @@
|
||||
module.exports = function(mongoose) {
|
||||
// for information generated client side
|
||||
var ClientSchema = new mongoose.Schema({
|
||||
ua: String,
|
||||
uaParsed: {},
|
||||
ip: String,
|
||||
headers: {},
|
||||
datestamp: { type: Date, default: Date.now },
|
||||
screen: {},
|
||||
modernizr: [],
|
||||
navigator: {}
|
||||
});
|
||||
|
||||
var ServerSchema = new mongoose.Schema({
|
||||
ua: String,
|
||||
ip: String,
|
||||
datestamp: { type: Date, default: Date.now },
|
||||
uaParsed: {},
|
||||
headers: {},
|
||||
});
|
||||
|
||||
var Schema = new mongoose.Schema({
|
||||
_id: { type: String, required: true },
|
||||
name: { type: String, required: true },
|
||||
project: String,
|
||||
client: [ ClientSchema ],
|
||||
server: [ ServerSchema ]
|
||||
});
|
||||
|
||||
mongoose.model('Fingerprint', Schema);
|
||||
};
|
||||
14
server/routes/_index.js
Normal file
14
server/routes/_index.js
Normal file
@ -0,0 +1,14 @@
|
||||
module.exports = function(mw, epiphany) {
|
||||
return [
|
||||
[ 'get', '/', [ mw.ua, function pg(req, res, next) {
|
||||
res.master = 'pages/index';
|
||||
next();
|
||||
} ] ],
|
||||
[ 'get', '/admin', [ function pg(req, res, next) {
|
||||
res.master = 'pages/admin';
|
||||
next();
|
||||
} ] ],
|
||||
[ 'post', '/api/fingerprints', mw.api.fingerprints.create ],
|
||||
[ 'post', '/api/fingerprints/:id', mw.api.fingerprints.push ]
|
||||
];
|
||||
};
|
||||
7
server/server.js
Normal file
7
server/server.js
Normal file
@ -0,0 +1,7 @@
|
||||
var Epiphany = require('epiphany');
|
||||
|
||||
var server = new Epiphany();
|
||||
|
||||
server.dust.filters.jsp = function(value) {
|
||||
return JSON.stringify(value, null, 2);
|
||||
};
|
||||
9
server/templates/error.dust
Normal file
9
server/templates/error.dust
Normal file
@ -0,0 +1,9 @@
|
||||
<div class="error row">
|
||||
<div class="col">
|
||||
<h1>Oops!</h1>
|
||||
<p>Ett problem har tyvärr uppstått.<p>
|
||||
<h2>{error.status} : {error.statusText}</h2>
|
||||
<p>{error.message}<p>
|
||||
<pre>{error.stack}</pre>
|
||||
</div>
|
||||
</div>
|
||||
23
server/templates/pages/admin.dust
Normal file
23
server/templates/pages/admin.dust
Normal file
@ -0,0 +1,23 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>The Code Bureau : Browser Fingerprint</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<form method="post" action="/api/fingerprints">
|
||||
<div>
|
||||
<input type="text" name="_id" placeholder="Id" /><button type="button" class="generate">Generate</button>
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" name="name" placeholder="Name" />
|
||||
</div>
|
||||
<div>
|
||||
<input type="text" name="project" placeholder="Project" />
|
||||
</div>
|
||||
<button>Submit</button>
|
||||
</form>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<script src="/js/admin.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
52
server/templates/pages/index.dust
Normal file
52
server/templates/pages/index.dust
Normal file
@ -0,0 +1,52 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>The Code Bureau : Browser Fingerprint</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
body {
|
||||
padding: 15px;
|
||||
}
|
||||
div {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
pre {
|
||||
white-space: -moz-pre-wrap;
|
||||
white-space: -o-pre-wrap;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
button {
|
||||
display: block;
|
||||
margin: 10px auto;
|
||||
padding: 10px 30px;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<h1>Server</h1>
|
||||
<h2>User Agent</h2>
|
||||
{ua}
|
||||
<pre>{uaParsed|jsp}</pre>
|
||||
|
||||
<h2>Headers</h2>
|
||||
|
||||
<pre>{headers|jsp}</pre>
|
||||
|
||||
<h1>Client</h1>
|
||||
|
||||
<noscript>No JavaScript</noscript>
|
||||
</div>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"/></script>
|
||||
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
|
||||
<script src="/js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
27
src/js/admin.js
Normal file
27
src/js/admin.js
Normal file
@ -0,0 +1,27 @@
|
||||
require('jquery-jsonify');
|
||||
|
||||
var fairdice = require('fair-dice');
|
||||
|
||||
$(function() {
|
||||
$('form button.generate').on('click', function() {
|
||||
console.log(fairdice.string());
|
||||
$('form input[name="_id"]').val(fairdice.string(6));
|
||||
});
|
||||
$('form').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
var $form = $(this);
|
||||
|
||||
$.ajax({
|
||||
url: $form.attr('action'),
|
||||
dataType: 'json',
|
||||
method: 'POST',
|
||||
data: $form.JSONify(),
|
||||
success: function(res) {
|
||||
console.log('success');
|
||||
console.log(res);
|
||||
var path = window.location.protocol + '//' + window.location.host + '/?id=' + res._id;
|
||||
$form.before('<div><h1>Added</h1><a href="' + path + '">' + path + '</a></div>');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
97
src/js/app.js
Normal file
97
src/js/app.js
Normal file
@ -0,0 +1,97 @@
|
||||
$(function() {
|
||||
var device = {};
|
||||
|
||||
var nav = _.clone(window.navigator);
|
||||
|
||||
nav.plugins = _.map(navigator.plugins, function(obj, key) {
|
||||
return obj.name + ' (' + obj.filename + ')';
|
||||
});
|
||||
|
||||
//device.navigator = _.omit(nav, [
|
||||
// 'appCodeName',
|
||||
// 'appMinorVersion',
|
||||
// 'appName',
|
||||
// 'appVersion',
|
||||
// 'battery',
|
||||
// 'cpuClass',
|
||||
// 'geolocation',
|
||||
// 'mimeTypes',
|
||||
// 'oscpu',
|
||||
// 'platform',
|
||||
// 'product',
|
||||
// 'vendor',
|
||||
// 'vendorSub'
|
||||
//]);
|
||||
device.navigator = _.pick(nav, [
|
||||
'cookieEnabled',
|
||||
'doNotTrack',
|
||||
'hardwareConcurrency',
|
||||
'language',
|
||||
'languages',
|
||||
'maxTouchPoints',
|
||||
'onLine',
|
||||
'plugins',
|
||||
'productSub',
|
||||
'browserLanguage',
|
||||
'systemLanguage',
|
||||
'userLanguage',
|
||||
'userAgent'
|
||||
]);
|
||||
|
||||
device.screen = _.pick(window.screen, [
|
||||
"availHeight",
|
||||
"availLeft",
|
||||
"availTop",
|
||||
"availWidth",
|
||||
"colorDepth",
|
||||
"height",
|
||||
"pixelDepth",
|
||||
"width"
|
||||
]);
|
||||
|
||||
device.screen.body = _.pick(document.body, 'clientWidth', 'clientHeight', 'offsetWidth', 'offsetHeight', 'scrollWidth', 'scrollHeight');
|
||||
device.screen.pixelRatio = window.devicePixelRatio;
|
||||
|
||||
var orientation = window.screen.orientation || window.screen.mozOrientation || window.screen.msOrientation;
|
||||
|
||||
if(!_.isString(orientation))
|
||||
orientation = _.pick(orientation, [ 'type', 'angle' ]);
|
||||
|
||||
device.screen.orientation = orientation;
|
||||
|
||||
device.modernizr = _.compact($(document.documentElement).attr('class').split(' '));
|
||||
|
||||
//nav.javaEnabled = nav.javaEnabled();
|
||||
var $div = $('#content');
|
||||
_.each(device, function(value, key) {
|
||||
$div.append($('<h2>' + key + '</h2>'));
|
||||
var $pre = $('<pre id="' + key + '">');
|
||||
$pre.text(JSON.stringify(value, null, 2));
|
||||
$div.append($pre);
|
||||
});
|
||||
|
||||
|
||||
// TODO maybe have server send Headers from AJAX request
|
||||
var id = window.location.search ? window.location.search.split('=')[1] : 'null';
|
||||
|
||||
var path = window.location.protocol + '//' + window.location.host + '/api/fingerprints/' + id;
|
||||
|
||||
console.log(path);
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
dataType: 'json',
|
||||
data: device,
|
||||
url: path,
|
||||
success: function(res) {
|
||||
var key = 'headers';
|
||||
$div.append($('<h2>' + key + '</h2>'));
|
||||
var $pre = $('<pre id="' + key + '">');
|
||||
$pre.text(JSON.stringify(res.headers, null, 2));
|
||||
$div.append($pre);
|
||||
console.log('success');
|
||||
},
|
||||
error: function() {
|
||||
console.log('error');
|
||||
}
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user