Improve realtime channel for onlyoffice
This commit is contained in:
parent
efdecd4059
commit
b79ba61984
@ -88,7 +88,10 @@ define([
|
|||||||
var openRtChannel = function (data) {
|
var openRtChannel = function (data) {
|
||||||
// XXX
|
// XXX
|
||||||
var channel = Hash.createChannelId();
|
var channel = Hash.createChannelId();
|
||||||
ctx.sframeChan.query('Q_OO_OPENCHANNEL', channel, function (err, obj) {
|
ctx.sframeChan.query('Q_OO_OPENCHANNEL', {
|
||||||
|
channel: channel,
|
||||||
|
lastCp: data.lastCp
|
||||||
|
}, function (err, obj) {
|
||||||
if (err || (obj && obj.error)) { console.error(err || (obj && obj.error)); }
|
if (err || (obj && obj.error)) { console.error(err || (obj && obj.error)); }
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -40,6 +40,8 @@ define([
|
|||||||
obj.ooType = window.location.pathname.replace(/^\//, '').replace(/\/$/, '');
|
obj.ooType = window.location.pathname.replace(/^\//, '').replace(/\/$/, '');
|
||||||
};
|
};
|
||||||
var addRpc = function (sframeChan, Cryptpad, Utils) {
|
var addRpc = function (sframeChan, Cryptpad, Utils) {
|
||||||
|
var crypto = Utils.Crypto.createEncryptor(Utils.secret.keys);
|
||||||
|
|
||||||
sframeChan.on('Q_OO_SAVE', function (data, cb) {
|
sframeChan.on('Q_OO_SAVE', function (data, cb) {
|
||||||
var chanId = Utils.Hash.hrefToHexChannelId(data.url);
|
var chanId = Utils.Hash.hrefToHexChannelId(data.url);
|
||||||
Cryptpad.getPadAttribute('lastVersion', function (err, data) {
|
Cryptpad.getPadAttribute('lastVersion', function (err, data) {
|
||||||
@ -57,16 +59,26 @@ define([
|
|||||||
Cryptpad.onlyoffice.execCommand({
|
Cryptpad.onlyoffice.execCommand({
|
||||||
cmd: 'OPEN_CHANNEL',
|
cmd: 'OPEN_CHANNEL',
|
||||||
data: {
|
data: {
|
||||||
channel: data,
|
// XXX add owners?
|
||||||
secret: secret
|
// owners: something...
|
||||||
|
channel: data.channel,
|
||||||
|
lastCp: data.lastCp,
|
||||||
|
padChan: Utils.secret.channel,
|
||||||
|
validateKey: Utils.secret.keys.validateKey
|
||||||
}
|
}
|
||||||
}, cb);
|
}, cb);
|
||||||
});
|
});
|
||||||
sframeChan.on('Q_OO_COMMAND', function (data, cb) {
|
sframeChan.on('Q_OO_COMMAND', function (obj, cb) {
|
||||||
Cryptpad.onlyoffice.execCommand(data, cb);
|
if (obj.cmd === 'SEND_MESSAGE' && !obj.data.isCp) {
|
||||||
|
obj.data.msg = crypto.encrypt(obj.data.msg);
|
||||||
|
}
|
||||||
|
Cryptpad.onlyoffice.execCommand(obj, cb);
|
||||||
});
|
});
|
||||||
Cryptpad.onlyoffice.onEvent.reg(function (data) {
|
Cryptpad.onlyoffice.onEvent.reg(function (obj) {
|
||||||
sframeChan.event('EV_OO_EVENT', data);
|
if (obj.ev === 'MESSAGE') {
|
||||||
|
obj.data = crypto.decrypt(obj.data, Utils.secret.keys.validateKeys);
|
||||||
|
}
|
||||||
|
sframeChan.event('EV_OO_EVENT', obj);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
SFCommonO.start({
|
SFCommonO.start({
|
||||||
|
|||||||
@ -1,28 +1,14 @@
|
|||||||
define([
|
define([
|
||||||
'/common/common-util.js',
|
'/common/common-util.js',
|
||||||
'/common/common-constants.js',
|
], function (Util) {
|
||||||
'/customize/messages.js',
|
|
||||||
'/bower_components/chainpad-crypto/crypto.js',
|
|
||||||
], function (Util, Constants, Messages, Crypto) {
|
|
||||||
var OO = {};
|
var OO = {};
|
||||||
|
|
||||||
var convertToUint8 = function (obj) {
|
var getHistory = function (ctx, data, clientId, cb) {
|
||||||
var l = Object.keys(obj).length;
|
|
||||||
var u = new Uint8Array(l);
|
|
||||||
for (var i = 0; i<l; i++) {
|
|
||||||
u[i] = obj[i];
|
|
||||||
}
|
|
||||||
return u;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var openChannel = function (ctx, obj, client, cb) {
|
var openChannel = function (ctx, obj, client, cb) {
|
||||||
var channel = obj.channel;
|
var channel = obj.channel;
|
||||||
var secret = obj.secret;
|
var padChan = obj.padChan;
|
||||||
if (secret.keys.cryptKey) {
|
|
||||||
secret.keys.cryptKey = convertToUint8(secret.keys.cryptKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
var padChan = secret.channel;
|
|
||||||
var network = ctx.store.network;
|
var network = ctx.store.network;
|
||||||
var first = true;
|
var first = true;
|
||||||
|
|
||||||
@ -40,11 +26,10 @@ define([
|
|||||||
if (chan) {
|
if (chan) {
|
||||||
// This channel is already open in another tab
|
// This channel is already open in another tab
|
||||||
|
|
||||||
// ==> Set the ID to our client object
|
// ==> Use our netflux ID to create our client ID
|
||||||
if (!c.id) { c.id = chan.wc.myID + '-' + client; }
|
if (!c.id) { c.id = chan.wc.myID + '-' + client; }
|
||||||
|
|
||||||
// ==> Send the join message to the other members of the channel
|
/// XXX send chan.history to client
|
||||||
// XXX bcast a "join" message to the channel?
|
|
||||||
|
|
||||||
// ==> And push the new tab to the list
|
// ==> And push the new tab to the list
|
||||||
chan.clients.push(client);
|
chan.clients.push(client);
|
||||||
@ -55,11 +40,14 @@ define([
|
|||||||
|
|
||||||
ctx.channels[channel] = ctx.channels[channel] || {};
|
ctx.channels[channel] = ctx.channels[channel] || {};
|
||||||
|
|
||||||
var chan = ctx.channels[channel];
|
chan = ctx.channels[channel];
|
||||||
|
|
||||||
|
// Create our client ID using the netflux ID
|
||||||
if (!c.id) { c.id = wc.myID + '-' + client; }
|
if (!c.id) { c.id = wc.myID + '-' + client; }
|
||||||
|
|
||||||
|
// If this is a reconnect, we have a new netflux ID so we're going to fix
|
||||||
|
// all our client IDs.
|
||||||
if (chan.clients) {
|
if (chan.clients) {
|
||||||
// If 2 tabs from the same worker have been opened at the same time,
|
|
||||||
// we have to fix both of them
|
|
||||||
chan.clients.forEach(function (cl) {
|
chan.clients.forEach(function (cl) {
|
||||||
if (ctx.clients[cl] && !ctx.clients[cl].id) {
|
if (ctx.clients[cl] && !ctx.clients[cl].id) {
|
||||||
ctx.clients[cl].id = wc.myID + '-' + cl;
|
ctx.clients[cl].id = wc.myID + '-' + cl;
|
||||||
@ -67,9 +55,6 @@ define([
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!chan.encryptor) { chan.encryptor = Crypto.createEncryptor(secret.keys); }
|
|
||||||
|
|
||||||
wc.on('join', function () {
|
wc.on('join', function () {
|
||||||
// XXX
|
// XXX
|
||||||
});
|
});
|
||||||
@ -77,12 +62,7 @@ define([
|
|||||||
// XXX
|
// XXX
|
||||||
});
|
});
|
||||||
wc.on('message', function (cryptMsg) {
|
wc.on('message', function (cryptMsg) {
|
||||||
var msg = chan.encryptor.decrypt(cryptMsg, secret.keys && secret.keys.validateKey);
|
ctx.emit('MESSAGE', cryptMsg, chan.clients);
|
||||||
var parsed;
|
|
||||||
try {
|
|
||||||
parsed = JSON.parse(msg);
|
|
||||||
// XXX
|
|
||||||
} catch (e) { console.error(e); }
|
|
||||||
});
|
});
|
||||||
|
|
||||||
chan.wc = wc;
|
chan.wc = wc;
|
||||||
@ -96,24 +76,94 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!first) { return; }
|
if (first) {
|
||||||
chan.clients = [client];
|
chan.clients = [client];
|
||||||
first = false;
|
chan.lastCp = obj.lastCp;
|
||||||
cb();
|
first = false;
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
var hk = network.historyKeeper;
|
||||||
|
var cfg = {
|
||||||
|
validateKey: obj.validateKey,
|
||||||
|
lastKnownHash: chan.lastKnownHash,
|
||||||
|
owners: obj.owners,
|
||||||
|
};
|
||||||
|
var msg = ['GET_HISTORY', wc.id, cfg];
|
||||||
|
// Add the validateKey if we are the channel creator and we have a validateKey
|
||||||
|
if (hk) {
|
||||||
|
network.sendto(hk, JSON.stringify(msg)).then(function () {
|
||||||
|
}, function (err) {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
network.on('message', function (msg, sender) {
|
||||||
|
var hk = network.historyKeeper;
|
||||||
|
if (sender !== hk) { return; }
|
||||||
|
|
||||||
|
// Parse the message
|
||||||
|
var parsed;
|
||||||
|
try {
|
||||||
|
parsed = JSON.parse(msg);
|
||||||
|
} catch (e) {}
|
||||||
|
if (!parsed) { return; }
|
||||||
|
|
||||||
|
|
||||||
|
// Keep only metadata messages for the current channel
|
||||||
|
if (parsed.channel && parsed.channel !== channel) { return; }
|
||||||
|
// Ignore the metadata message
|
||||||
|
if (parsed.validateKey && parsed.channel) { return; }
|
||||||
|
// End of history: emit READY
|
||||||
|
if (parsed.state && parsed.state === 1 && parsed.channel) {
|
||||||
|
ctx.emit('READY', '');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (parsed.error && parsed.channel) { return; }
|
||||||
|
|
||||||
|
var msg = parsed[4];
|
||||||
|
|
||||||
|
// Keep only the history for our channel
|
||||||
|
if (msg[3] !== channel) { return; }
|
||||||
|
|
||||||
|
if (chan.lastCp) {
|
||||||
|
if (chan.lastCp === msg) {
|
||||||
|
delete chan.lastCp;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isCp = /^cp\|/.test(msg);
|
||||||
|
if (isCp) { return; }
|
||||||
|
|
||||||
|
chan.lastKnownHash = msg.slice(0,64);
|
||||||
|
ctx.emit('MESSAGE', msg, chan.clients);
|
||||||
|
});
|
||||||
|
|
||||||
network.join(channel).then(onOpen, function (err) {
|
network.join(channel).then(onOpen, function (err) {
|
||||||
return void cb({error: err});
|
return void cb({error: err});
|
||||||
});
|
});
|
||||||
|
|
||||||
network.on('reconnect', function () {
|
network.on('reconnect', function () {
|
||||||
if (!ctx.channels[channel]) { console.log("cant reconnect", channel); return; }
|
if (!ctx.channels[channel]) { return; }
|
||||||
network.join(channel).then(onOpen, function (err) {
|
network.join(channel).then(onOpen, function (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var sendMessage = function (ctx, data, clientId, cb) {
|
||||||
|
var c = ctx.clients[clientId];
|
||||||
|
if (!c) { return void cb({ error: 'NOT_IN_CHANNEL' }); }
|
||||||
|
var chan = ctx.channels[c.channel];
|
||||||
|
if (!chan) { return void cb({ error: 'INVALID_CHANNEL' }); }
|
||||||
|
if (data.isCp) {
|
||||||
|
return void chan.sendMsg(data.isCp, cb);
|
||||||
|
}
|
||||||
|
chan.sendMsg(data.msg, cb);
|
||||||
|
};
|
||||||
|
|
||||||
var leaveChannel = function (ctx, padChan) {
|
var leaveChannel = function (ctx, padChan) {
|
||||||
// Leave channel and prevent reconnect when we leave a pad
|
// Leave channel and prevent reconnect when we leave a pad
|
||||||
@ -143,19 +193,6 @@ define([
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the leave message to the channel we were in
|
|
||||||
if (ctx.clients[clientId]) {
|
|
||||||
var leaveMsg = {
|
|
||||||
leave: true,
|
|
||||||
id: ctx.clients[clientId].id
|
|
||||||
};
|
|
||||||
chan = ctx.channels[ctx.clients[clientId].channel];
|
|
||||||
if (chan) {
|
|
||||||
chan.sendMsg(JSON.stringify(leaveMsg));
|
|
||||||
ctx.emit('MESSAGE', leaveMsg, chan.clients);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete ctx.clients[clientId];
|
delete ctx.clients[clientId];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -179,6 +216,9 @@ define([
|
|||||||
oo.execCommand = function (clientId, obj, cb) {
|
oo.execCommand = function (clientId, obj, cb) {
|
||||||
var cmd = obj.cmd;
|
var cmd = obj.cmd;
|
||||||
var data = obj.data;
|
var data = obj.data;
|
||||||
|
if (cmd === 'SEND_MESSAGE') {
|
||||||
|
return void sendMessage(ctx, data, clientId, cb);
|
||||||
|
}
|
||||||
if (cmd === 'OPEN_CHANNEL') {
|
if (cmd === 'OPEN_CHANNEL') {
|
||||||
return void openChannel(ctx, data, clientId, cb);
|
return void openChannel(ctx, data, clientId, cb);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,7 +53,7 @@ define([
|
|||||||
_Constants, _Feedback, _LocalStore, _AppConfig, _Test) {
|
_Constants, _Feedback, _LocalStore, _AppConfig, _Test) {
|
||||||
CpNfOuter = _CpNfOuter;
|
CpNfOuter = _CpNfOuter;
|
||||||
Cryptpad = _Cryptpad;
|
Cryptpad = _Cryptpad;
|
||||||
Crypto = _Crypto;
|
Crypto = Utils.Crypto = _Crypto;
|
||||||
Cryptget = _Cryptget;
|
Cryptget = _Cryptget;
|
||||||
SFrameChannel = _SFrameChannel;
|
SFrameChannel = _SFrameChannel;
|
||||||
FilePicker = _FilePicker;
|
FilePicker = _FilePicker;
|
||||||
@ -156,7 +156,7 @@ define([
|
|||||||
var w = waitFor();
|
var w = waitFor();
|
||||||
// No password for drive, profile and todo
|
// No password for drive, profile and todo
|
||||||
cfg.getSecrets(Cryptpad, Utils, waitFor(function (err, s) {
|
cfg.getSecrets(Cryptpad, Utils, waitFor(function (err, s) {
|
||||||
secret = s;
|
secret = Utils.secret = s;
|
||||||
Cryptpad.getShareHashes(secret, function (err, h) {
|
Cryptpad.getShareHashes(secret, function (err, h) {
|
||||||
hashes = h;
|
hashes = h;
|
||||||
w();
|
w();
|
||||||
@ -165,7 +165,7 @@ define([
|
|||||||
} else {
|
} else {
|
||||||
var parsed = Utils.Hash.parsePadUrl(window.location.href);
|
var parsed = Utils.Hash.parsePadUrl(window.location.href);
|
||||||
var todo = function () {
|
var todo = function () {
|
||||||
secret = Utils.Hash.getSecrets(parsed.type, void 0, password);
|
secret = Utils.secret = Utils.Hash.getSecrets(parsed.type, void 0, password);
|
||||||
Cryptpad.getShareHashes(secret, waitFor(function (err, h) { hashes = h; }));
|
Cryptpad.getShareHashes(secret, waitFor(function (err, h) { hashes = h; }));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -951,7 +951,7 @@ define([
|
|||||||
// Create a new hash
|
// Create a new hash
|
||||||
password = data.password;
|
password = data.password;
|
||||||
var newHash = Utils.Hash.createRandomHash(parsed.type, password);
|
var newHash = Utils.Hash.createRandomHash(parsed.type, password);
|
||||||
secret = Utils.Hash.getSecrets(parsed.type, newHash, password);
|
secret = Utils.secret = Utils.Hash.getSecrets(parsed.type, newHash, password);
|
||||||
|
|
||||||
// Update the hash in the address bar
|
// Update the hash in the address bar
|
||||||
var ohc = window.onhashchange;
|
var ohc = window.onhashchange;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user