Seperated common crypto operations to common file and made common toolbar used for both pad and spreadsheet
This commit is contained in:
77
www/common/crypto.js
Normal file
77
www/common/crypto.js
Normal file
@@ -0,0 +1,77 @@
|
||||
define([
|
||||
'/bower_components/tweetnacl/nacl-fast.min.js',
|
||||
], function () {
|
||||
var Nacl = window.nacl;
|
||||
var module = { exports: {} };
|
||||
|
||||
var encryptStr = function (str, key) {
|
||||
var array = Nacl.util.decodeUTF8(str);
|
||||
var nonce = Nacl.randomBytes(24);
|
||||
var packed = Nacl.secretbox(array, nonce, key);
|
||||
if (!packed) { throw new Error(); }
|
||||
return Nacl.util.encodeBase64(nonce) + "|" + Nacl.util.encodeBase64(packed);
|
||||
};
|
||||
|
||||
var decryptStr = function (str, key) {
|
||||
var arr = str.split('|');
|
||||
if (arr.length !== 2) { throw new Error(); }
|
||||
var nonce = Nacl.util.decodeBase64(arr[0]);
|
||||
var packed = Nacl.util.decodeBase64(arr[1]);
|
||||
var unpacked = Nacl.secretbox.open(packed, nonce, key);
|
||||
if (!unpacked) { throw new Error(); }
|
||||
return Nacl.util.encodeUTF8(unpacked);
|
||||
};
|
||||
|
||||
// this is crap because of bencoding messages... it should go away....
|
||||
var splitMessage = function (msg, sending) {
|
||||
var idx = 0;
|
||||
var nl;
|
||||
for (var i = ((sending) ? 0 : 1); i < 3; i++) {
|
||||
nl = msg.indexOf(':',idx);
|
||||
idx = nl + Number(msg.substring(idx,nl)) + 1;
|
||||
}
|
||||
return [ msg.substring(0,idx), msg.substring(msg.indexOf(':',idx) + 1) ];
|
||||
};
|
||||
|
||||
var encrypt = module.exports.encrypt = function (msg, key) {
|
||||
var spl = splitMessage(msg, true);
|
||||
var json = JSON.parse(spl[1]);
|
||||
// non-patches are not encrypted.
|
||||
if (json[0] !== 2) { return msg; }
|
||||
json[1] = encryptStr(JSON.stringify(json[1]), key);
|
||||
var res = JSON.stringify(json);
|
||||
return spl[0] + res.length + ':' + res;
|
||||
};
|
||||
|
||||
var decrypt = module.exports.decrypt = function (msg, key) {
|
||||
var spl = splitMessage(msg, false);
|
||||
var json = JSON.parse(spl[1]);
|
||||
// non-patches are not encrypted.
|
||||
if (json[0] !== 2) { return msg; }
|
||||
if (typeof(json[1]) !== 'string') { throw new Error(); }
|
||||
json[1] = JSON.parse(decryptStr(json[1], key));
|
||||
var res = JSON.stringify(json);
|
||||
return spl[0] + res.length + ':' + res;
|
||||
};
|
||||
|
||||
var parseKey = module.exports.parseKey = function (str) {
|
||||
var array = Nacl.util.decodeBase64(str);
|
||||
var hash = Nacl.hash(array);
|
||||
var lk = hash.subarray(32);
|
||||
return {
|
||||
lookupKey: lk,
|
||||
cryptKey: hash.subarray(0,32),
|
||||
channel: Nacl.util.encodeBase64(lk).substring(0,10)
|
||||
};
|
||||
};
|
||||
|
||||
var rand64 = module.exports.rand64 = function (bytes) {
|
||||
return Nacl.util.encodeBase64(Nacl.randomBytes(bytes));
|
||||
};
|
||||
|
||||
var genKey = module.exports.genKey = function () {
|
||||
return rand64(18);
|
||||
};
|
||||
|
||||
return module.exports;
|
||||
});
|
||||
@@ -1,4 +1,6 @@
|
||||
var Toolbar = function ($, container, Messages, myUserName, realtime) {
|
||||
define([
|
||||
'/common/messages.js'
|
||||
], function (Messages) {
|
||||
|
||||
/** Id of the element for getting debug info. */
|
||||
var DEBUG_LINK_CLS = 'rtwysiwyg-debug-link';
|
||||
@@ -22,15 +24,15 @@ var Toolbar = function ($, container, Messages, myUserName, realtime) {
|
||||
return 'rtwysiwyg-uid-' + String(Math.random()).substring(2);
|
||||
};
|
||||
|
||||
var createRealtimeToolbar = function (container) {
|
||||
var createRealtimeToolbar = function ($container) {
|
||||
var id = uid();
|
||||
$(container).prepend(
|
||||
$container.prepend(
|
||||
'<div class="' + TOOLBAR_CLS + '" id="' + id + '">' +
|
||||
'<div class="rtwysiwyg-toolbar-leftside"></div>' +
|
||||
'<div class="rtwysiwyg-toolbar-rightside"></div>' +
|
||||
'</div>'
|
||||
);
|
||||
var toolbar = $('#'+id);
|
||||
var toolbar = $container.find('#'+id);
|
||||
toolbar.append([
|
||||
'<style>',
|
||||
'.' + TOOLBAR_CLS + ' {',
|
||||
@@ -77,10 +79,10 @@ var Toolbar = function ($, container, Messages, myUserName, realtime) {
|
||||
return toolbar;
|
||||
};
|
||||
|
||||
var createSpinner = function (container) {
|
||||
var createSpinner = function ($container) {
|
||||
var id = uid();
|
||||
$(container).append('<div class="rtwysiwyg-spinner" id="'+id+'"></div>');
|
||||
return $('#'+id)[0];
|
||||
$container.append('<div class="rtwysiwyg-spinner" id="'+id+'"></div>');
|
||||
return $container.find('#'+id)[0];
|
||||
};
|
||||
|
||||
var kickSpinner = function (spinnerElement, reversed) {
|
||||
@@ -93,10 +95,10 @@ var Toolbar = function ($, container, Messages, myUserName, realtime) {
|
||||
}, SPINNER_DISAPPEAR_TIME);
|
||||
};
|
||||
|
||||
var createUserList = function (container) {
|
||||
var createUserList = function ($container) {
|
||||
var id = uid();
|
||||
$(container).prepend('<div class="' + USER_LIST_CLS + '" id="'+id+'"></div>');
|
||||
return $('#'+id)[0];
|
||||
$container.prepend('<div class="' + USER_LIST_CLS + '" id="'+id+'"></div>');
|
||||
return $container.find('#'+id)[0];
|
||||
};
|
||||
|
||||
var updateUserList = function (myUserName, listElement, userList) {
|
||||
@@ -115,10 +117,10 @@ var Toolbar = function ($, container, Messages, myUserName, realtime) {
|
||||
}
|
||||
};
|
||||
|
||||
var createLagElement = function (container) {
|
||||
var createLagElement = function ($container) {
|
||||
var id = uid();
|
||||
$(container).append('<div class="' + LAG_ELEM_CLS + '" id="'+id+'"></div>');
|
||||
return $('#'+id)[0];
|
||||
$container.append('<div class="' + LAG_ELEM_CLS + '" id="'+id+'"></div>');
|
||||
return $container.find('#'+id)[0];
|
||||
};
|
||||
|
||||
var checkLag = function (realtime, lagElement) {
|
||||
@@ -133,40 +135,49 @@ var Toolbar = function ($, container, Messages, myUserName, realtime) {
|
||||
lagElement.textContent = lagMsg;
|
||||
};
|
||||
|
||||
var create = function ($container, myUserName, realtime) {
|
||||
var toolbar = createRealtimeToolbar($container);
|
||||
var userListElement = createUserList(toolbar.find('.rtwysiwyg-toolbar-leftside'));
|
||||
var spinner = createSpinner(toolbar.find('.rtwysiwyg-toolbar-rightside'));
|
||||
var lagElement = createLagElement(toolbar.find('.rtwysiwyg-toolbar-rightside'));
|
||||
|
||||
var toolbar = createRealtimeToolbar(container);
|
||||
var userListElement = createUserList(toolbar.find('.rtwysiwyg-toolbar-leftside'));
|
||||
var spinner = createSpinner(toolbar.find('.rtwysiwyg-toolbar-rightside'));
|
||||
var lagElement = createLagElement(toolbar.find('.rtwysiwyg-toolbar-rightside'));
|
||||
var connected = false;
|
||||
|
||||
var connected = false;
|
||||
realtime.onUserListChange(function (userList) {
|
||||
if (userList.indexOf(myUserName) !== -1) { connected = true; }
|
||||
if (!connected) { return; }
|
||||
updateUserList(myUserName, userListElement, userList);
|
||||
});
|
||||
|
||||
realtime.onUserListChange(function (userList) {
|
||||
if (userList.indexOf(myUserName) !== -1) { connected = true; }
|
||||
if (!connected) { return; }
|
||||
updateUserList(myUserName, userListElement, userList);
|
||||
});
|
||||
var ks = function () {
|
||||
if (connected) { kickSpinner(spinner, false); }
|
||||
};
|
||||
|
||||
var ks = function () {
|
||||
if (connected) { kickSpinner(spinner, false); }
|
||||
realtime.onPatch(ks);
|
||||
// Try to filter out non-patch messages, doesn't have to be perfect this is just the spinner
|
||||
realtime.onMessage(function (msg) { if (msg.indexOf(':[2,') > -1) { ks(); } });
|
||||
|
||||
setInterval(function () {
|
||||
if (!connected) { return; }
|
||||
checkLag(realtime, lagElement);
|
||||
}, 3000);
|
||||
|
||||
return {
|
||||
failed: function () {
|
||||
connected = false;
|
||||
userListElement.textContent = '';
|
||||
lagElement.textContent = '';
|
||||
},
|
||||
reconnecting: function () {
|
||||
connected = false;
|
||||
userListElement.textContent = Messages.reconnecting;
|
||||
lagElement.textContent = '';
|
||||
},
|
||||
connected: function () {
|
||||
connected = true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
realtime.onPatch(ks);
|
||||
realtime.onMessage(ks);
|
||||
|
||||
setInterval(function () {
|
||||
if (!connected) { return; }
|
||||
checkLag(realtime, lagElement);
|
||||
}, 3000);
|
||||
|
||||
return {
|
||||
reconnecting: function () {
|
||||
connected = false;
|
||||
userListElement.textContent = Messages.reconnecting;
|
||||
lagElement.textContent = '';
|
||||
},
|
||||
connected: function () {
|
||||
connected = true;
|
||||
}
|
||||
};
|
||||
};
|
||||
return { create: create };
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user