From ed5d97f899e7b3b4bb94e36442b64e2a70c6f41b Mon Sep 17 00:00:00 2001 From: ansuz Date: Wed, 1 Apr 2020 11:48:16 -0400 Subject: [PATCH 01/12] WIP history-keeper fixes --- lib/hk-util.js | 17 +++++--- lib/workers/db-worker.js | 6 ++- scripts/tests/test-mailbox.js | 81 +++++++++++++++++++++++++++-------- 3 files changed, 79 insertions(+), 25 deletions(-) diff --git a/lib/hk-util.js b/lib/hk-util.js index c0da609ee..8a0d5fc86 100644 --- a/lib/hk-util.js +++ b/lib/hk-util.js @@ -395,7 +395,7 @@ const storeMessage = function (Env, channel, msg, isCp, optionalMessageHash) { * -1 if you didn't find it */ -const getHistoryOffset = (Env, channelName, lastKnownHash, _cb) => { +const getHistoryOffset = (Env, channelName, lastKnownHash, _cb) => { // XXX const cb = Util.once(Util.mkAsync(_cb)); // lastKnownhash === -1 means we want the complete history @@ -417,8 +417,9 @@ const getHistoryOffset = (Env, channelName, lastKnownHash, _cb) => { // 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('EINVAL')); + return; // XXX fall through to find the offset since it isn't cached + //waitFor.abort(); + //return void cb(new Error('EINVAL')); } // Since last 2 checkpoints @@ -474,7 +475,7 @@ const getHistoryAsync = (Env, channelName, lastKnownHash, beforeHash, handler, c let offset = -1; nThen((waitFor) => { - getHistoryOffset(Env, channelName, lastKnownHash, waitFor((err, os) => { + getHistoryOffset(Env, channelName, lastKnownHash, waitFor((err, os) => { // XXX if (err) { waitFor.abort(); return void cb(err); @@ -482,7 +483,11 @@ 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')); + console.log(lastKnownHash); + return void cb(new Error("could not find offset")); // XXX EUNKNOWN + } const start = (beforeHash) ? 0 : offset; store.readMessagesBin(channelName, start, (msgObj, readMore, abort) => { if (beforeHash && msgObj.offset >= offset) { return void abort(); } @@ -630,7 +635,7 @@ const handleGetHistory = function (Env, Server, seq, userId, parsed) { }, (err) => { if (err && err.code !== 'ENOENT') { if (err.message !== 'EINVAL') { Log.error("HK_GET_HISTORY", err); } - const parsedMsg = {error:err.message, channel: channelName, txid: txid}; + const parsedMsg = {error:err.message, channel: channelName, txid: txid}; // XXX Server.send(userId, [0, HISTORY_KEEPER_ID, 'MSG', userId, JSON.stringify(parsedMsg)]); return; } 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(); From 834c96a4fcfa232930d69a0699f10112e8034a57 Mon Sep 17 00:00:00 2001 From: ansuz Date: Wed, 1 Apr 2020 17:43:40 -0400 Subject: [PATCH 02/12] update comments and remove some notes --- lib/hk-util.js | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/lib/hk-util.js b/lib/hk-util.js index 8a0d5fc86..a6a843242 100644 --- a/lib/hk-util.js +++ b/lib/hk-util.js @@ -395,7 +395,7 @@ const storeMessage = function (Env, channel, msg, isCp, optionalMessageHash) { * -1 if you didn't find it */ -const getHistoryOffset = (Env, channelName, lastKnownHash, _cb) => { // XXX +const getHistoryOffset = (Env, channelName, lastKnownHash, _cb) => { const cb = Util.once(Util.mkAsync(_cb)); // lastKnownhash === -1 means we want the complete history @@ -407,20 +407,9 @@ const getHistoryOffset = (Env, channelName, lastKnownHash, _cb) => { // XXX // 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") { - return; // XXX fall through to find the offset since it isn't cached - //waitFor.abort(); - //return void cb(new Error('EINVAL')); - } + + // 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) { @@ -442,13 +431,13 @@ const getHistoryOffset = (Env, channelName, lastKnownHash, _cb) => { // XXX 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(); @@ -475,7 +464,7 @@ const getHistoryAsync = (Env, channelName, lastKnownHash, beforeHash, handler, c let offset = -1; nThen((waitFor) => { - getHistoryOffset(Env, channelName, lastKnownHash, waitFor((err, os) => { // XXX + getHistoryOffset(Env, channelName, lastKnownHash, waitFor((err, os) => { if (err) { waitFor.abort(); return void cb(err); @@ -485,8 +474,6 @@ const getHistoryAsync = (Env, channelName, lastKnownHash, beforeHash, handler, c }).nThen((waitFor) => { if (offset === -1) { return void cb(new Error('EUNKNOWN')); - console.log(lastKnownHash); - return void cb(new Error("could not find offset")); // XXX EUNKNOWN } const start = (beforeHash) ? 0 : offset; store.readMessagesBin(channelName, start, (msgObj, readMore, abort) => { @@ -635,7 +622,7 @@ const handleGetHistory = function (Env, Server, seq, userId, parsed) { }, (err) => { if (err && err.code !== 'ENOENT') { if (err.message !== 'EINVAL') { Log.error("HK_GET_HISTORY", err); } - const parsedMsg = {error:err.message, channel: channelName, txid: txid}; // XXX + const parsedMsg = {error:err.message, channel: channelName, txid: txid}; Server.send(userId, [0, HISTORY_KEEPER_ID, 'MSG', userId, JSON.stringify(parsedMsg)]); return; } From 1f3e47e1095f6087ccb4fc0517c07e1d214aec49 Mon Sep 17 00:00:00 2001 From: Weblate Date: Wed, 1 Apr 2020 11:41:10 +0200 Subject: [PATCH 03/12] Translated using Weblate (Italian) Currently translated at 100.0% (1246 of 1246 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/it/ --- www/common/translations/messages.it.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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": "

Abbiamo bisogno del tuo aiuto!

Per garantire che CryptPad sia attivamente sviluppato, valuta se aiutare il progetto sulla pagina OpenCollective, dove potrai vedere la nostra Roadmap e gli obiettivi di finanziamento.", "admin_updateLimitHint": "Forzare un aggiornamento dei limiti dello spazio utente può essere fatto in qualsiasi momento, ma è necessario solo in caso di errori", "admin_flushCacheTitle": "Svuota la cache HTTP", @@ -1316,7 +1316,7 @@ "fm_info_sharedFolderHistory": "questa è solo la cronologia delle tue cartelle condivise: {0}
Il tuo CryptDrive rimarrà in sola lettura durante la navigazione.", "share_description": "Scegli cosa vuoi condividere e prendi il link o invialo direttamente ai tuoi contatti CryptPad.", "admin_supportInitHelp": "Il tuo server non è ancora configurato per avere una mailbox di supporto. Se vuoi una mailbox di supporto per ricevere messaggi dai tuoi utenti, chiedi all'amministratore del server di avviare lo script posizionato in \"./scripts/generate-admin-keys.js\", quindi salvare la chiave pubblica nel file \"config.js\" ed inviarti la chiave privata.", - "admin_supportInitPrivate": "La tua installazione CryptPad è configurata per usare una mailbox di supporto ma il tuo account non ha la chiave privata corretta per accedervi. Usa la form che segue per aggiungere o aggiornare la chiave privata del tuo account.", + "admin_supportInitPrivate": "La tua installazione CryptPad è configurata per usare una mailbox di supporto ma il tuo account non ha la chiave privata corretta per accedervi. Usa il modulo che segue per aggiungere o aggiornare la chiave privata del tuo account.", "admin_supportInitHint": "Puoi configurare una mailbox di supporto per dare agli utenti del tuo CryptPad un modo per contattarti in maniera sicura se hanno problemi con i loro account.", "admin_supportListHint": "Questa è la lista dei ticket inviati dagli utenti alla mailbox di supporto. Tutti gli amministratori possono vedere i messaggi e le risposte. Un ticket chiuso non può essere riaperto. Puoi solo rimuovere (nascondere) i ticket chiusi, ma i ticket rimossi rimangono visibili agli altri amministratori.", "requestEdit_confirm": "{1} ha richiesto la possibilità di modificare il pad {0}. Vuoi fornirgli l'accesso?", From 572f81877fff2521d14061ec0a56829282313e73 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 2 Apr 2020 15:28:33 +0200 Subject: [PATCH 04/12] Fix reconnecting issues after EUNKNOWN and ENOENT --- www/common/sframe-chainpad-netflux-inner.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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; } From d12fad3420ca066f361eae1449e2037660446918 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 2 Apr 2020 16:16:40 +0200 Subject: [PATCH 05/12] Fix kanban edit modal not locked on disconnect --- www/kanban/inner.js | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/www/kanban/inner.js b/www/kanban/inner.js index 310219e75..e99b61767 100644 --- a/www/kanban/inner.js +++ b/www/kanban/inner.js @@ -135,8 +135,12 @@ define([ var PROPERTIES = ['title', 'body', 'tags', 'color']; var BOARD_PROPERTIES = ['title', 'color']; var createEditModal = function (framework, kanban) { + if (framework.isReadOnly()) { return; } + if (editModal) { return editModal; } + var dataObject = {}; var isBoard, id; + var offline = false; var update = Util.throttle(function () { kanban.setBoards(kanban.options.boards); @@ -147,7 +151,7 @@ define([ framework.localChange(); update(); }; - if (editModal) { return editModal; } + var conflicts, conflictContainer, titleInput, tagsDiv, colors, text; var content = h('div', [ conflictContainer = h('div#cp-kanban-edit-conflicts', [ @@ -167,7 +171,6 @@ define([ ]); var $tags = $(tagsDiv); - var $conflict = $(conflicts); var $cc = $(conflictContainer); var conflict = { @@ -282,6 +285,7 @@ define([ }); var commitTags = function () { + if (offline) { return; } setTimeout(function () { dataObject.tags = Util.deduplicateString(_field.getTokens().map(function (t) { return t.toLowerCase(); @@ -305,6 +309,7 @@ define([ var $color = $(h('span.cp-kanban-palette.fa')); $color.addClass('cp-kanban-palette-'+(color || 'nocolor')); $color.click(function () { + if (offline) { return; } if (color === selectedColor) { return; } selectedColor = color; $colors.find('.cp-kanban-palette').removeClass('fa-check'); @@ -363,6 +368,17 @@ define([ buttons: button }); modal.classList.add('cp-kanban-edit-modal'); + var $modal = $(modal); + + framework.onEditableChange(function (unlocked) { + editor.setOption('readOnly', !unlocked); + $title.prop('disabled', unlocked ? '' : 'disabled'); + $(_field.element).tokenfield(unlocked ? 'enable' : 'disable'); + + $modal.find('nav button.danger').prop('disabled', unlocked ? '' : 'disabled'); + offline = !unlocked; + }); + var setId = function (_isBoard, _id) { // Reset the mdoal with a new id @@ -386,7 +402,7 @@ define([ .show(); } // Also reset the buttons - $(modal).find('nav').after(UI.dialog.getButtons(button)).remove(); + $modal.find('nav').after(UI.dialog.getButtons(button)).remove(); }; onRemoteChange.reg(function () { @@ -975,6 +991,7 @@ define([ } kanban.options.readOnly = true; $container.addClass('cp-app-readonly'); + $container.find('.kanban-edit-item').remove(); }); var getCursor = function () { From 2daf7592995e5f2d216c9feeb20d5daab98bc426 Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 2 Apr 2020 15:39:55 -0400 Subject: [PATCH 06/12] remove clickable items from rendered mermaid --- www/common/diffMarked.js | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/www/common/diffMarked.js b/www/common/diffMarked.js index f8e006216..ccf2fc162 100644 --- a/www/common/diffMarked.js +++ b/www/common/diffMarked.js @@ -287,6 +287,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'); @@ -364,7 +381,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; @@ -400,7 +417,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; } From 3b05d24f107aee0cabd20344c7f7f36a4c24832c Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 2 Apr 2020 17:46:29 -0400 Subject: [PATCH 07/12] wip csp issue --- server.js | 13 ++++++++----- www/common/sframe-app-outer.js | 4 ++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/server.js b/server.js index 9b82d7c3c..7ae779d13 100644 --- a/server.js +++ b/server.js @@ -42,7 +42,7 @@ if (process.env.PACKAGE) { throw new Error("No 'httpUnsafeOrigin' provided"); } - config.httpUnsafeOrigin = config.httpUnsafeOrigin.trim(); + config.httpUnsafeOrigin = config.httpUnsafeOrigin.trim().replace(/\/$/, ''); // fall back to listening on a local address // if httpAddress is not a string @@ -125,12 +125,15 @@ var setHeaders = (function () { if (Object.keys(headers).length) { return function (req, res) { const h = [ - /^\/pad\/inner\.html.*/, + /^\/+pad\/inner\.html.*/, /^\/common\/onlyoffice\/.*\/index\.html.*/, - /^\/(sheet|ooslide|oodoc)\/inner\.html.*/, + /^\/+(sheet|ooslide|oodoc)\/in.*\.html.*/, ].some((regex) => { - return regex.test(req.url) - }) ? padHeaders : headers; + if (regex.test('' + req.url)) { + console.log('CSP MATCH: [%s] <= [%s]', regex, req.url); + return true; + } + }) ? padHeaders: headers; for (let header in h) { res.setHeader(header, h[header]); } }; } diff --git a/www/common/sframe-app-outer.js b/www/common/sframe-app-outer.js index d85266ca7..2d5948fd8 100644 --- a/www/common/sframe-app-outer.js +++ b/www/common/sframe-app-outer.js @@ -31,6 +31,10 @@ define([ ApiConfig.httpSafeOrigin + window.location.pathname + 'inner.html?' + requireConfig.urlArgs + '#' + encodeURIComponent(JSON.stringify(req))); + console.log(ApiConfig.httpSafeOrigin); + + console.error(document.getElementById('sbox-iframe').getAttribute('src')); + // This is a cheap trick to avoid loading sframe-channel in parallel with the // loading screen setup. var done = waitFor(); From adfd1eaaa2d6b1490ad155ee644d8d1a295e3736 Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 2 Apr 2020 22:57:57 -0400 Subject: [PATCH 08/12] avoid a silly typeError in the event of an error --- lib/storage/file.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); }, From 902e9624e87ec2292d44089e1cd4b6c9c96de184 Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 3 Apr 2020 11:19:35 +0200 Subject: [PATCH 09/12] Don't send encrypted messages to chainpad --- www/common/sframe-chainpad-netflux-outer.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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); From 7ccfe7a67355786a30c63123351942c3b025341f Mon Sep 17 00:00:00 2001 From: Weblate Date: Fri, 3 Apr 2020 16:35:47 +0200 Subject: [PATCH 10/12] Translated using Weblate (English) Currently translated at 100.0% (1246 of 1246 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/ --- www/common/translations/messages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/common/translations/messages.json b/www/common/translations/messages.json index 264f76ad6..50133d1a2 100644 --- a/www/common/translations/messages.json +++ b/www/common/translations/messages.json @@ -963,7 +963,7 @@ "creation_expiration": "Expiration time", "creation_passwordValue": "Password", "creation_propertiesTitle": "Availability", - "creation_appMenuName": "Advanced mode (Ctrl + E)", + "creation_appMenuName": "New pad (Ctrl + E)", "creation_newPadModalDescription": "Click on a pad type to create it. You can also press Tab to select the type and press Enter to confirm.", "creation_newPadModalDescriptionAdvanced": "You can check the box (or press Space to change its value) if you want to display the pad creation screen (for owned pads, expiring pads, etc.).", "creation_newPadModalAdvanced": "Display the pad creation screen", From 427389d1c7547c6b97d8d13539656d0957c49446 Mon Sep 17 00:00:00 2001 From: Weblate Date: Fri, 3 Apr 2020 16:35:47 +0200 Subject: [PATCH 11/12] Translated using Weblate (French) Currently translated at 100.0% (1246 of 1246 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/fr/ --- www/common/translations/messages.fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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", From 9fa93172cf445be62f60ea508d4839304333f8a4 Mon Sep 17 00:00:00 2001 From: ansuz Date: Fri, 3 Apr 2020 10:37:23 -0400 Subject: [PATCH 12/12] tolerate trailing slashes in httpSafeDomain --- server.js | 14 ++++++-------- www/common/sframe-app-outer.js | 4 ---- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/server.js b/server.js index 7ae779d13..2e6869b9f 100644 --- a/server.js +++ b/server.js @@ -42,7 +42,8 @@ if (process.env.PACKAGE) { throw new Error("No 'httpUnsafeOrigin' provided"); } - config.httpUnsafeOrigin = config.httpUnsafeOrigin.trim().replace(/\/$/, ''); + 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 @@ -125,15 +126,12 @@ var setHeaders = (function () { if (Object.keys(headers).length) { return function (req, res) { const h = [ - /^\/+pad\/inner\.html.*/, + /^\/pad\/inner\.html.*/, /^\/common\/onlyoffice\/.*\/index\.html.*/, - /^\/+(sheet|ooslide|oodoc)\/in.*\.html.*/, + /^\/(sheet|ooslide|oodoc)\/inner\.html.*/, ].some((regex) => { - if (regex.test('' + req.url)) { - console.log('CSP MATCH: [%s] <= [%s]', regex, req.url); - return true; - } - }) ? padHeaders: headers; + return regex.test(req.url); + }) ? padHeaders : headers; for (let header in h) { res.setHeader(header, h[header]); } }; } diff --git a/www/common/sframe-app-outer.js b/www/common/sframe-app-outer.js index 2d5948fd8..d85266ca7 100644 --- a/www/common/sframe-app-outer.js +++ b/www/common/sframe-app-outer.js @@ -31,10 +31,6 @@ define([ ApiConfig.httpSafeOrigin + window.location.pathname + 'inner.html?' + requireConfig.urlArgs + '#' + encodeURIComponent(JSON.stringify(req))); - console.log(ApiConfig.httpSafeOrigin); - - console.error(document.getElementById('sbox-iframe').getAttribute('src')); - // This is a cheap trick to avoid loading sframe-channel in parallel with the // loading screen setup. var done = waitFor();