283 lines
10 KiB
JavaScript
283 lines
10 KiB
JavaScript
var app = angular.module('souris-app', ['souris-common', 'hljs']).
|
|
config(function ($routeProvider) {
|
|
$routeProvider.
|
|
when('/', {controller: CreateCtrl, templateUrl: 'create.html'}).
|
|
when('/:id!:key', {controller: ViewCtrl, templateUrl: 'view.html'}).
|
|
when('/:id', {controller: ViewCtrl, templateUrl: 'view.html'}).
|
|
otherwise({redirectTo: '/'});
|
|
});
|
|
|
|
var TEXT = "";
|
|
function CreateCtrl($scope, $remoteService, $location, $route) {
|
|
"use strict";
|
|
|
|
$scope.reload = $route.reload;
|
|
$scope.o = {text: TEXT};
|
|
|
|
var base_url = $location.absUrl();
|
|
base_url = base_url.slice(0, base_url.indexOf('#'));
|
|
$scope.$base_url = base_url;
|
|
|
|
// Add Randomness to RNG
|
|
console.info("Adding extra entropy from server and user input.");
|
|
$scope.entropy = 0;
|
|
var addEntropy = function (s) {
|
|
$scope.entropy += s.length;
|
|
fn.seed(s, {entropy: true});
|
|
};
|
|
$remoteService('/paste/rng').get().success(addEntropy);
|
|
|
|
(function (events, count) {
|
|
var t = [];
|
|
|
|
function w(e) {
|
|
t.push([e.pageX, e.pageY, e.keyCode, +new Date]);
|
|
if (t.length < count) {
|
|
return;
|
|
}
|
|
addEntropy(t);
|
|
$scope.$apply();
|
|
t = [];
|
|
}
|
|
|
|
for (var i in events)
|
|
if (events.hasOwnProperty(i))
|
|
document.addEventListener(events[i], w);
|
|
})(['mousemove', 'keydown', 'keypress', 'click', 'scroll'], 16);
|
|
|
|
$scope.HighliteLang = fn.obj(HighliteLang);
|
|
$scope.ExpireTimes = fn.obj(ExpireTimes);
|
|
|
|
// Encrypt and send function
|
|
$scope.Encrypt = function (o) {
|
|
if (o.text.length > 512) {o.zip = true; $scope.o.zip = true; }
|
|
var e = encrypt(o);
|
|
|
|
console.log("Sending:\n" + json(e));
|
|
|
|
$remoteService('/paste')
|
|
.post({}, e.txt)
|
|
.success(function (d) {
|
|
console.log("Received:\n" + d);
|
|
d = d.split(' ');
|
|
$scope.result = {status: d[0], id: d[1], key: e.key, text: e.txt};
|
|
});
|
|
|
|
};
|
|
}
|
|
CreateCtrl.$inject = ['$scope', '$remoteService', '$location', '$route'];
|
|
|
|
function ViewCtrl($scope, $params, $remoteService, $location) {
|
|
"use strict";
|
|
|
|
var base_url = $location.absUrl();
|
|
base_url = base_url.slice(0, base_url.indexOf('#'));
|
|
$scope.$base_url = base_url;
|
|
|
|
var id = $params.id,
|
|
key = $params.key;
|
|
|
|
$scope.id = id;
|
|
$scope.key = key;
|
|
|
|
function store(o) {
|
|
$scope.store = o;
|
|
}
|
|
$scope.copy = function(t) {
|
|
TEXT = t;
|
|
$location.path('/');
|
|
}
|
|
$remoteService('/paste/:id')
|
|
.get({id: id})
|
|
.success(decrypt(key, store))
|
|
.error(function(d, c){
|
|
var msg = '';
|
|
switch(c){
|
|
case 403: msg = 'Authentication Required.'; break;
|
|
case 404: msg = 'Message Not Found.'; break;
|
|
case 410: msg = 'Message Expired.'; break;
|
|
}
|
|
$scope.store = {err:msg, code:c};
|
|
});
|
|
}
|
|
ViewCtrl.$inject = ['$scope', '$routeParams', '$remoteService', '$location'];
|
|
|
|
var HighliteLang = [["text", "Plain Text"], ["apache", "Apache"], ["bash", "Bash"], ["coffeescript", "CoffeeScript"], ["cpp", "C++"], ["cs", "C#"], ["css", "CSS"], ["diff", "Diff"], ["http", "HTTP"], ["ini", "Ini"], ["java", "Java"], ["javascript", "JavaScript"], ["json", "JSON"], ["makefile", "Makefile"], ["markdown", "Markdown"], ["nginx", "Nginx"], ["objectivec", "Objective C"], ["perl", "Perl"], ["php", "PHP"], ["python", "Python"], ["ruby", "Ruby"], ["sql", "SQL"], ["xml", "HTML, XML"]];
|
|
var ExpireTimes = [[3600, "1 Hour"], [86400, "1 Day"], [604800, "1 Week"], [2419200, "4 Weeks"], [15778463, "6 Months"], [31556926, "1 Year"]];
|
|
var fn = {
|
|
sha: function (s) { return this.b64(CryptoJS.SHA256(s)); },
|
|
rmd: function (s) { return this.b64(CryptoJS.RIPEMD160(s)); },
|
|
chk: function (s) { return this.b64(CryptoJS.RIPEMD160(CryptoJS.SHA256(s))); },
|
|
enc: function (t, p) { return CryptoJS.AES.encrypt(t, p).toString(); },
|
|
dec: function (c, p) { return CryptoJS.AES.decrypt(c, p); },
|
|
b64: function (s) {
|
|
if (s == undefined) return;
|
|
return CryptoJS.enc.Base64.stringify(s).replace(/[=]+/, '').replace(/\//g, '_').replace(/\+/g, '-');
|
|
},
|
|
d64: function (s) {
|
|
if (s == undefined) return;
|
|
switch (s.length % 3) {
|
|
case 2:
|
|
s += '=';
|
|
// fallthrough
|
|
case 1:
|
|
s += '=';
|
|
}
|
|
return CryptoJS.enc.Base64.parse(s.replace(/_/g, '/').replace(/-/g, '+'));
|
|
},
|
|
rng: function (n) { return this.b64(CryptoJS.lib.WordArray.random(n)); },
|
|
seed: Math.seedrandom,
|
|
u8a: function (wa) {
|
|
var w = wa.words;
|
|
var b = new Uint8Array(w.length * 4), v, i, j, k = 0;
|
|
for (i = 0; i < w.length; ++i) {
|
|
v = w[i];
|
|
for (j = 3; j >= 0; --j) {
|
|
b[k++] = ((v >> 8 * j) & 0xFF);
|
|
}
|
|
}
|
|
return b;
|
|
},
|
|
u16a: function (ua) {
|
|
var s = '';
|
|
for (var i = 0; i < ua.length; i++) {
|
|
s += ('0' + ua[i].toString(16)).slice(-2);
|
|
}
|
|
return CryptoJS.enc.Hex.parse(s);
|
|
},
|
|
str8: function (ua) {
|
|
var s = '';
|
|
for (var i = 0; i < ua.byteLength; i++) {
|
|
if ((ua[i]&0x80) == 0) s += String.fromCharCode(ua[i]);
|
|
else if ((ua[i]&0xe0) == 0xc0 && (ua[i+1]&0xc0) == 0x80) {
|
|
s += String.fromCharCode(((ua[i]&0x1f)<<6) + (ua[i+1]&0x3f));
|
|
i += 1;
|
|
}
|
|
else if ((ua[i]&0xf0) == 0xe0 && (ua[i+1]&0xc0) == 0x80 && (ua[i+2]&0xc0) == 0x80){
|
|
s += String.fromCharCode(((ua[i]&0x0f)<<12) + ((ua[i+1]&0x3f)<<6) + (ua[i+2]&0x3f));
|
|
i += 2;
|
|
}
|
|
else if ((ua[i]&0xf8) == 0xf0 && (ua[i+1]&0xc0) == 0x80 && (ua[i+2]&0xc0) == 0x80 && (ua[i+3]&0xc0) == 0x80) {
|
|
s += String.fromCharCode(((ua[i]&0x0f)<<18) + ((ua[i+1]&0x3f)<<12) + ((ua[i+2]&0x3f)<<6) + (ua[i+3]&0x3f));
|
|
i += 3;
|
|
}
|
|
else { s += String.fromCharCode(65533); }
|
|
}
|
|
return s;
|
|
},
|
|
obj: function (a) {
|
|
var o = [];
|
|
for (var i = 0; i < a.length; i++) {
|
|
o.push({key: a[i][0], val: a[i][1]});
|
|
}
|
|
return o;
|
|
}
|
|
};
|
|
|
|
var decrypt = function (key, tgt) {
|
|
return function (d) {
|
|
|
|
if (d.length === 0) tgt({err: "Not Found", code: 'not_found'});
|
|
|
|
var s = d.split('\n');
|
|
d = {};
|
|
var i = 0;
|
|
|
|
while (true) {
|
|
if (s[i] == "") break;
|
|
|
|
var l = s[i].trim().split(':\t');
|
|
d[l[0]] = l[1];
|
|
|
|
i++;
|
|
}
|
|
d.tx = s.splice(i).join('');
|
|
|
|
if (key === undefined) tgt({err: "Missing Key", code: 'no_key'});
|
|
else if (d.chk != fn.rmd(fn.d64(key))) tgt({err: "Invalid Key", code: "bad_key"});
|
|
else {
|
|
var tx;
|
|
if (d.zip) {
|
|
tx = fn.dec(d.tx, key);
|
|
tx = fn.u8a(tx);
|
|
tx = fn.str8(pako.inflate(tx));
|
|
} else {
|
|
tx = fn.dec(d.tx, key).toString(CryptoJS.enc.Utf8);
|
|
}
|
|
|
|
var lang = 'text';
|
|
for (i = 0; i < HighliteLang.length; i++)
|
|
if (d.lang == HighliteLang[i][0])
|
|
lang = HighliteLang[i][0];
|
|
|
|
tgt({code: 'ok', tx: tx, lang: lang, exp: d.exp, zip: d.zip});
|
|
}
|
|
};
|
|
};
|
|
|
|
var encrypt = function (o) {
|
|
var ts = Date.now();
|
|
console.info("Begin Encryption Process...");
|
|
|
|
var pass;
|
|
if (o.pass !== undefined) pass = fn.chk(o.pass);
|
|
|
|
var r = fn.rng(40);
|
|
var key = fn.sha(r);
|
|
var chk = fn.chk(r);
|
|
var text = o.text;
|
|
|
|
if (o.zip) {
|
|
console.info("Compressing text...");
|
|
var bl = o.text.length, bs = Date.now();
|
|
var deflate = pako.gzip(text);
|
|
text = fn.u16a(deflate);
|
|
|
|
console.info("Compress complete: " + (Date.now() - bs) + "ms, " + bl + " => " + o.text.length + " bytes");
|
|
}
|
|
var enc = fn.enc(text, key);
|
|
var exp = (o.exp === undefined ? undefined : (o.exp + Date.now() / 1000 | 0));
|
|
|
|
var header = {
|
|
'pass': pass,
|
|
'chk': chk,
|
|
'lang': o.lang,
|
|
'exp': exp,
|
|
'zip': o.zip,
|
|
'burn': o.burn
|
|
};
|
|
|
|
var s = '';
|
|
for (var i in header) if (header.hasOwnProperty(i)) if (header[i] !== undefined) {
|
|
s += i + ":\t" + header[i] + "\n";
|
|
}
|
|
s += "\n";
|
|
while (enc.length > 79) {
|
|
s += enc.slice(0, 79) + "\n";
|
|
enc = enc.slice(79);
|
|
}
|
|
s += enc + "\n";
|
|
|
|
console.info("Encrypt complete: " + (Date.now() - ts) + " ms");
|
|
return {'txt': s, 'key': key};
|
|
};
|
|
|
|
m.filter('blength', function () {
|
|
return function (o) {
|
|
if (!(typeof o == 'string' || o instanceof String)) return;
|
|
if (o === undefined || o.length === undefined) return;
|
|
var utf8length = 0;
|
|
for (var n = 0; n < o.length; n++) {
|
|
var c = o.charCodeAt(n);
|
|
if (c < 128) {
|
|
utf8length++;
|
|
}
|
|
else if ((c > 127) && (c < 2048)) {
|
|
utf8length = utf8length + 2;
|
|
} else {
|
|
utf8length = utf8length + 3;
|
|
}
|
|
}
|
|
return utf8length;
|
|
};
|
|
}); |