diff --git a/lib/hk-util.js b/lib/hk-util.js
index 0c7985742..0bb96a52b 100644
--- a/lib/hk-util.js
+++ b/lib/hk-util.js
@@ -407,19 +407,9 @@ const getHistoryOffset = (Env, channelName, lastKnownHash, _cb) => {
// check if the "hash" the client is requesting exists in the index
const lkh = index.offsetByHash[lastKnownHash];
- // we evict old hashes from the index as new checkpoints are discovered.
- // if someone connects and asks for a hash that is no longer relevant,
- // we tell them it's an invalid request. This is because of the semantics of "GET_HISTORY"
- // which is only ever used when connecting or reconnecting in typical uses of history...
- // this assumption should hold for uses by chainpad, but perhaps not for other uses cases.
- // EXCEPT: other cases don't use checkpoints!
- // clients that are told that their request is invalid should just make another request
- // without specifying the hash, and just trust the server to give them the relevant data.
- // QUESTION: does this mean mailboxes are causing the server to store too much stuff in memory?
- if (lastKnownHash && typeof(lkh) !== "number") {
- waitFor.abort();
- return void cb(new Error('EUNKNOWN'));
- }
+
+ // fall through to the next block if the offset of the hash in question is not in memory
+ if (lastKnownHash && typeof(lkh) !== "number") { return; }
// Since last 2 checkpoints
if (!lastKnownHash) {
@@ -441,13 +431,13 @@ const getHistoryOffset = (Env, channelName, lastKnownHash, _cb) => {
offset = lkh;
}));
}).nThen((w) => {
- // if offset is less than zero then presumably the channel has no messages
- // returning falls through to the next block and therefore returns -1
+ // skip past this block if the offset is anything other than -1
+ // this basically makes these first two nThen blocks behave like if-else
if (offset !== -1) { return; }
- // do a lookup from the index
- // FIXME maybe we don't need this anymore?
- // otherwise we have a non-negative offset and we can start to read from there
+ // either the message exists in history but is not in the cached index
+ // or it does not exist at all. In either case 'getHashOffset' is expected
+ // to return a number: -1 if not present, positive interger otherwise
Env.getHashOffset(channelName, lastKnownHash, w(function (err, _offset) {
if (err) {
w.abort();
@@ -482,7 +472,9 @@ const getHistoryAsync = (Env, channelName, lastKnownHash, beforeHash, handler, c
offset = os;
}));
}).nThen((waitFor) => {
- if (offset === -1) { return void cb(new Error("could not find offset")); }
+ if (offset === -1) {
+ return void cb(new Error('EUNKNOWN'));
+ }
const start = (beforeHash) ? 0 : offset;
store.readMessagesBin(channelName, start, (msgObj, readMore, abort) => {
if (beforeHash && msgObj.offset >= offset) { return void abort(); }
diff --git a/lib/storage/file.js b/lib/storage/file.js
index 994680218..255f74016 100644
--- a/lib/storage/file.js
+++ b/lib/storage/file.js
@@ -1044,7 +1044,7 @@ module.exports.create = function (conf, _cb) {
getWeakLock: function (channelName, _cb) {
var cb = Util.once(Util.mkAsync(_cb));
- if (!isValidChannelId(channelName)) { return void cb(new Error('EINVAL')); }
+ //if (!isValidChannelId(channelName)) { return void cb(new Error('EINVAL')); } // XXX
schedule.unordered(channelName, cb);
},
diff --git a/lib/workers/db-worker.js b/lib/workers/db-worker.js
index 65a381479..0b9de4f53 100644
--- a/lib/workers/db-worker.js
+++ b/lib/workers/db-worker.js
@@ -153,7 +153,8 @@ const computeIndex = function (data, cb) {
messageBuf = [];
}
} else if (messageBuf.length > 100 && cpIndex.length === 0) {
- messageBuf = messageBuf.slice(0, 50);
+ // take the last 50 messages
+ messageBuf = messageBuf.slice(-50);
}
// if it's not metadata or a checkpoint then it should be a regular message
// store it in the buffer
@@ -352,7 +353,8 @@ const getMultipleFileSize = function (data, cb) {
const getHashOffset = function (data, cb) {
const channelName = data.channel;
- const lastKnownHash = data.lastKnownHash;
+ const lastKnownHash = data.hash;
+ if (typeof(lastKnownHash) !== 'string') { return void cb("INVALID_HASH"); }
var offset = -1;
store.readMessagesBin(channelName, 0, (msgObj, readMore, abort) => {
diff --git a/scripts/tests/test-mailbox.js b/scripts/tests/test-mailbox.js
index b0418c5db..d152cf0f2 100644
--- a/scripts/tests/test-mailbox.js
+++ b/scripts/tests/test-mailbox.js
@@ -11,8 +11,14 @@ var Hash = require("../../www/common/common-hash");
var CpNetflux = require("../../www/bower_components/chainpad-netflux");
var Util = require("../../lib/common-util");
-var createMailbox = function (config, cb) {
+// you need more than 100 messages in the history, and you need a lastKnownHash between "50" and "length - 50"
+
+var createMailbox = function (config, _cb) {
+ var cb = Util.once(Util.mkAsync(_cb));
+
var webchannel;
+ var user = config.user;
+ user.messages = [];
CpNetflux.start({
network: config.network,
@@ -21,11 +27,16 @@ var createMailbox = function (config, cb) {
owners: [ config.edPublic ],
noChainPad: true,
+
+ lastKnownHash: config.lastKnownHash,
+ onChannelError: function (err) {
+ cb(err);
+ },
onConnect: function (wc /*, sendMessage */) {
webchannel = wc;
},
- onMessage: function (/* msg, user, vKey, isCp, hash, author */) {
-
+ onMessage: function (msg /*, user, vKey, isCp, hash, author */) {
+ user.messages.push(msg);
},
onReady: function () {
cb(void 0, webchannel);
@@ -37,6 +48,8 @@ process.on('unhandledRejection', function (err) {
console.error(err);
});
+var state = {};
+
var makeCurveKeys = function () {
var pair = Nacl.box.keyPair();
return {
@@ -53,6 +66,10 @@ var makeEdKeys = function () {
};
};
+var edKeys = makeEdKeys();
+var curveKeys = makeCurveKeys();
+var mailboxChannel = Hash.createChannelId();
+
var createUser = function (config, cb) {
// config should contain keys for a team rpc (ed)
// teamEdKeys
@@ -75,11 +92,11 @@ var createUser = function (config, cb) {
// make all the parameters you'll need
var network = user.network = user.config.network;
- user.edKeys = makeEdKeys();
+ user.edKeys = edKeys;
+ user.curveKeys = curveKeys;
- user.curveKeys = makeCurveKeys();
user.mailbox = Mailbox.createEncryptor(user.curveKeys);
- user.mailboxChannel = Hash.createChannelId();
+ user.mailboxChannel = mailboxChannel;
// create an anon rpc for alice
Rpc.createAnonymous(network, w(function (err, rpc) {
@@ -109,6 +126,11 @@ var createUser = function (config, cb) {
}).nThen(function (w) {
// create and subscribe to your mailbox
createMailbox({
+ user: user,
+
+
+ lastKnownHash: config.lastKnownHash,
+
network: user.network,
channel: user.mailboxChannel,
crypto: user.mailbox,
@@ -116,8 +138,9 @@ var createUser = function (config, cb) {
}, w(function (err /*, wc*/) {
if (err) {
w.abort();
- console.error("Mailbox creation error");
- process.exit(1);
+ //console.error("Mailbox creation error");
+ cb(err);
+ //process.exit(1);
}
//wc.leave();
}));
@@ -135,14 +158,10 @@ var createUser = function (config, cb) {
var alice;
-var sharedConfig = {
- teamEdKeys: makeEdKeys(),
- teamCurveKeys: makeCurveKeys(),
- rosterSeed: Crypto.Team.createSeed(),
-};
-
nThen(function (w) {
- createUser(sharedConfig, w(function (err, _alice) {
+ createUser({
+ //sharedConfig
+ }, w(function (err, _alice) {
if (err) {
w.abort();
return void console.log(err);
@@ -163,13 +182,18 @@ nThen(function (w) {
var i = 0;
var next = w();
+ state.hashes = [];
+
var send = function () {
- if (i++ >= 300) { return next(); }
+ if (i++ >= 160) { return next(); }
var msg = alice.mailbox.encrypt(JSON.stringify({
pewpew: 'bangbang',
}), alice.curveKeys.curvePublic);
+ var hash = msg.slice(0, 64);
+ state.hashes.push(hash);
+
alice.anonRpc.send('WRITE_PRIVATE_MESSAGE', [
alice.mailboxChannel,
msg
@@ -177,10 +201,33 @@ nThen(function (w) {
], w(function (err) {
if (err) { throw new Error(err); }
console.log('message %s written successfully', i);
- setTimeout(send, 250);
+ setTimeout(send, 15);
}));
};
send();
+}).nThen(function (w) {
+ console.log("Connecting with second user");
+ createUser({
+ lastKnownHash: state.hashes[55],
+ }, w(function (err, _alice) {
+ if (err) {
+ w.abort();
+ console.log("lastKnownHash: ", state.hashes[55]);
+ console.log(err);
+ process.exit(1);
+ //return void console.log(err);
+ }
+ var user = state.alice2 = _alice;
+
+ if (user.messages.length === 105) {
+ process.exit(0);
+ }
+ //console.log(user.messages, user.messages.length);
+ process.exit(1);
+ }));
+}).nThen(function () {
+
+
}).nThen(function () {
alice.cleanup();
//bob.cleanup();
diff --git a/server.js b/server.js
index 9b82d7c3c..2e6869b9f 100644
--- a/server.js
+++ b/server.js
@@ -43,6 +43,7 @@ if (process.env.PACKAGE) {
}
config.httpUnsafeOrigin = config.httpUnsafeOrigin.trim();
+ config.httpSafeOrigin = config.httpSafeOrigin.trim().replace(/\/$/, '');
// fall back to listening on a local address
// if httpAddress is not a string
@@ -129,7 +130,7 @@ var setHeaders = (function () {
/^\/common\/onlyoffice\/.*\/index\.html.*/,
/^\/(sheet|ooslide|oodoc)\/inner\.html.*/,
].some((regex) => {
- return regex.test(req.url)
+ return regex.test(req.url);
}) ? padHeaders : headers;
for (let header in h) { res.setHeader(header, h[header]); }
};
diff --git a/www/common/diffMarked.js b/www/common/diffMarked.js
index c385a606c..5a8a594a1 100644
--- a/www/common/diffMarked.js
+++ b/www/common/diffMarked.js
@@ -288,6 +288,23 @@ define([
return patch;
};
+ var removeMermaidClickables = function ($el) {
+ // find all links in the tree and do the following for each one
+ $el.find('a').each(function (index, a) {
+ var parent = a.parentElement;
+ if (!parent) { return; }
+ // iterate over the links' children and transform them into preceding children
+ // to preserve their visible ordering
+ slice(a.children).forEach(function (child) {
+ parent.insertBefore(child, a);
+ });
+ // remove the link once it has been emptied
+ $(a).remove();
+ });
+ // finally, find all 'clickable' items and remove the class
+ $el.find('.clickable').removeClass('clickable');
+ };
+
DiffMd.apply = function (newHtml, $content, common) {
var contextMenu = common.importMediaTagMenu();
var id = $content.attr('id');
@@ -413,7 +430,7 @@ define([
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type === 'childList') {
- var list_values = [].slice.call(mutation.target.children)
+ var list_values = slice(mutation.target.children)
.map(function (el) { return el.outerHTML; })
.join('');
mediaMap[mutation.target.getAttribute('src')] = list_values;
@@ -469,7 +486,13 @@ define([
// check if you had cached a pre-rendered instance of the supplied source
if (typeof(cached) !== 'object') {
try {
- Mermaid.init(undefined, $(el));
+ var $el = $(el);
+ Mermaid.init(undefined, $el);
+ // clickable elements in mermaid don't work well with our sandboxing setup
+ // the function below strips clickable elements but still leaves behind some artifacts
+ // tippy tooltips might still be useful, so they're not removed. It would be
+ // preferable to just support links, but this covers up a rough edge in the meantime
+ removeMermaidClickables($el);
} catch (e) { console.error(e); }
return;
}
diff --git a/www/common/sframe-chainpad-netflux-inner.js b/www/common/sframe-chainpad-netflux-inner.js
index 7024bcfe3..b6f4c6aaf 100644
--- a/www/common/sframe-chainpad-netflux-inner.js
+++ b/www/common/sframe-chainpad-netflux-inner.js
@@ -112,11 +112,16 @@ define([
});
sframeChan.on('EV_RT_CONNECT', function (content) {
//content.members.forEach(userList.onJoin);
+ if (isReady && myID === content.myID) {
+ // We are connected and we are "reconnecting" ==> we probably had to rejoin
+ // the channel because of a server error (enoent), don't update the toolbar
+ return;
+ }
isReady = false;
if (myID) {
// it's a reconnect
myID = content.myID;
- chainpad.start();
+ //chainpad.start();
onConnectionChange({ state: true, myId: myID });
return;
}
diff --git a/www/common/sframe-chainpad-netflux-outer.js b/www/common/sframe-chainpad-netflux-outer.js
index 9e3b957fc..84b90f24e 100644
--- a/www/common/sframe-chainpad-netflux-outer.js
+++ b/www/common/sframe-chainpad-netflux-outer.js
@@ -45,7 +45,8 @@ define([], function () {
return decryptedMsg;
} catch (err) {
console.error(err);
- return msg;
+ console.warn(peer, msg);
+ return false;
}
};
@@ -81,6 +82,7 @@ define([], function () {
validateKey = msgObj.validateKey;
}
var message = msgIn(msgObj.user, msgObj.msg);
+ if (!message) { return; }
verbose(message);
diff --git a/www/common/translations/messages.fr.json b/www/common/translations/messages.fr.json
index c5c5b4649..17582944a 100644
--- a/www/common/translations/messages.fr.json
+++ b/www/common/translations/messages.fr.json
@@ -945,7 +945,7 @@
"creation_expiration": "Date d'expiration",
"creation_passwordValue": "Mot de passe",
"creation_propertiesTitle": "Disponibilité",
- "creation_appMenuName": "Mode avancé (Ctrl + E)",
+ "creation_appMenuName": "Nouveau pad (Ctrl + E)",
"creation_newPadModalDescription": "Cliquez sur un type de pad pour le créer. Vous pouvez aussi appuyer sur Tab pour sélectionner un type et appuyer sur Entrée pour valider.",
"creation_newPadModalDescriptionAdvanced": "Cochez la case si vous souhaitez voir l'écran de création de pads (pour les pads avec propriétaire ou à durée de vie). Vous pouvez appuyer sur Espace pour changer sa valeur.",
"creation_newPadModalAdvanced": "Afficher l'écran de création de pads",
diff --git a/www/common/translations/messages.it.json b/www/common/translations/messages.it.json
index 0bd465dbd..737d39f11 100644
--- a/www/common/translations/messages.it.json
+++ b/www/common/translations/messages.it.json
@@ -1306,7 +1306,7 @@
"team_cat_general": "Info",
"properties_passwordWarning": "La password è stata cambiata ma non siamo in grado di aggiornare il tuo CryptDrive con i nuovi dati. Devi rimuovere i vecchi pad manualmente.
Premi OK per ricaricare ed aggiornare i tuoi diritti di accesso.",
"share_embedCategory": "Incorporamento",
- "chrome68": "Sembra che tu stia usando il browser Chrome o Chromium versione 68. Contiene un bug che si manifesta nella pagina che diventa completamente bianca dopo alcuni secondi o smette di rispondere ai clic. Per risolvere il problema puoi passare ad un'altra tab e tornare a questa, o provare a scorrere la pagina. Questo problema sarà risolto nella prossima versione del tuo browser.",
+ "chrome68": "Sembra che tu stia usando il browser Chrome o Chromium versione 68. Contiene un bug che si manifesta nella pagina che diventa completamente bianca dopo alcuni secondi o smette di rispondere ai clic. Per risolvere il problema puoi passare ad un'altra scheda e tornare a questa, o provare a scorrere la pagina. Questo problema sarà risolto nella prossima versione del tuo browser.",
"crowdfunding_popup_text": "