From 6047a8640e86de711646a2ca98d33e0b0cabdfdc Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 14 Nov 2019 15:49:46 +0100 Subject: [PATCH 01/80] temp --- www/common/common-ui-elements.js | 6 +- www/common/cryptpad-common.js | 230 ++++++++++++++++++++++++++++++ www/common/outer/async-store.js | 65 ++++++++- www/common/outer/onlyoffice.js | 37 +++++ www/common/outer/store-rpc.js | 1 + www/common/sframe-common-outer.js | 5 + 6 files changed, 338 insertions(+), 6 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index df8836788..58cadb920 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -551,9 +551,10 @@ define([ $d.append(password); } - if (!data.noEditPassword && owned && parsed.type !== "sheet") { // FIXME SHEET fix password change for sheets + if (!data.noEditPassword && owned) { // FIXME SHEET fix password change for sheets var sframeChan = common.getSframeChannel(); + var isOO = parsed.type === 'sheet'; var isFile = parsed.hashData.type === 'file'; var isSharedFolder = parsed.type === 'drive'; @@ -586,7 +587,8 @@ define([ UI.confirm(changePwConfirm, function (yes) { if (!yes) { pLocked = false; return; } $(passwordOk).html('').append(h('span.fa.fa-spinner.fa-spin', {style: 'margin-left: 0'})); - var q = isFile ? 'Q_BLOB_PASSWORD_CHANGE' : 'Q_PAD_PASSWORD_CHANGE'; + var q = isFile ? 'Q_BLOB_PASSWORD_CHANGE' : + (isOO ? 'Q_OO_PASSWORD_CHANGE' : 'Q_PAD_PASSWORD_CHANGE'); // If this is a file password change, register to the upload events: // * if there is a pending upload, ask if we shoudl interrupt diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index 25a64404d..c960967fa 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -1155,6 +1155,233 @@ define([ }); }; + common.changeOOPassword = function (data, cb) { + var href = data.href; + var newPassword = data.password; + var teamId = data.teamId; + if (!href) { return void cb({ error: 'EINVAL_HREF' }); } + var parsed = Hash.parsePadUrl(href); + if (!parsed.hash) { return void cb({ error: 'EINVAL_HREF' }); } + if (parsed.type !== 'sheet') { return void cb({ error: 'EINVAL_TYPE' }); } + + var warning = false; + var newHash, newRoHref; + var oldChannel; + var oldSecret; + var oldMetadata; + var oldRtChannel; + var privateData; + var padData; + + var newSecret; + if (parsed.hashData.version >= 2) { + newSecret = Hash.getSecrets(parsed.type, parsed.hash, newPassword); + if (!(newSecret.keys && newSecret.keys.editKeyStr)) { + return void cb({error: 'EAUTH'}); + } + newHash = Hash.getEditHashFromKeys(newSecret); + } + var newHref = '/' + parsed.type + '/#' + newHash; + var newRtChannel = Hash.createChannelId(); + + var Crypt, Crypto; + var cryptgetVal; + var lastCp; + var optsPut = { + password: newPassword, + metadata: { + validateKey: newSecret.keys.validateKey + }, + }; + + Nthen(function (waitFor) { + common.getPadAttribute('', waitFor(function (err, _data) { + padData = _data; + }), href); + }).nThen(function (waitFor) { + oldSecret = Hash.getSecrets(parsed.type, parsed.hash, padData.password); + + require([ + '/common/cryptget.js', + '/bower_components/chainpad-crypto/crypto.js', + ], waitFor(function (_Crypt, _Crypto) { + Crypt = _Crypt; + Crypto = _Crypto; + })); + + common.getPadMetadata({channel: oldSecret.channel}, waitFor(function (metadata) { + oldMetadata = metadata; + })); + common.getMetadata(waitFor(function (err, data) { + if (err) { + waitFor.abort(); + return void cb({ error: err }); + } + privateData = data.priv; + })); + }).nThen(function (waitFor) { + // Check if we're allowed to change the password + var owners = oldMetadata.owners; + optsPut.metadata.owners = owners; + var edPublic = teamId ? (privateData.teams[teamId] || {}).edPublic : privateData.edPublic; + var isOwner = Array.isArray(owners) && edPublic && owners.indexOf(edPublic) !== -1; + if (!isOwner) { + // We're not an owner, we shouldn't be able to change the password! + waitFor.abort(); + return void cb({ error: 'EPERM' }); + } + + var mailbox = oldMetadata.mailbox; + if (mailbox) { + // Create the encryptors to be able to decrypt and re-encrypt the mailboxes + var oldCrypto = Crypto.createEncryptor(oldSecret.keys); + var newCrypto = Crypto.createEncryptor(newSecret.keys); + + var m; + if (typeof(mailbox) === "string") { + try { + m = newCrypto.encrypt(oldCrypto.decrypt(mailbox, true, true)); + } catch (e) {} + } else if (mailbox && typeof(mailbox) === "object") { + m = {}; + Object.keys(mailbox).forEach(function (ed) { + try { + m[ed] = newCrypto.encrypt(oldCrypto.decrypt(mailbox[ed], true, true)); + } catch (e) { + console.error(e); + } + }); + } + optsPut.metadata.mailbox = m; + } + + var expire = oldMetadata.expire; + if (expire) { + optsPut.metadata.expire = (expire - (+new Date())) / 1000; // Lifetime in seconds + } + + // Get last cp (cryptget) + Crypt.get(parsed.hash, waitFor(function (err, val) { + if (err) { + waitFor.abort(); + return void cb({ error: err }); + } + try { + cryptgetVal = JSON.parse(val); + if (!cryptgetVal.content) { + waitFor.abort(); + return void cb({ error: 'INVALID_CONTENT' }); + } + } catch (e) { + waitFor.abort(); + return void cb({ error: 'CANT_PARSE' }); + } + }), { + password: padData.password + }); + }).nThen(function (waitFor) { + // Re-encrypt rtchannel + oldRtChannel = Util.find(cryptgetVal, ['content', 'channel']); + var newCrypto = Crypto.createEncryptor(newSecret.keys); + var oldCrypto = Crypto.createEncryptor(oldSecret.keys); + var cps = Util.find(cryptgetVal, ['content', 'hashes']); + var lastCp = cps.length ? cps[cps.length - 1] : {}; + common.getHistory({ + channel: oldRtChannel, + lastKnownHash: lastCp.hash + }, waitFor(function (obj) { + if (obj && obj.error) { + waitFor.abort(); + return void cb(obj); + } + var msgs = obj; + newHistory = msgs.map(function (str) { + try { + var d = oldCrypto.decrypt(msg, true, true); + return newCrypto.encrypt(d); + } catch (e) { + waitFor.abort(); + return void cb({error: e}); + } + }); + // Update last knwon hash in cryptgetVal + if (lastCp) { lastCp.hash = msgs[0].slice(0, 64); } + common.onlyoffice.execCommand({ + cmd: 'REENCRYPT', + data: { + channel: newRtChannel, + msgs: newHistory, + metadata: optsPut.metadata + } + }, waitFor(function (obj) { + if (obj && obj.error) { + waitFor.abort(); + return void cb(obj); + } + })); + })); + }).nThen(function (waitFor) { + // The new rt channel is ready + // The blob uses its own encryption and doesn't need to be reencrypted + cryptgetVal.content.channel = newRtChannel; + Crypt.put(newHash, cryptgetVal, waitFor(function (err) { + if (err) { + waitFor.abort(); + return void cb({ error: err }); + } + }), optsPut); + }).nThen(function (waitFor) { + pad.leavePad({ + channel: oldSecret.channel + }, waitFor()); + pad.onDisconnectEvent.fire(true); + }).nThen(function (waitFor) { + // Set the new password to our pad data + common.setPadAttribute('password', newPassword, waitFor(function (err) { + if (err) { warning = true; } + }), href); + common.setPadAttribute('channel', newSecret.channel, waitFor(function (err) { + if (err) { warning = true; } + }), href); + common.setPadAttribute('rtChannel', newRtChannel, waitFor(function (err) { + if (err) { warning = true; } + }), href); + var viewHash = Hash.getViewHashFromKeys(newSecret); + newRoHref = '/' + parsed.type + '/#' + viewHash; + common.setPadAttribute('roHref', newRoHref, waitFor(function (err) { + if (err) { warning = true; } + }), href); + + if (parsed.hashData.password && newPassword) { return; } // same hash + common.setPadAttribute('href', newHref, waitFor(function (err) { + if (err) { warning = true; } + }), href); + }).nThen(function (waitFor) { + // delete the old pad + common.removeOwnedChannel({ + channel: oldSecret.channel, + teamId: teamId + }, waitFor(function (obj) { + if (obj && obj.error) { + waitFor.abort(); + return void cb(obj); + } + common.removeOwnedChannel({ + channel: oldRtChannel, + teamId: teamId + }, waitFor()); + })); + }).nThen(function () { + cb({ + warning: warning, + hash: newHash, + href: newHref, + roHref: newRoHref + }); + }); + }; + + common.changeUserPassword = function (Crypt, edPublic, data, cb) { if (!edPublic) { return void cb({ @@ -1350,6 +1577,9 @@ define([ common.getFullHistory = function (data, cb) { postMessage("GET_FULL_HISTORY", data, cb, {timeout: 180000}); }; + common.getHistory = function (data, cb) { + postMessage("GET_HISTORY", data, cb, {timeout: 180000}); + }; common.getHistoryRange = function (data, cb) { postMessage("GET_HISTORY_RANGE", data, cb); }; diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index 5900601e8..06d5b7d3a 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -1692,7 +1692,7 @@ define([ // GET_FULL_HISTORY from sframe-common-outer Store.getFullHistory = function (clientId, data, cb) { var network = store.network; - var hkn = network.historyKeeper; + var hk = network.historyKeeper; //var crypto = Crypto.createEncryptor(data.keys); // Get the history messages and send them to the iframe var parse = function (msg) { @@ -1709,6 +1709,7 @@ define([ var parsed = parse(msg); if (parsed[0] === 'FULL_HISTORY_END') { cb(msgs); + network.off('message', onMsg); completed = true; return; } @@ -1725,12 +1726,68 @@ define([ } }; network.on('message', onMsg); - network.sendto(hkn, JSON.stringify(['GET_FULL_HISTORY', data.channel, data.validateKey])); + network.sendto(hk, JSON.stringify(['GET_FULL_HISTORY', data.channel, data.validateKey])); + }; + + Store.getHistory = function (clientId, data, cb) { + var network = store.network; + var hk = network.historyKeeper; + + var parse = function (msg) { + try { + return JSON.parse(msg); + } catch (e) { + return null; + } + }; + + var msgs = []; + var completed = false; + var onMsg = function (msg, sender) { + if (completed) { return; } + if (sender !== hk) { return; } + var parsed = parse(msg); + + // Ignore the metadata message + if (parsed.validateKey && parsed.channel) { return; } + if (parsed.error && parsed.channel) { + if (parsed.channel === data.channel) { + network.off('message', onMsg); + completed = true; + cb({error: parsed.error}); + } + return; + } + + // End of history: cb + if (parsed.state === 1 && parsed.channel) { + if (parsed.channel !== data.channel) { return; } + cb(msgs); + network.off('message', onMsg); + completed = true; + return; + } + + msg = parsed[4]; + // Keep only the history for our channel + if (parsed[3] !== data.channel) { return; } + if (msg) { + msg = msg.replace(/cp\|(([A-Za-z0-9+\/=]+)\|)?/, ''); + msgs.push(msg); + } + }; + network.on('message', onMsg); + + var cfg = { + lastKnownHash: data.lastKnownHash + }; + var msg = ['GET_HISTORY', data.channel, cfg]; + network.sendto(hk, JSON.stringify(msg)); }; Store.getHistoryRange = function (clientId, data, cb) { var network = store.network; - var hkn = network.historyKeeper; + var hk = network.historyKeeper; var parse = function (msg) { try { return JSON.parse(msg); @@ -1778,7 +1835,7 @@ define([ }; network.on('message', onMsg); - network.sendto(hkn, JSON.stringify(['GET_HISTORY_RANGE', data.channel, { + network.sendto(hk, JSON.stringify(['GET_HISTORY_RANGE', data.channel, { from: data.lastKnownHash, cpCount: 2, txid: txid diff --git a/www/common/outer/onlyoffice.js b/www/common/outer/onlyoffice.js index 1dc010ba4..cb88596aa 100644 --- a/www/common/outer/onlyoffice.js +++ b/www/common/outer/onlyoffice.js @@ -200,6 +200,40 @@ define([ })); }; + var reencrypt = function (ctx, data, cId, cb) { + var channel = data.channel; + var network = ctx.store.network; + + var onOpen = function (wc) { + var hk = network.historyKeeper; + var cfg = { + metadata: data.metadata + }; + var msg = ['GET_HISTORY', wc.id, cfg]; + network.sendto(hk, JSON.stringify(msg)); + data.msgs.forEach(function (msg) { + wc.bcast(msg); + }); + wc.leave(); + cb(); + }; + + ctx.store.anon_rpc.send("IS_NEW_CHANNEL", channel, function (e, response) { + if (e) { return void cb({error: e}); } + if (response && response.length && typeof(response[0]) === 'boolean') { + var isNew = response[0]; + } else { + cb({error: 'INVALID_RESPONSE'}); + } + if (!isNew) { return void cb({error: 'EEXISTS'}); } + + // Channel is new: we can push our reencrypted history + network.join(channel).then(onOpen, function (err) { + return void cb({error: err}); + }); + }); + }; + var leaveChannel = function (ctx, padChan) { // Leave channel and prevent reconnect when we leave a pad Object.keys(ctx.channels).some(function (ooChan) { @@ -267,6 +301,9 @@ define([ if (cmd === 'OPEN_CHANNEL') { return void openChannel(ctx, data, clientId, cb); } + if (cmd === 'REENCRYPT') { + return void reencrypt(ctx, data, clientId, cb); + } }; return oo; diff --git a/www/common/outer/store-rpc.js b/www/common/outer/store-rpc.js index 2ef490876..12b5ff6e5 100644 --- a/www/common/outer/store-rpc.js +++ b/www/common/outer/store-rpc.js @@ -73,6 +73,7 @@ define([ JOIN_PAD: Store.joinPad, LEAVE_PAD: Store.leavePad, GET_FULL_HISTORY: Store.getFullHistory, + GET_HISTORY: Store.getHistory, GET_HISTORY_RANGE: Store.getHistoryRange, IS_NEW_CHANNEL: Store.isNewChannel, REQUEST_PAD_ACCESS: Store.requestPadAccess, diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index 224a9f73c..604aaa4e7 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -1007,6 +1007,11 @@ define([ }, cb); }); + sframeChan.on('Q_OO_PASSWORD_CHANGE', function (data, cb) { + data.href = data.href || window.location.href; + Cryptpad.changeOOPassword(data, cb); + }); + sframeChan.on('Q_PAD_PASSWORD_CHANGE', function (data, cb) { data.href = data.href || window.location.href; Cryptpad.changePadPassword(Cryptget, Crypto, data, cb); From f826e6aa3b46ebe5189fa96a25a219476951ffb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Mon, 25 Nov 2019 15:42:26 +0000 Subject: [PATCH 02/80] align filter input and buttons --- customize.dist/src/less2/include/usergrid.less | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/customize.dist/src/less2/include/usergrid.less b/customize.dist/src/less2/include/usergrid.less index 38202de86..9201f7415 100644 --- a/customize.dist/src/less2/include/usergrid.less +++ b/customize.dist/src/less2/include/usergrid.less @@ -23,6 +23,8 @@ flex: 1; min-width: 0; margin-bottom: 0 !important; + height: 38px; + margin: 6px 8px 6px 0px; &::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */ color: @cryptpad_color_grey; opacity: 1; /* Firefox */ @@ -33,6 +35,10 @@ margin: 0; display: none; } + button:last-child { + margin-right: 0px !important; + } + } .cp-usergrid-user { width: 70px; From 0dc0df8aa182f0b5ecf5c61143ea8096e130ff51 Mon Sep 17 00:00:00 2001 From: yflory Date: Mon, 25 Nov 2019 16:50:38 +0100 Subject: [PATCH 03/80] Remove XXX --- www/common/sframe-common-outer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index 604aaa4e7..dc710ef27 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -223,7 +223,6 @@ define([ if (wrongPasswordStored) { // Store the correct password nThen(function (w) { - // XXX noPasswordStored: return; ? Cryptpad.setPadAttribute('password', password, w(), parsed.getUrl()); Cryptpad.setPadAttribute('channel', secret.channel, w(), parsed.getUrl()); if (parsed.hashData.mode === 'edit') { From 8fc08538a1cefd22fcd920b026a0809bc438f2fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Tue, 26 Nov 2019 11:21:58 +0000 Subject: [PATCH 04/80] open share modal on ready --- www/common/toolbar3.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/common/toolbar3.js b/www/common/toolbar3.js index 224f7eeb6..2e503164c 100644 --- a/www/common/toolbar3.js +++ b/www/common/toolbar3.js @@ -533,7 +533,7 @@ MessengerUI, Messages) { Common.getSframeChannel().event('EV_SHARE_OPEN', { hidden: true }); - $shareBlock.click(function () { + $shareBlock.ready(function () { // XXX temporary open share modal on load var title = (config.title && config.title.getTitle && config.title.getTitle()) || (config.title && config.title.defaultName) || ""; From 66073804eed656ae65d69a59dc42ac66d73b8eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Tue, 26 Nov 2019 11:50:34 +0000 Subject: [PATCH 05/80] remove rounded corners on avatars --- customize.dist/src/less2/include/avatar.less | 1 - 1 file changed, 1 deletion(-) diff --git a/customize.dist/src/less2/include/avatar.less b/customize.dist/src/less2/include/avatar.less index 87b4a3a32..9ef46482a 100644 --- a/customize.dist/src/less2/include/avatar.less +++ b/customize.dist/src/less2/include/avatar.less @@ -30,7 +30,6 @@ justify-content: center; align-items: center; - border-radius: 4px; overflow: hidden; box-sizing: content-box; } From 851437a05bc3498a68012755c00cafba6d17d92b Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 26 Nov 2019 16:13:21 +0100 Subject: [PATCH 06/80] Fix onlyoffice password change --- www/common/cryptpad-common.js | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index c960967fa..3a96ad202 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -1285,27 +1285,35 @@ define([ var newCrypto = Crypto.createEncryptor(newSecret.keys); var oldCrypto = Crypto.createEncryptor(oldSecret.keys); var cps = Util.find(cryptgetVal, ['content', 'hashes']); - var lastCp = cps.length ? cps[cps.length - 1] : {}; + var l = Object.keys(cps).length; + var lastCp = l ? cps[l] : {}; + cryptgetVal.content.hashes = {}; common.getHistory({ channel: oldRtChannel, lastKnownHash: lastCp.hash }, waitFor(function (obj) { if (obj && obj.error) { waitFor.abort(); - return void cb(obj); + console.error(obj); + return void cb(obj.error); } var msgs = obj; newHistory = msgs.map(function (str) { try { - var d = oldCrypto.decrypt(msg, true, true); + var d = oldCrypto.decrypt(str, true, true); return newCrypto.encrypt(d); } catch (e) { + console.log(e); waitFor.abort(); return void cb({error: e}); } }); // Update last knwon hash in cryptgetVal - if (lastCp) { lastCp.hash = msgs[0].slice(0, 64); } + if (lastCp) { + lastCp.hash = newHistory[0].slice(0, 64); + lastCp.index = 50; + cryptgetVal.content.hashes[1] = lastCp; + } common.onlyoffice.execCommand({ cmd: 'REENCRYPT', data: { @@ -1316,7 +1324,8 @@ define([ }, waitFor(function (obj) { if (obj && obj.error) { waitFor.abort(); - return void cb(obj); + console.warn(obj); + return void cb(obj.error); } })); })); @@ -1324,7 +1333,7 @@ define([ // The new rt channel is ready // The blob uses its own encryption and doesn't need to be reencrypted cryptgetVal.content.channel = newRtChannel; - Crypt.put(newHash, cryptgetVal, waitFor(function (err) { + Crypt.put(newHash, JSON.stringify(cryptgetVal), waitFor(function (err) { if (err) { waitFor.abort(); return void cb({ error: err }); @@ -1364,7 +1373,8 @@ define([ }, waitFor(function (obj) { if (obj && obj.error) { waitFor.abort(); - return void cb(obj); + console.info(obj); + return void cb(obj.error); } common.removeOwnedChannel({ channel: oldRtChannel, From 50886b81da85d4a787f7921cb329bc492014c576 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 27 Nov 2019 11:31:43 +0100 Subject: [PATCH 07/80] Update orgmode regex in codemirror #466 --- www/code/orgmode.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/www/code/orgmode.js b/www/code/orgmode.js index 3377ebb15..f36ffe9d6 100644 --- a/www/code/orgmode.js +++ b/www/code/orgmode.js @@ -6,22 +6,24 @@ define([ CodeMirror.defineSimpleMode("orgmode", { start: [ - {regex: /^(^\*{1,6}\s)(TODO|DOING|WAITING|NEXT){0,1}(CANCELLED|CANCEL|DEFERRED|DONE|REJECTED|STOP|STOPPED){0,1}(.*)$/, token: ["header org-level-star", "header org-todo", "header org-done", "header"]}, + {regex: /(\*\s)(TODO|DOING|WAITING|NEXT|PENDING|)(CANCELLED|CANCELED|CANCEL|DONE|REJECTED|STOP|STOPPED|)(\s+\[\#[A-C]\]\s+|)(.*?)(?:(\s{10,}|))(\:[\S]+\:|)$/, sol: true, token: ["header level1 org-level-star","header level1 org-todo","header level1 org-done", "header level1 org-priority", "header level1", "header level1 void", "header level1 comment"]}, + {regex: /(\*{1,}\s)(TODO|DOING|WAITING|NEXT|PENDING|)(CANCELLED|CANCELED|CANCEL|DEFERRED|DONE|REJECTED|STOP|STOPPED|)(\s+\[\#[A-C]\]\s+|)(.*?)(?:(\s{10,}|))(\:[\S]+\:|)$/, sol: true, token: ["header org-level-star","header org-todo","header org-done", "header org-priority", "header", "header void", "header comment"]}, {regex: /(\+[^\+]+\+)/, token: ["strikethrough"]}, {regex: /(\*[^\*]+\*)/, token: ["strong"]}, {regex: /(\/[^\/]+\/)/, token: ["em"]}, {regex: /(\_[^\_]+\_)/, token: ["link"]}, {regex: /(\~[^\~]+\~)/, token: ["comment"]}, {regex: /(\=[^\=]+\=)/, token: ["comment"]}, - {regex: /\[\[[^\[\]]*\]\[[^\[\]]*\]\]/, token: "url"}, // links - {regex: /\[[xX\s]?\]/, token: 'qualifier'}, // checkbox - {regex: /\#\+BEGIN_[A-Z]*/, token: "comment", next: "env"}, // comments - {regex: /:?[A-Z_]+\:.*/, token: "comment"}, // property drawers - {regex: /(\#\+[A-Z_]*)(\:.*)/, token: ["keyword", 'qualifier']}, // environments - {regex: /(CLOCK\:|SHEDULED\:)(\s.+)/, token: ["comment", "keyword"]} + {regex: /\[\[[^\[\]]+\]\[[^\[\]]+\]\]/, token: "org-url"}, // links + {regex: /\[\[[^\[\]]+\]\]/, token: "org-image"}, // image + {regex: /\[[xX\s\-\_]\]/, token: 'qualifier org-toggle'}, // checkbox + {regex: /\#\+(?:(BEGIN|begin))_[a-zA-Z]*/, token: "comment", next: "env", sol: true}, // comments + {regex: /:?[A-Z_]+\:.*/, token: "comment", sol: true}, // property drawers + {regex: /(\#\+[a-zA-Z_]*)(\:.*)/, token: ["keyword", 'qualifier'], sol: true}, // environments + {regex: /(CLOCK\:|SHEDULED\:|DEADLINE\:)(\s.+)/, token: ["comment", "keyword"]} ], env: [ - {regex: /.*?\#\+END_[A-Z]*/, token: "comment", next: "start"}, + {regex: /\#\+(?:(END|end))_[a-zA-Z]*/, token: "comment", next: "start", sol: true}, {regex: /.*/, token: "comment"} ] }); From 3b6155ffce80a7c1901852ffda0d2c2d8ba2fc19 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 27 Nov 2019 13:14:33 +0100 Subject: [PATCH 08/80] Change properties icon in the drive --- www/common/drive-ui.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index 4c73a95a8..2f7da5886 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -79,7 +79,7 @@ define([ var faColor = 'cptools-palette'; var faTrash = 'fa-trash'; var faDelete = 'fa-eraser'; - var faProperties = 'fa-database'; + var faProperties = 'fa-info-circle'; var faTags = 'fa-hashtag'; var faUploadFiles = 'cptools-file-upload'; var faUploadFolder = 'cptools-folder-upload'; From 8a0e0621fb9d78a5b5d31375013e1e94f7f0a494 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 27 Nov 2019 17:26:21 +0100 Subject: [PATCH 09/80] Fast auth --- www/auth/main.js | 85 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 18 deletions(-) diff --git a/www/auth/main.js b/www/auth/main.js index 7930e96e0..afe029bc3 100644 --- a/www/auth/main.js +++ b/www/auth/main.js @@ -1,12 +1,16 @@ define([ 'jquery', - '/common/cryptpad-common.js', + '/common/cryptget.js', + '/common/pinpad.js', '/common/common-constants.js', '/common/outer/local-store.js', + '/common/outer/login-block.js', + '/common/outer/network-config.js', '/common/test.js', '/bower_components/nthen/index.js', + '/bower_components/netflux-websocket/netflux-client.js', '/bower_components/tweetnacl/nacl-fast.min.js' -], function ($, Cryptpad, Constants, LocalStore, Test, nThen) { +], function ($, Crypt, Pinpad, Constants, LocalStore, Block, NetConfig, Test, nThen, Netflux) { var Nacl = window.nacl; var signMsg = function (msg, privKey) { @@ -27,9 +31,55 @@ define([ sessionStorage[Constants.userHashKey]; var proxy; + var rpc; + var network; + var rpcError; + + var loadProxy = function (hash) { + nThen(function (waitFor) { + Crypt.get(hash, waitFor(function (err, val) { + if (err) { + waitFor.abort(); + console.error(err); + } + try { + var parsed = JSON.parse(val); + proxy = parsed; + } catch (e) { + console.log("Can't parse user drive", e); + } + }); + }).nThen(function (waitFor) { + var wsUrl = NetConfig.getWebsocketURL(); + var w = waitFor(); + Netflux.connect(wsUrl).then(function (network) { + network = _network; + w(); + }, function (err) { + rpcError = err; + console.error(err); + waitFor.abort(); + }); + }).nThen(function (waitFor) { + Pinpad.create(network, proxy, waitFor(function (e, call) { + if (e) { + rpcError = e; + return void waitFor.abort(); + } + rpc = call; + })); + }).nThen(function () { + console.log('IFRAME READY'); + Test(function () { + // This is only here to maybe trigger an error. + window.drive = proxy['drive']; + Test.passed(); + }); + }); + }; var whenReady = function (cb) { - if (proxy) { return void cb(); } + if (proxy && (rpc || rpcError)) { return void cb(); } console.log('CryptPad not ready...'); setTimeout(function () { whenReady(cb); @@ -50,6 +100,8 @@ define([ ret.error = "UNAUTH_DOMAIN"; } else if (!LocalStore.isLoggedIn()) { ret.error = "NOT_LOGGED_IN"; + } else if ('LOGIN') { + // XXX Display login modal.... } else { return void whenReady(function () { var sig = signMsg(data.data, proxy.edPrivate); @@ -63,7 +115,14 @@ define([ } } else if (data.cmd === 'UPDATE_LIMIT') { return void whenReady(function () { - Cryptpad.updatePinLimit(function (e, limit, plan, note) { + if (rpcError) { + // XXX + // Tell the user on accounts that there was an issue and they need to wait maximum 24h or contact an admin + } + rpc.updatePinLimits(function (e, limit, plan, note) { + if (e) { + // XXX same as above + } ret.res = [limit, plan, note]; srcWindow.postMessage(JSON.stringify(ret), domain); }); @@ -74,18 +133,8 @@ define([ srcWindow.postMessage(JSON.stringify(ret), domain); }); - nThen(function (waitFor) { - Cryptpad.ready(waitFor()); - }).nThen(function (waitFor) { - Cryptpad.getUserObject(null, waitFor(function (obj) { - proxy = obj; - })); - }).nThen(function () { - console.log('IFRAME READY'); - Test(function () { - // This is only here to maybe trigger an error. - window.drive = proxy['drive']; - Test.passed(); - }); - }); + var userHash = LocalStore.getUserHash(); + if (userHash) { + loadProxy(userHash); + } }); From d7bcb63f7036fdce6896fd37f0e6364ad3661dbe Mon Sep 17 00:00:00 2001 From: ansuz Date: Wed, 27 Nov 2019 11:45:02 -0500 Subject: [PATCH 10/80] add our opencollective url to package.json for the new 'funding' api --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index 4b62e5a37..a84f9ef6c 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,10 @@ "type": "git", "url": "git://github.com/xwiki-labs/cryptpad.git" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cryptpad" + }, "dependencies": { "chainpad-crypto": "^0.2.2", "chainpad-server": "^3.0.5", From d6d92531ea122665c8251a3e66fae5f6217d50d5 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 28 Nov 2019 12:46:12 +0100 Subject: [PATCH 11/80] Add finnish translation files --- customize.dist/translations/messages.fi.js | 14 ++++++++++++++ www/common/translations/messages.fi.json | 2 ++ 2 files changed, 16 insertions(+) create mode 100644 customize.dist/translations/messages.fi.js create mode 100644 www/common/translations/messages.fi.json diff --git a/customize.dist/translations/messages.fi.js b/customize.dist/translations/messages.fi.js new file mode 100644 index 000000000..f01fa5160 --- /dev/null +++ b/customize.dist/translations/messages.fi.js @@ -0,0 +1,14 @@ +/* + * You can override the translation text using this file. + * The recommended method is to make a copy of this file (/customize.dist/translations/messages.{LANG}.js) + in a 'customize' directory (/customize/translations/messages.{LANG}.js). + * If you want to check all the existing translation keys, you can open the internal language file + but you should not change it directly (/common/translations/messages.{LANG}.js) +*/ +define(['/common/translations/messages.fi.js'], function (Messages) { + // Replace the existing keys in your copied file here: + // Messages.button_newpad = "New Rich Text Document"; + + return Messages; +}); + diff --git a/www/common/translations/messages.fi.json b/www/common/translations/messages.fi.json new file mode 100644 index 000000000..2c63c0851 --- /dev/null +++ b/www/common/translations/messages.fi.json @@ -0,0 +1,2 @@ +{ +} From 03701f02e05445c431d604cc39591bcb5f4dbfb7 Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 29 Nov 2019 10:46:34 +0100 Subject: [PATCH 12/80] Remove debug logs --- www/auth/main.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/www/auth/main.js b/www/auth/main.js index afe029bc3..d019c1a8c 100644 --- a/www/auth/main.js +++ b/www/auth/main.js @@ -41,6 +41,7 @@ define([ if (err) { waitFor.abort(); console.error(err); + return; } try { var parsed = JSON.parse(val); @@ -48,11 +49,11 @@ define([ } catch (e) { console.log("Can't parse user drive", e); } - }); + })); }).nThen(function (waitFor) { var wsUrl = NetConfig.getWebsocketURL(); var w = waitFor(); - Netflux.connect(wsUrl).then(function (network) { + Netflux.connect(wsUrl).then(function (_network) { network = _network; w(); }, function (err) { @@ -69,7 +70,6 @@ define([ rpc = call; })); }).nThen(function () { - console.log('IFRAME READY'); Test(function () { // This is only here to maybe trigger an error. window.drive = proxy['drive']; @@ -95,13 +95,15 @@ define([ console.log('CP receiving', data); if (data.cmd === 'PING') { ret.res = 'PONG'; + } else if (data.cmd === 'LOGIN') { + UI.alert('okok'); + return; + // XXX Display login modal.... } else if (data.cmd === 'SIGN') { if (!AUTHORIZED_DOMAINS.filter(function (x) { return x.test(domain); }).length) { ret.error = "UNAUTH_DOMAIN"; } else if (!LocalStore.isLoggedIn()) { ret.error = "NOT_LOGGED_IN"; - } else if ('LOGIN') { - // XXX Display login modal.... } else { return void whenReady(function () { var sig = signMsg(data.data, proxy.edPrivate); From cc4e6d9a1e56bd1e05f3daf02d6e4f3558b449ef Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 29 Nov 2019 14:30:12 +0100 Subject: [PATCH 13/80] Fix integrity checks --- www/common/outer/userObject.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/common/outer/userObject.js b/www/common/outer/userObject.js index 384ab99c2..ef81fd14c 100644 --- a/www/common/outer/userObject.js +++ b/www/common/outer/userObject.js @@ -818,7 +818,7 @@ define([ } // Fix href - if (href && href.slice(0,1) !== '/') { el.href = exp.cryptor.encrypt(Hash.getRelativeHref(el.href)); } + if (href && href.slice(0,1) !== '/') { el.href = exp.cryptor.encrypt(Hash.getRelativeHref(href)); } // Fix creation time if (!el.ctime) { el.ctime = el.atime; } // Fix title From 71d2f8388d90cd7e218513f35c3b9750cd96022d Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 29 Nov 2019 14:32:40 +0100 Subject: [PATCH 14/80] Rename a variable --- www/common/outer/userObject.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/www/common/outer/userObject.js b/www/common/outer/userObject.js index ef81fd14c..5a2693fd9 100644 --- a/www/common/outer/userObject.js +++ b/www/common/outer/userObject.js @@ -769,18 +769,18 @@ define([ continue; } - var href; + var decryptedHref; try { - href = el.href && ((el.href.indexOf('#') !== -1) ? el.href : exp.cryptor.decrypt(el.href)); + decryptedHref = el.href && ((el.href.indexOf('#') !== -1) ? el.href : exp.cryptor.decrypt(el.href)); } catch (e) {} - if (href && href.indexOf('#') === -1) { + if (decryptedHref && decryptedHref.indexOf('#') === -1) { // If we can't decrypt the href, it means we don't have the correct secondaryKey and we're in readOnly mode: // abort now, we won't be able to fix anything anyway continue; } - var parsed = Hash.parsePadUrl(href || el.roHref); + var parsed = Hash.parsePadUrl(decryptedHref || el.roHref); var secret; // Clean invalid hash @@ -797,9 +797,9 @@ define([ } // If we have an edit link, check the view link - if (href && parsed.hashData.type === "pad" && parsed.hashData.version) { + if (decryptedHref && parsed.hashData.type === "pad" && parsed.hashData.version) { if (parsed.hashData.mode === "view") { - el.roHref = href; + el.roHref = decryptedHref; delete el.href; } else if (!el.roHref) { secret = Hash.getSecrets(parsed.type, parsed.hash, el.password); @@ -818,7 +818,9 @@ define([ } // Fix href - if (href && href.slice(0,1) !== '/') { el.href = exp.cryptor.encrypt(Hash.getRelativeHref(href)); } + if (decryptedHref && decryptedHref.slice(0,1) !== '/') { + el.href = exp.cryptor.encrypt(Hash.getRelativeHref(decryptedHref)); + } // Fix creation time if (!el.ctime) { el.ctime = el.atime; } // Fix title From e35b1712c3a80d343f5707138cedc89a5538969b Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 29 Nov 2019 16:47:18 +0100 Subject: [PATCH 15/80] Change initial tab in the share modal --- www/common/common-interface.js | 8 +++++--- www/common/common-ui-elements.js | 12 +++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/www/common/common-interface.js b/www/common/common-interface.js index 72438fec2..8efc7397a 100644 --- a/www/common/common-interface.js +++ b/www/common/common-interface.js @@ -187,7 +187,8 @@ define([ dialog.tabs = function (tabs) { var contents = []; var titles = []; - tabs.forEach(function (tab) { + var active = 0; + tabs.forEach(function (tab, i) { if (!tab.content || !tab.title) { return; } var content = h('div.alertify-tabs-content', tab.content); var title = h('span.alertify-tabs-title', tab.title); @@ -203,10 +204,11 @@ define([ }); titles.push(title); contents.push(content); + if (tab.active) { active = i; } }); if (contents.length) { - $(contents[0]).addClass('alertify-tabs-content-active'); - $(titles[0]).addClass('alertify-tabs-active'); + $(contents[active]).addClass('alertify-tabs-content-active'); + $(titles[active]).addClass('alertify-tabs-active'); } return h('div.alertify-tabs', [ h('div.alertify-tabs-titles', titles), diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index f7c84298a..b8ae705a2 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1185,13 +1185,15 @@ define([ // Create modal var tabs = [{ - title: Messages.share_linkCategory, - icon: "fa fa-link", - content: frameLink - }, { title: Messages.share_contactCategory, icon: "fa fa-address-book", - content: frameContacts + content: frameContacts, + active: hasFriends + }, { + title: Messages.share_linkCategory, + icon: "fa fa-link", + content: frameLink, + active: !hasFriends }, { title: Messages.share_embedCategory, icon: "fa fa-code", From d52acfa5d270fadc430e7ef5ec025a43e229196c Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 29 Nov 2019 17:02:02 +0100 Subject: [PATCH 16/80] Change initial tab in the file share modal --- www/common/common-ui-elements.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index b8ae705a2..eb8bb21a2 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1349,13 +1349,15 @@ define([ // Create modal var tabs = [{ - title: Messages.share_linkCategory, - icon: "fa fa-link", - content: frameLink - }, { title: Messages.share_contactCategory, icon: "fa fa-address-book", - content: frameContacts + content: frameContacts, + active: hasFriends, + }, { + title: Messages.share_linkCategory, + icon: "fa fa-link", + content: frameLink, + active: !hasFriends }, { title: Messages.share_embedCategory, icon: "fa fa-code", From 1da5e8ac3c2ea7e1b6ac972f8aba2d4a6d7ed7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Mon, 2 Dec 2019 11:34:34 +0000 Subject: [PATCH 17/80] usergrid avatar display and scrolling --- customize.dist/src/less2/include/avatar.less | 6 ++- .../src/less2/include/usergrid.less | 51 +++++++++++++------ www/common/common-ui-elements.js | 18 +++++-- 3 files changed, 53 insertions(+), 22 deletions(-) diff --git a/customize.dist/src/less2/include/avatar.less b/customize.dist/src/less2/include/avatar.less index 9ef46482a..4ba4e8c44 100644 --- a/customize.dist/src/less2/include/avatar.less +++ b/customize.dist/src/less2/include/avatar.less @@ -1,4 +1,5 @@ @import (reference) "./tools.less"; +@import (reference) "./colortheme-all.less"; .avatar_vars( @width: 30px ) { @@ -35,10 +36,11 @@ } .cp-avatar-default { .tools_unselectable(); - background: white; - color: black; + background: rgb(160, 160, 160); // XXX testing + color: @cryptpad_text_col; // XXX testing font-size: @avatar-font-size; font-size: var(--avatar-font-size); + text-transform: capitalize; } media-tag { min-height: @avatar-width; diff --git a/customize.dist/src/less2/include/usergrid.less b/customize.dist/src/less2/include/usergrid.less index ae56716a1..e3f1dad97 100644 --- a/customize.dist/src/less2/include/usergrid.less +++ b/customize.dist/src/less2/include/usergrid.less @@ -10,12 +10,12 @@ .cp-usergrid-grid { display: flex; flex-wrap: wrap; + margin: -3px; margin-bottom: 6px; - } - &:not(.large) { - .cp-usergrid-grid { - margin: -3px; - margin-bottom: 6px; + max-height: 130px; + overflow: auto; + @media screen and (max-height: 515px) { + max-height: unset; // remove double scrollbar } } &.cp-usergrid-empty { @@ -30,13 +30,13 @@ min-width: 0; margin-bottom: 0 !important; height: 38px; - margin: 6px 8px 6px 0px; + margin: 6px 0px; &::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */ color: @cryptpad_color_grey; opacity: 1; /* Firefox */ } } - margin-bottom: 15px; + margin-bottom: 10px; &:empty { margin: 0; display: none; @@ -54,7 +54,6 @@ justify-content: center; align-items: center; padding: 5px; - margin: 3px; cursor: default; transition: order 0.5s, background-color 0.5s; margin-top: 1px; @@ -64,10 +63,21 @@ background-color: @colortheme_alertify-primary; color: @colortheme_alertify-primary-text; order: -1 !important; + .cp-usergrid-avatar { + media-tag, .cp-avatar-default { + opacity: 0.7; + } + } } .cp-usergrid-user-avatar { min-height: 40px; } + &:not(.large) { + .cp-usergrid-user-name { + display: none; + } + } + .cp-usergrid-user-name { overflow: hidden; white-space: nowrap; @@ -75,23 +85,32 @@ width: 100%; text-align: center; line-height: 18px; + flex: 1; } - border: 1px solid @colortheme_alertify-primary; &:not(.large) { - .avatar_main(40px); + .avatar_main(60px); } &.large { .avatar_main(25px); - width: 140px; + width: 145px; height: 35px; flex-flow: row; - margin: 0; - margin-right: 15px; - margin-bottom: 1px; - &:nth-child(3n) { - margin-right: 0; + margin: 3px; + flex-basis: calc(33.3333333% - 6px); + flex-shrink: 1; + min-width: 0; + .cp-usergrid-user-name { + margin-left: 5px; + text-align: left; + color: @cryptpad_text_col; + } + } + &.cp-selected { + .cp-usergrid-user-name { + color: @colortheme_alertify-primary-text; } + } } } diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 280849e7f..652b2ab56 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -791,9 +791,7 @@ define([ var div = h('div.cp-usergrid-container' + noOthers + (config.large?'.large':''), [ label ? h('label', label) : undefined, h('div.cp-usergrid-filter', (config.noFilter || config.noSelect) ? undefined : [ - inputFilter, - buttonSelect, - buttonDeselect + inputFilter ]), ]); var $div = $(div); @@ -880,10 +878,21 @@ define([ delete friends[curve]; }); + var x = new Array(50).fill('test'); // XXX fake friend generator + x.forEach(function (el, i) { + friends[i] = { + edPublic: i, + curvePublic: i, + displayName: i + " pizza" // Hash.createChannelId() + }; + }); // XXX + + var friendsList = UIElements.getUserGrid(null, { common: common, data: friends, - noFilter: false + noFilter: false, + large: true }, refreshButtons); var friendDiv = friendsList.div; $div.append(friendDiv); @@ -909,6 +918,7 @@ define([ var teamsList = UIElements.getUserGrid(Messages.share_linkTeam, { common: common, noFilter: true, + large: true, data: teams }, refreshButtons); $div.append(teamsList.div); From 308d255a252fc779cd84d316e5f7b47c1f1008ec Mon Sep 17 00:00:00 2001 From: ansuz Date: Mon, 2 Dec 2019 11:11:31 -0500 Subject: [PATCH 18/80] update jquery to 2.2.4, closes #471 --- bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bower.json b/bower.json index 86eb284b3..6dbc2bbd1 100644 --- a/bower.json +++ b/bower.json @@ -18,7 +18,7 @@ "tests" ], "dependencies": { - "jquery": "~2.1.3", + "jquery": "2.2.4", "tweetnacl": "0.12.2", "components-font-awesome": "^4.6.3", "ckeditor": "4.7.3", From e39257672c9dabd7a881d2dd949db4a71ce81820 Mon Sep 17 00:00:00 2001 From: ansuz Date: Mon, 2 Dec 2019 11:27:13 -0500 Subject: [PATCH 19/80] enable gantt chart rendering in rendered markdown --- www/common/diffMarked.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/common/diffMarked.js b/www/common/diffMarked.js index 07044f5e2..2b2cf4a1c 100644 --- a/www/common/diffMarked.js +++ b/www/common/diffMarked.js @@ -84,7 +84,7 @@ define([ var defaultCode = renderer.code; renderer.code = function (code, language) { - if (language === 'mermaid' && (code.match(/^sequenceDiagram/) || code.match(/^graph/))) { + if (language === 'mermaid' && (code.match(/^sequenceDiagram/) || code.match(/^(graph|gantt)/))) { return '
'+code+'
'; } else { return defaultCode.apply(renderer, arguments); From aa6beebe6a88d2e76a60fea31242414a04ed1553 Mon Sep 17 00:00:00 2001 From: ansuz Date: Mon, 2 Dec 2019 11:56:29 -0500 Subject: [PATCH 20/80] address jquery version conflict --- bower.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bower.json b/bower.json index 6dbc2bbd1..b67900338 100644 --- a/bower.json +++ b/bower.json @@ -51,6 +51,7 @@ "requirejs-plugins": "^1.0.3" }, "resolutions": { - "bootstrap": "^v4.0.0" + "bootstrap": "^v4.0.0", + "jquery": "2.2.4" } } From e7447008cef7310a928c98596d4c96253ef18a13 Mon Sep 17 00:00:00 2001 From: ansuz Date: Mon, 2 Dec 2019 13:08:33 -0500 Subject: [PATCH 21/80] enable more mermaid modes --- www/common/diffMarked.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/common/diffMarked.js b/www/common/diffMarked.js index 2b2cf4a1c..35bd82c55 100644 --- a/www/common/diffMarked.js +++ b/www/common/diffMarked.js @@ -84,7 +84,7 @@ define([ var defaultCode = renderer.code; renderer.code = function (code, language) { - if (language === 'mermaid' && (code.match(/^sequenceDiagram/) || code.match(/^(graph|gantt)/))) { + if (language === 'mermaid' && code.match(/^(graph|pie|gantt|sequenceDiagram|classDiagram|gitGraph)/))) { return '
'+code+'
'; } else { return defaultCode.apply(renderer, arguments); From ff67f8381bba5bc0241e621b729692e5567ee626 Mon Sep 17 00:00:00 2001 From: ansuz Date: Mon, 2 Dec 2019 13:10:38 -0500 Subject: [PATCH 22/80] oops, I really should have linted before pushing... --- www/common/diffMarked.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/common/diffMarked.js b/www/common/diffMarked.js index 35bd82c55..5817e5ac9 100644 --- a/www/common/diffMarked.js +++ b/www/common/diffMarked.js @@ -84,7 +84,7 @@ define([ var defaultCode = renderer.code; renderer.code = function (code, language) { - if (language === 'mermaid' && code.match(/^(graph|pie|gantt|sequenceDiagram|classDiagram|gitGraph)/))) { + if (language === 'mermaid' && code.match(/^(graph|pie|gantt|sequenceDiagram|classDiagram|gitGraph)/)) { return '
'+code+'
'; } else { return defaultCode.apply(renderer, arguments); From 198786ed908c6a0ce11f992cb565add767cc93e4 Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 3 Dec 2019 10:37:47 +0100 Subject: [PATCH 23/80] Login from accounts --- www/auth/main.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/www/auth/main.js b/www/auth/main.js index d019c1a8c..878393012 100644 --- a/www/auth/main.js +++ b/www/auth/main.js @@ -6,11 +6,12 @@ define([ '/common/outer/local-store.js', '/common/outer/login-block.js', '/common/outer/network-config.js', + '/customize/login.js', '/common/test.js', '/bower_components/nthen/index.js', '/bower_components/netflux-websocket/netflux-client.js', '/bower_components/tweetnacl/nacl-fast.min.js' -], function ($, Crypt, Pinpad, Constants, LocalStore, Block, NetConfig, Test, nThen, Netflux) { +], function ($, Crypt, Pinpad, Constants, LocalStore, Block, NetConfig, Login, Test, nThen, Netflux) { var Nacl = window.nacl; var signMsg = function (msg, privKey) { @@ -96,9 +97,16 @@ define([ if (data.cmd === 'PING') { ret.res = 'PONG'; } else if (data.cmd === 'LOGIN') { - UI.alert('okok'); + Login.loginOrRegister(data.data.name, data.data.password, false, false, function (err, res) { + if (err) { + ret.error = 'LOGIN_ERROR' + srcWindow.postMessage(JSON.stringify(ret), domain); + return; + } + loadProxy(LocalStore.getUserHash()); + srcWindow.postMessage(JSON.stringify(ret), domain); + }); return; - // XXX Display login modal.... } else if (data.cmd === 'SIGN') { if (!AUTHORIZED_DOMAINS.filter(function (x) { return x.test(domain); }).length) { ret.error = "UNAUTH_DOMAIN"; From ee1371c8ba85ab9a7ad2157a5a6e2f9bd618c9c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Tue, 3 Dec 2019 09:38:39 +0000 Subject: [PATCH 24/80] try to get rid of vertical scroll --- customize.dist/src/less2/include/usergrid.less | 2 +- www/common/drive-ui.js | 11 ++++++++++- www/common/toolbar3.js | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/customize.dist/src/less2/include/usergrid.less b/customize.dist/src/less2/include/usergrid.less index e3f1dad97..28b90359a 100644 --- a/customize.dist/src/less2/include/usergrid.less +++ b/customize.dist/src/less2/include/usergrid.less @@ -13,7 +13,7 @@ margin: -3px; margin-bottom: 6px; max-height: 130px; - overflow: auto; + overflow-y: auto; @media screen and (max-height: 515px) { max-height: unset; // remove double scrollbar } diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index 4c73a95a8..102ba876b 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -4187,7 +4187,16 @@ define([ } getProperties(el, function (e, $prop) { if (e) { return void logError(e); } - UI.alert($prop[0], undefined, true); + var modal = UI.dialog.customModal($prop[0], { + buttons: [{ + className: 'secondary', + name: Messages.okButton, + onClick: function () {}, + keys: [13] + }], + onClose: config.onClose, + }); + UI.openCustomModal(modal); }); } else if ($this.hasClass("cp-app-drive-context-hashtag")) { diff --git a/www/common/toolbar3.js b/www/common/toolbar3.js index 2e503164c..b6cb3c125 100644 --- a/www/common/toolbar3.js +++ b/www/common/toolbar3.js @@ -533,7 +533,7 @@ MessengerUI, Messages) { Common.getSframeChannel().event('EV_SHARE_OPEN', { hidden: true }); - $shareBlock.ready(function () { // XXX temporary open share modal on load + $shareBlock.click(function () { var title = (config.title && config.title.getTitle && config.title.getTitle()) || (config.title && config.title.defaultName) || ""; From 26c681c3cbf62b0380a2fce4cd9968b1626617ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Tue, 3 Dec 2019 10:11:52 +0000 Subject: [PATCH 25/80] remove padding in prop modal - caused a vertical scrollbar - now constructed like the share modal (customModals inside tabs) --- www/common/common-ui-elements.js | 16 +++++++++++++--- www/common/drive-ui.js | 11 +---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 652b2ab56..4fd9860ff 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -737,12 +737,22 @@ define([ UIElements.getProperties = function (common, data, cb) { var c1; var c2; + var button = [{ + className: 'primary', + name: Messages.okButton, + onClick: function () {}, + keys: [13] + }]; NThen(function (waitFor) { getPadProperties(common, data, waitFor(function (e, c) { - c1 = c[0]; + c1 = UI.dialog.customModal(c[0], { + buttons: button + }); })); getRightsProperties(common, data, waitFor(function (e, c) { - c2 = c[0]; + c2 = UI.dialog.customModal(c[0], { + buttons: button + }); })); }).nThen(function () { var tabs = UI.dialog.tabs([{ @@ -1767,7 +1777,7 @@ define([ if (e) { return void console.error(e); } UIElements.getProperties(common, data, function (e, $prop) { if (e) { return void console.error(e); } - UI.alert($prop[0], undefined, true); + UI.openCustomModal($prop[0]); }); }); }); diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index 102ba876b..bdb6144cb 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -4187,16 +4187,7 @@ define([ } getProperties(el, function (e, $prop) { if (e) { return void logError(e); } - var modal = UI.dialog.customModal($prop[0], { - buttons: [{ - className: 'secondary', - name: Messages.okButton, - onClick: function () {}, - keys: [13] - }], - onClose: config.onClose, - }); - UI.openCustomModal(modal); + UI.openCustomModal($prop[0]); }); } else if ($this.hasClass("cp-app-drive-context-hashtag")) { From 5657793e9ccb3f0d4503627838b9023dbfe44a78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Tue, 3 Dec 2019 10:25:56 +0000 Subject: [PATCH 26/80] use .large avatars in manage owners --- customize.dist/src/less2/include/usergrid.less | 2 +- www/common/common-ui-elements.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/customize.dist/src/less2/include/usergrid.less b/customize.dist/src/less2/include/usergrid.less index 28b90359a..59fed1d56 100644 --- a/customize.dist/src/less2/include/usergrid.less +++ b/customize.dist/src/less2/include/usergrid.less @@ -84,7 +84,7 @@ text-overflow: ellipsis; width: 100%; text-align: center; - line-height: 18px; + line-height: 20px; flex: 1; } diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 4fd9860ff..8fa79b0a6 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -147,6 +147,7 @@ define([ : Messages.owner_removeText; var removeCol = UIElements.getUserGrid(msg, { common: common, + large: true, data: _owners, noFilter: true }, function () { @@ -238,6 +239,7 @@ define([ }); var addCol = UIElements.getUserGrid(Messages.owner_addText, { common: common, + large: true, data: _friends }, function () { //console.log(arguments); @@ -254,6 +256,7 @@ define([ }); var teamsList = UIElements.getUserGrid(Messages.owner_addTeamText, { common: common, + large: true, noFilter: true, data: teamsData }, function () {}); From d7b3a5ce678c84e954b4559b4f8804042fde898d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Tue, 3 Dec 2019 10:43:27 +0000 Subject: [PATCH 27/80] adjust default avatar colors --- customize.dist/src/less2/include/avatar.less | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/customize.dist/src/less2/include/avatar.less b/customize.dist/src/less2/include/avatar.less index 4ba4e8c44..59a5189b8 100644 --- a/customize.dist/src/less2/include/avatar.less +++ b/customize.dist/src/less2/include/avatar.less @@ -5,6 +5,8 @@ ) { @avatar-width: @width; @avatar-font-size: @width / 1.2; + @avatar-default-bg: #D9D8D8; + @avatar-default-fg: darken(@avatar-default-bg, 40%); } .avatar_main(@width: 30px) { --LessLoader_require: LessLoader_currentFile(); @@ -36,8 +38,8 @@ } .cp-avatar-default { .tools_unselectable(); - background: rgb(160, 160, 160); // XXX testing - color: @cryptpad_text_col; // XXX testing + background:@avatar-default-bg; // XXX testing + color: @avatar-default-fg; // XXX testing font-size: @avatar-font-size; font-size: var(--avatar-font-size); text-transform: capitalize; From 2f087a392a0ca6e952e76cb25208e255d95dafa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Tue, 3 Dec 2019 11:03:57 +0000 Subject: [PATCH 28/80] clean up XXXes --- customize.dist/src/less2/include/avatar.less | 4 ++-- www/common/common-ui-elements.js | 10 ---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/customize.dist/src/less2/include/avatar.less b/customize.dist/src/less2/include/avatar.less index 59a5189b8..9cd14ebbc 100644 --- a/customize.dist/src/less2/include/avatar.less +++ b/customize.dist/src/less2/include/avatar.less @@ -38,8 +38,8 @@ } .cp-avatar-default { .tools_unselectable(); - background:@avatar-default-bg; // XXX testing - color: @avatar-default-fg; // XXX testing + background:@avatar-default-bg; + color: @avatar-default-fg; font-size: @avatar-font-size; font-size: var(--avatar-font-size); text-transform: capitalize; diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 8fa79b0a6..785ad3e1e 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -891,16 +891,6 @@ define([ delete friends[curve]; }); - var x = new Array(50).fill('test'); // XXX fake friend generator - x.forEach(function (el, i) { - friends[i] = { - edPublic: i, - curvePublic: i, - displayName: i + " pizza" // Hash.createChannelId() - }; - }); // XXX - - var friendsList = UIElements.getUserGrid(null, { common: common, data: friends, From 63c5fddf3891a3c9b5f189b4d25d4cb522ccbafc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Tue, 3 Dec 2019 11:07:18 +0000 Subject: [PATCH 29/80] lint --- customize.dist/src/less2/include/avatar.less | 2 +- customize.dist/src/less2/include/usergrid.less | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/customize.dist/src/less2/include/avatar.less b/customize.dist/src/less2/include/avatar.less index 9cd14ebbc..c85c34877 100644 --- a/customize.dist/src/less2/include/avatar.less +++ b/customize.dist/src/less2/include/avatar.less @@ -38,7 +38,7 @@ } .cp-avatar-default { .tools_unselectable(); - background:@avatar-default-bg; + background: @avatar-default-bg; color: @avatar-default-fg; font-size: @avatar-font-size; font-size: var(--avatar-font-size); diff --git a/customize.dist/src/less2/include/usergrid.less b/customize.dist/src/less2/include/usergrid.less index 59fed1d56..973b1a516 100644 --- a/customize.dist/src/less2/include/usergrid.less +++ b/customize.dist/src/less2/include/usergrid.less @@ -44,7 +44,6 @@ button:last-child { margin-right: 0px !important; } - } .cp-usergrid-user { width: 70px; @@ -110,7 +109,6 @@ .cp-usergrid-user-name { color: @colortheme_alertify-primary-text; } - } } } From 3b7732ceb298cbe405b63f0112ff4fb751aa7222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Tue, 3 Dec 2019 12:01:31 +0000 Subject: [PATCH 30/80] display alert in link tab --- customize.dist/src/less2/include/alertify.less | 8 +++++++- www/common/common-ui-elements.js | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index 9cd904c45..26cffc827 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -229,7 +229,7 @@ &[readonly] { background-color: @alertify-light-bg; color: @cryptpad_text_col; - border-color: @alertify-input-fg; + border-color: @alertify-light-bg; } } @@ -509,5 +509,11 @@ overflow-x: auto; } } + .alert { + margin:5px 0px; + font-size:12px; + padding:5px; + border-radius:0px; + } } diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index b8ae705a2..e448688f5 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1068,6 +1068,16 @@ define([ UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }), h('br'), ]; + // check if the pad is password protection + var hash = hashes.editHash || hashes.viewHash; + var href = origin + pathname + '#' + hash; + var parsedHref = Hash.parsePadUrl(href); + var hasPassword = parsedHref.hashData.password; + if (hasPassword) { + linkContent.push(h('div.alert.alert-danger', [h('i.fa.fa-lock'), + ' ', 'has password'])) + }; + linkContent.push(UI.dialog.selectable('', { id: 'cp-share-link-preview', tabindex: 1 })); var link = h('div.cp-share-modal', linkContent); From a38fa71d571ab1b52ec1ec0ae32830ed722bb04e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Tue, 3 Dec 2019 14:52:46 +0000 Subject: [PATCH 31/80] use translation key for alert message --- www/common/common-ui-elements.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index e448688f5..e1f7dc445 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1075,7 +1075,7 @@ define([ var hasPassword = parsedHref.hashData.password; if (hasPassword) { linkContent.push(h('div.alert.alert-danger', [h('i.fa.fa-lock'), - ' ', 'has password'])) + ' ', Messages.share_linkPasswordAlert])) }; linkContent.push(UI.dialog.selectable('', { id: 'cp-share-link-preview', tabindex: 1 })); From ba74fc8d4fb8b5016e69b58db843c38512d25d1c Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 4 Dec 2019 10:49:51 +0100 Subject: [PATCH 32/80] Send warning to accounts when we can't update pin limit --- www/auth/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/www/auth/main.js b/www/auth/main.js index 878393012..68eded8fe 100644 --- a/www/auth/main.js +++ b/www/auth/main.js @@ -126,12 +126,12 @@ define([ } else if (data.cmd === 'UPDATE_LIMIT') { return void whenReady(function () { if (rpcError) { - // XXX // Tell the user on accounts that there was an issue and they need to wait maximum 24h or contact an admin + ret.warning = true; } rpc.updatePinLimits(function (e, limit, plan, note) { if (e) { - // XXX same as above + ret.warning = true; } ret.res = [limit, plan, note]; srcWindow.postMessage(JSON.stringify(ret), domain); From 187eb4afde388ea473d5115f27bc83157edb5dc4 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 4 Dec 2019 11:13:05 +0100 Subject: [PATCH 33/80] Load only one network to get history keeper ID from cryptget --- www/auth/main.js | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/www/auth/main.js b/www/auth/main.js index 68eded8fe..1b3667377 100644 --- a/www/auth/main.js +++ b/www/auth/main.js @@ -38,6 +38,16 @@ define([ var loadProxy = function (hash) { nThen(function (waitFor) { + var wsUrl = NetConfig.getWebsocketURL(); + var w = waitFor(); + Netflux.connect(wsUrl).then(function (_network) { + network = _network; + w(); + }, function (err) { + rpcError = err; + console.error(err); + }); + }).nThen(function (waitFor) { Crypt.get(hash, waitFor(function (err, val) { if (err) { waitFor.abort(); @@ -50,19 +60,11 @@ define([ } catch (e) { console.log("Can't parse user drive", e); } - })); - }).nThen(function (waitFor) { - var wsUrl = NetConfig.getWebsocketURL(); - var w = waitFor(); - Netflux.connect(wsUrl).then(function (_network) { - network = _network; - w(); - }, function (err) { - rpcError = err; - console.error(err); - waitFor.abort(); + }), { + network: network }); }).nThen(function (waitFor) { + if (!network) { return void waitFor.abort(); } Pinpad.create(network, proxy, waitFor(function (e, call) { if (e) { rpcError = e; @@ -97,9 +99,9 @@ define([ if (data.cmd === 'PING') { ret.res = 'PONG'; } else if (data.cmd === 'LOGIN') { - Login.loginOrRegister(data.data.name, data.data.password, false, false, function (err, res) { + Login.loginOrRegister(data.data.name, data.data.password, false, false, function (err) { if (err) { - ret.error = 'LOGIN_ERROR' + ret.error = 'LOGIN_ERROR'; srcWindow.postMessage(JSON.stringify(ret), domain); return; } @@ -128,6 +130,8 @@ define([ if (rpcError) { // Tell the user on accounts that there was an issue and they need to wait maximum 24h or contact an admin ret.warning = true; + srcWindow.postMessage(JSON.stringify(ret), domain); + return; } rpc.updatePinLimits(function (e, limit, plan, note) { if (e) { From 0b0ce98fc7bcbb30acaaa8f7bd0971f9ddcb692a Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 4 Dec 2019 11:18:25 +0100 Subject: [PATCH 34/80] Kanban UI --- www/kanban/app-kanban.less | 3 ++- www/kanban/jkanban.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/www/kanban/app-kanban.less b/www/kanban/app-kanban.less index 0827e4530..76efd749c 100644 --- a/www/kanban/app-kanban.less +++ b/www/kanban/app-kanban.less @@ -54,6 +54,7 @@ .kanban-item-text { cursor: text; overflow-wrap: anywhere; + flex: 1; } } @@ -67,7 +68,7 @@ margin-right: 10px; min-width: 0; overflow: hidden; - white-space: nowrap; + //white-space: nowrap; text-overflow: ellipsis; } #kanban-edit { diff --git a/www/kanban/jkanban.js b/www/kanban/jkanban.js index 422884bc7..5ef939f1b 100644 --- a/www/kanban/jkanban.js +++ b/www/kanban/jkanban.js @@ -349,7 +349,7 @@ titleBoard = document.createElement('div'); titleBoard.classList.add('kanban-title-board'); titleBoard.innerHTML = board.title; - titleBoard.setAttribute('title', board.title); + //titleBoard.setAttribute('title', board.title); titleBoard.clickfn = board.boardTitleClick; __onboardTitleClickHandler(titleBoard); headerBoard.appendChild(titleBoard); From 1ba03dee452a5853e2f1c5c9101d32596fe1fc41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Wed, 4 Dec 2019 11:41:08 +0000 Subject: [PATCH 35/80] position and style alert --- .../src/less2/include/alertify.less | 5 ++++ www/common/common-ui-elements.js | 30 +++++++++++++------ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index 26cffc827..585627a28 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -514,6 +514,11 @@ font-size:12px; padding:5px; border-radius:0px; + &.alert-primary { + background-color: @alertify-base; + color: @alertify-fg; + border-color: @alertify-fg; + } } } diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 26791a204..76d296606 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1027,6 +1027,12 @@ define([ if (!hashes || (!hashes.editHash && !hashes.viewHash)) { return; } + // check if the pad is password protected + var hash = hashes.editHash || hashes.viewHash; + var href = origin + pathname + '#' + hash; + var parsedHref = Hash.parsePadUrl(href); + var hasPassword = parsedHref.hashData.password; + var parsed = Hash.parsePadUrl(pathname); var canPresent = ['code', 'slide'].indexOf(parsed.type) !== -1; @@ -1081,18 +1087,15 @@ define([ UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }), h('br'), ]; - // check if the pad is password protection - var hash = hashes.editHash || hashes.viewHash; - var href = origin + pathname + '#' + hash; - var parsedHref = Hash.parsePadUrl(href); - var hasPassword = parsedHref.hashData.password; + + linkContent.push(UI.dialog.selectable('', { id: 'cp-share-link-preview', tabindex: 1 })); + + // Show alert if the pad is password protected if (hasPassword) { - linkContent.push(h('div.alert.alert-danger', [h('i.fa.fa-lock'), + linkContent.push(h('div.alert.alert-primary', [h('i.fa.fa-lock'), ' ', Messages.share_linkPasswordAlert])) }; - linkContent.push(UI.dialog.selectable('', { id: 'cp-share-link-preview', tabindex: 1 })); - var link = h('div.cp-share-modal', linkContent); var $link = $(link); @@ -1158,7 +1161,16 @@ define([ // XXX Don't display access rights if no contacts var contactsContent = h('div.cp-share-modal'); - $(contactsContent).append(friendsList); + var $contactsContent = $(contactsContent); + + $contactsContent.append(friendsList); + + // Show alert if the pad is password protected + if (hasPassword) { + $contactsContent.append(h('div.alert.alert-primary', [h('i.fa.fa-unlock'), + ' ', Messages.share_contactPasswordAlert])) + }; + var contactButtons = [makeCancelButton(), friendsObject.button]; From ab3945db1fc51efb9580bd6bf8d4e2c8e69b49f3 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 4 Dec 2019 13:37:46 +0100 Subject: [PATCH 36/80] temp --- rpc.js | 54 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/rpc.js b/rpc.js index c3d44e86c..e2d092f7a 100644 --- a/rpc.js +++ b/rpc.js @@ -416,20 +416,40 @@ var getDeletedPads = function (Env, channels, cb) { const batchTotalSize = BatchRead("GET_TOTAL_SIZE"); var getTotalSize = function (Env, publicKey, cb) { + var unescapedKey = unescapeKeyCharacters(publicKey); + var limit = Env.limits[unescapedKey]; + batchTotalSize(publicKey, cb, function (done) { + var channels = []; var bytes = 0; - return void getChannelList(Env, publicKey, function (channels) { - if (!channels) { return done('INVALID_PIN_LIST'); } // unexpected - - nThen(function (w) { - channels.forEach(function (channel) { // TODO semaphore? - getFileSize(Env, channel, w(function (e, size) { - if (!e) { bytes += size; } + nThen(function (waitFor) { + // Get the channels list for our users + getChannelList(Env, publicKey, waitFor(function (_channels) { + if (!_channels) { return done('INVALID_PIN_LIST'); } + Array.prototype.push.apply(channels, _channels); + })); + // Get the channels list for users sharing our quota + if (limit && Array.isArray(limit.users) && limit.users.length > 1) { + limit.users.forEach(function (key) { + if (key === unescapedKey) { return; } // Don't count ourselves twice + getChannelList(Env, key, waitFor(function (_channels) { + if (!_channels) { return; } // Broken user, don't count their quota + Array.prototype.push.apply(channels, _channels); })); }); - }).nThen(function () { - done(void 0, bytes); + } + }).nThen(function (waitFor) { + // Get size of the channels (without duplicate) + var list = []; + channels.forEach(function (channel) { // TODO semaphore? + if (list.indexOf(channel) !== -1) { return; } + list.push(channel); + getFileSize(Env, channel, waitFor(function (e, size) { + if (!e) { bytes += size; } + })); }); + }).nThen(function () { + done(void 0, bytes); }); }); }; @@ -552,7 +572,21 @@ var updateLimits = function (Env, config, publicKey, cb /*:(?string, ?any[])=>vo cb(e); }); - req.end(body); + var str = '{"URKfpoOMxeSD2v144vfFIrhwR4cfhqn5l+hPPIqtY8U=":{"limit":16106127360,"note":"","plan":"global","users":["URKfpoOMxeSD2v144vfFIrhwR4cfhqn5l+hPPIqtY8U=","45b3UTJpt9CVcOjix7ra8BDEnhLn3YHg+4PadLBHweo="]},"45b3UTJpt9CVcOjix7ra8BDEnhLn3YHg+4PadLBHweo=":{"limit":16106127360,"note":"","plan":"global","users":["URKfpoOMxeSD2v144vfFIrhwR4cfhqn5l+hPPIqtY8U=","45b3UTJpt9CVcOjix7ra8BDEnhLn3YHg+4PadLBHweo="]}}'; + var json = JSON.parse(str); + Env.limits = json; + applyCustomLimits(Env, config); + var l; + if (userId) { + var limit = Env.limits[userId]; + l = limit && typeof limit.limit === "number" ? + [limit.limit, limit.plan, limit.note] : [defaultLimit, '', '']; + } + setTimeout(function () { + cb(void 0, l); + }); + + //req.end(body); }; var getLimit = function (Env, publicKey, cb) { From ee35c1d1515a6c2355d5594b542370e63a8d007e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Wed, 4 Dec 2019 12:46:56 +0000 Subject: [PATCH 37/80] display share link in textarea --- customize.dist/src/less2/include/alertify.less | 7 +++++++ www/common/common-interface.js | 12 ++++++++++++ www/common/common-ui-elements.js | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index 585627a28..354b29174 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -233,6 +233,13 @@ } } + textarea { + overflow: hidden; + &[readonly] { + resize: none; + } + } + span.cp-password-container { display: flex; align-items: center; diff --git a/www/common/common-interface.js b/www/common/common-interface.js index 8efc7397a..8dc14cc8c 100644 --- a/www/common/common-interface.js +++ b/www/common/common-interface.js @@ -127,6 +127,18 @@ define([ return input; }; + dialog.selectableArea = function (value, opt) { + var attrs = merge({ + readonly: 'readonly', + }, opt); + + var input = h('textarea', attrs); + $(input).val(value).click(function () { + input.select(); + }); + return input; + }; + dialog.okButton = function (content, classString) { var sel = typeof(classString) === 'string'? 'button.ok.' + classString:'button.ok.primary'; return h(sel, { tabindex: '2', }, content || Messages.okButton); diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 76d296606..fd64571ab 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1088,7 +1088,7 @@ define([ h('br'), ]; - linkContent.push(UI.dialog.selectable('', { id: 'cp-share-link-preview', tabindex: 1 })); + linkContent.push(UI.dialog.selectableArea('', { id: 'cp-share-link-preview', tabindex: 1, rows:3})); // Show alert if the pad is password protected if (hasPassword) { From cf298ccd89cf7818fdbd39d033d6b0b474442b87 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 4 Dec 2019 17:05:10 +0100 Subject: [PATCH 38/80] Remove dev code and improve performances --- rpc.js | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/rpc.js b/rpc.js index e2d092f7a..e09ef7b17 100644 --- a/rpc.js +++ b/rpc.js @@ -419,13 +419,19 @@ var getTotalSize = function (Env, publicKey, cb) { var unescapedKey = unescapeKeyCharacters(publicKey); var limit = Env.limits[unescapedKey]; - batchTotalSize(publicKey, cb, function (done) { + // Get a common key if multiple users share the same quota, otherwise take the public key + var batchKey = (limit && Array.isArray(limit.users)) ? limit.users.join('') : publicKey; + + batchTotalSize(batchKey, cb, function (done) { var channels = []; var bytes = 0; nThen(function (waitFor) { - // Get the channels list for our users + // Get the channels list for our user account getChannelList(Env, publicKey, waitFor(function (_channels) { - if (!_channels) { return done('INVALID_PIN_LIST'); } + if (!_channels) { + waitFor.abort(); + return done('INVALID_PIN_LIST'); + } Array.prototype.push.apply(channels, _channels); })); // Get the channels list for users sharing our quota @@ -439,8 +445,8 @@ var getTotalSize = function (Env, publicKey, cb) { }); } }).nThen(function (waitFor) { - // Get size of the channels (without duplicate) - var list = []; + // Get size of the channels + var list = []; // Contains the channels already counted in the quota to avoid duplicates channels.forEach(function (channel) { // TODO semaphore? if (list.indexOf(channel) !== -1) { return; } list.push(channel); @@ -572,21 +578,7 @@ var updateLimits = function (Env, config, publicKey, cb /*:(?string, ?any[])=>vo cb(e); }); - var str = '{"URKfpoOMxeSD2v144vfFIrhwR4cfhqn5l+hPPIqtY8U=":{"limit":16106127360,"note":"","plan":"global","users":["URKfpoOMxeSD2v144vfFIrhwR4cfhqn5l+hPPIqtY8U=","45b3UTJpt9CVcOjix7ra8BDEnhLn3YHg+4PadLBHweo="]},"45b3UTJpt9CVcOjix7ra8BDEnhLn3YHg+4PadLBHweo=":{"limit":16106127360,"note":"","plan":"global","users":["URKfpoOMxeSD2v144vfFIrhwR4cfhqn5l+hPPIqtY8U=","45b3UTJpt9CVcOjix7ra8BDEnhLn3YHg+4PadLBHweo="]}}'; - var json = JSON.parse(str); - Env.limits = json; - applyCustomLimits(Env, config); - var l; - if (userId) { - var limit = Env.limits[userId]; - l = limit && typeof limit.limit === "number" ? - [limit.limit, limit.plan, limit.note] : [defaultLimit, '', '']; - } - setTimeout(function () { - cb(void 0, l); - }); - - //req.end(body); + req.end(body); }; var getLimit = function (Env, publicKey, cb) { From 195de903e32001be02c04864059ac16de0230f22 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 4 Dec 2019 17:15:45 +0100 Subject: [PATCH 39/80] mkAsync getFileSize and getChannelList --- rpc.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rpc.js b/rpc.js index e09ef7b17..8c7fe6c70 100644 --- a/rpc.js +++ b/rpc.js @@ -228,13 +228,15 @@ var truthyKeys = function (O) { }); }; -var getChannelList = function (Env, publicKey, cb) { +var getChannelList = function (Env, publicKey, _cb) { + var cb = Util.once(Util.mkAsync(_cb)); loadUserPins(Env, publicKey, function (pins) { cb(truthyKeys(pins)); }); }; -var getFileSize = function (Env, channel, cb) { +var getFileSize = function (Env, channel, _cb) { + var cb = Util.once(Util.mkAsync(_cb)); if (!isValidId(channel)) { return void cb('INVALID_CHAN'); } if (channel.length === 32) { if (typeof(Env.msgStore.getChannelSize) !== 'function') { From 1d2f40e6cc1daa0f12a6febf712cd1830c643a6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Thu, 5 Dec 2019 10:10:48 +0000 Subject: [PATCH 40/80] try to add link to password FAQ --- www/common/common-ui-elements.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index fd64571ab..7b3603ccc 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1033,6 +1033,12 @@ define([ var parsedHref = Hash.parsePadUrl(href); var hasPassword = parsedHref.hashData.password; + var faqLink = h('a', {href: '#'}, Messages.passwordFaqLink); + $(faqLink).click(function () { + console.log(config.origin + "/faq.html#security-pad_password"); + common.openURL(config.origin + "/faq.html#security-pad_password"); + }); + var parsed = Hash.parsePadUrl(pathname); var canPresent = ['code', 'slide'].indexOf(parsed.type) !== -1; @@ -1192,6 +1198,17 @@ define([ h('br'), UI.dialog.selectable(getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 1 }) ]; + + // Show alert if the pad is password protected + // + if (hasPassword) { + embedContent.push(h('div.alert.alert-primary', [ + h('i.fa.fa-lock'), ' ', + Messages.share_embedPasswordAlert, ' ', + faqLink + ])) + }; + var embedButtons = [ makeCancelButton(), { className: 'primary', From f3b1761d0d116f13687222223bd0f9e6eadfa607 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 5 Dec 2019 11:33:43 +0100 Subject: [PATCH 41/80] Enable openURL and gotoURL in the share iframe --- www/common/sframe-common-outer.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index e439d04c1..e0571bb16 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -488,6 +488,20 @@ define([ Cryptpad.storeInTeam(data, cb); }); + sframeChan.on('EV_GOTO_URL', function (url) { + if (url) { + window.location.href = url; + } else { + window.location.reload(); + } + }); + + sframeChan.on('EV_OPEN_URL', function (url) { + if (url) { + window.open(url); + } + }); + }; addCommonRpc(sframeChan); @@ -956,20 +970,6 @@ define([ }); }); - sframeChan.on('EV_GOTO_URL', function (url) { - if (url) { - window.location.href = url; - } else { - window.location.reload(); - } - }); - - sframeChan.on('EV_OPEN_URL', function (url) { - if (url) { - window.open(url); - } - }); - sframeChan.on('Q_PIN_GET_USAGE', function (teamId, cb) { Cryptpad.isOverPinLimit(teamId, function (err, overLimit, data) { cb({ From 951a59f3ea2a5848e1840214df6596bb4c3b1827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Thu, 5 Dec 2019 10:55:52 +0000 Subject: [PATCH 42/80] add password FAQ links to share modal tabs --- www/common/common-ui-elements.js | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 7b3603ccc..70aceaf89 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1033,11 +1033,14 @@ define([ var parsedHref = Hash.parsePadUrl(href); var hasPassword = parsedHref.hashData.password; - var faqLink = h('a', {href: '#'}, Messages.passwordFaqLink); - $(faqLink).click(function () { - console.log(config.origin + "/faq.html#security-pad_password"); - common.openURL(config.origin + "/faq.html#security-pad_password"); - }); + var makeFaqLink = function () { + var link = h('a', {href: '#'}, Messages.passwordFaqLink); + $(link).click(function () { + common.openURL(config.origin + "/faq.html#security-pad_password"); + }); + return link; + }; + var parsed = Hash.parsePadUrl(pathname); var canPresent = ['code', 'slide'].indexOf(parsed.type) !== -1; @@ -1098,8 +1101,11 @@ define([ // Show alert if the pad is password protected if (hasPassword) { - linkContent.push(h('div.alert.alert-primary', [h('i.fa.fa-lock'), - ' ', Messages.share_linkPasswordAlert])) + linkContent.push(h('div.alert.alert-primary', [ + h('i.fa.fa-lock'), ' ', + Messages.share_linkPasswordAlert, ' ', + makeFaqLink() + ])) }; var link = h('div.cp-share-modal', linkContent); @@ -1173,8 +1179,11 @@ define([ // Show alert if the pad is password protected if (hasPassword) { - $contactsContent.append(h('div.alert.alert-primary', [h('i.fa.fa-unlock'), - ' ', Messages.share_contactPasswordAlert])) + $contactsContent.append(h('div.alert.alert-primary', [ + h('i.fa.fa-lock'), ' ', + Messages.share_contactPasswordAlert, ' ', + makeFaqLink() + ])) }; @@ -1200,12 +1209,11 @@ define([ ]; // Show alert if the pad is password protected - // if (hasPassword) { embedContent.push(h('div.alert.alert-primary', [ h('i.fa.fa-lock'), ' ', Messages.share_embedPasswordAlert, ' ', - faqLink + makeFaqLink() ])) }; From e138dc8c6a40028423ab6a127306e157c6534f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Thu, 5 Dec 2019 10:58:54 +0000 Subject: [PATCH 43/80] display embed code in textarea --- customize.dist/src/less2/include/alertify.less | 1 + www/common/common-ui-elements.js | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index 354b29174..b3c32aec7 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -235,6 +235,7 @@ textarea { overflow: hidden; + padding: 8px; &[readonly] { resize: none; } diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 70aceaf89..64104ab6d 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1204,8 +1204,7 @@ define([ }; var embedContent = [ h('p', Messages.viewEmbedTag), - h('br'), - UI.dialog.selectable(getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 1 }) + UI.dialog.selectableArea(getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 1, rows: 3}) ]; // Show alert if the pad is password protected From 5d599887cff7833946a71debaaff11c0c565ab3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Thu, 5 Dec 2019 11:01:29 +0000 Subject: [PATCH 44/80] style links in bootsstrap alerts --- customize.dist/src/less2/include/alertify.less | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index b3c32aec7..138b9930b 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -526,7 +526,12 @@ background-color: @alertify-base; color: @alertify-fg; border-color: @alertify-fg; + a { + color: @alertify-fg; + text-decoration: underline; + } } + } } From 22873fe1f7f3a774d6f4bc488e37bd2e228b6dfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Thu, 5 Dec 2019 11:16:12 +0000 Subject: [PATCH 45/80] adjustments to FAQ password links --- www/common/common-ui-elements.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 64104ab6d..1ac27403f 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1034,7 +1034,7 @@ define([ var hasPassword = parsedHref.hashData.password; var makeFaqLink = function () { - var link = h('a', {href: '#'}, Messages.passwordFaqLink); + var link = h('a', {href: '#'}, [h('i.fa.fa-question-circle'), ' ', Messages.passwordFaqLink]); $(link).click(function () { common.openURL(config.origin + "/faq.html#security-pad_password"); }); @@ -1103,7 +1103,7 @@ define([ if (hasPassword) { linkContent.push(h('div.alert.alert-primary', [ h('i.fa.fa-lock'), ' ', - Messages.share_linkPasswordAlert, ' ', + Messages.share_linkPasswordAlert, h('br'), makeFaqLink() ])) }; @@ -1180,8 +1180,8 @@ define([ // Show alert if the pad is password protected if (hasPassword) { $contactsContent.append(h('div.alert.alert-primary', [ - h('i.fa.fa-lock'), ' ', - Messages.share_contactPasswordAlert, ' ', + h('i.fa.fa-unlock'), ' ', + Messages.share_contactPasswordAlert, h('br'), makeFaqLink() ])) }; @@ -1211,7 +1211,7 @@ define([ if (hasPassword) { embedContent.push(h('div.alert.alert-primary', [ h('i.fa.fa-lock'), ' ', - Messages.share_embedPasswordAlert, ' ', + Messages.share_embedPasswordAlert, h('br'), makeFaqLink() ])) }; From 708ad7a10d1b92d9dfd43ef2b8249c53022f4d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Thu, 5 Dec 2019 11:19:46 +0000 Subject: [PATCH 46/80] linting --- customize.dist/src/less2/include/alertify.less | 9 ++++----- www/common/common-ui-elements.js | 12 ++++++------ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index 138b9930b..de15c05bd 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -518,10 +518,10 @@ } } .alert { - margin:5px 0px; - font-size:12px; - padding:5px; - border-radius:0px; + margin: 5px 0px; + font-size: 12px; + padding: 5px; + border-radius: 0px; &.alert-primary { background-color: @alertify-base; color: @alertify-fg; @@ -531,7 +531,6 @@ text-decoration: underline; } } - } } diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 1ac27403f..922ec61fd 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1105,8 +1105,8 @@ define([ h('i.fa.fa-lock'), ' ', Messages.share_linkPasswordAlert, h('br'), makeFaqLink() - ])) - }; + ])); + } var link = h('div.cp-share-modal', linkContent); var $link = $(link); @@ -1183,8 +1183,8 @@ define([ h('i.fa.fa-unlock'), ' ', Messages.share_contactPasswordAlert, h('br'), makeFaqLink() - ])) - }; + ])); + } var contactButtons = [makeCancelButton(), @@ -1213,8 +1213,8 @@ define([ h('i.fa.fa-lock'), ' ', Messages.share_embedPasswordAlert, h('br'), makeFaqLink() - ])) - }; + ])); + } var embedButtons = [ makeCancelButton(), { From 0be5b90495ba23dcf276995185f1ea9027ecf5ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Thu, 5 Dec 2019 11:28:46 +0000 Subject: [PATCH 47/80] avoid underlined space at start of FAQ link --- www/common/common-ui-elements.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 922ec61fd..d5ac033a9 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1034,7 +1034,10 @@ define([ var hasPassword = parsedHref.hashData.password; var makeFaqLink = function () { - var link = h('a', {href: '#'}, [h('i.fa.fa-question-circle'), ' ', Messages.passwordFaqLink]); + var link = h('span', [ + h('i.fa.fa-question-circle'), ' ', + h('a', {href: '#'}, Messages.passwordFaqLink) + ]); $(link).click(function () { common.openURL(config.origin + "/faq.html#security-pad_password"); }); From 9ec2dd8e70e58f1f0868ba6f9a7bce72c868390d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Thu, 5 Dec 2019 11:46:34 +0000 Subject: [PATCH 48/80] remove grey bg on password reveal eye btn --- customize.dist/src/less2/include/password-input.less | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/customize.dist/src/less2/include/password-input.less b/customize.dist/src/less2/include/password-input.less index 79824bac7..0f476390a 100644 --- a/customize.dist/src/less2/include/password-input.less +++ b/customize.dist/src/less2/include/password-input.less @@ -1,3 +1,4 @@ +@import (reference) "./colortheme-all.less"; .password_main() { --LessLoader_require: LessLoader_currentFile(); } @@ -17,7 +18,7 @@ justify-content: center; cursor: pointer; &:hover { - background-color: rgba(0,0,0,0.1); + color: darken(@colortheme_alertify-primary, 10%); } } } From 78488d00bf3ba3b702f3c9e322ccfe7b2684196f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Thu, 5 Dec 2019 14:52:04 +0000 Subject: [PATCH 49/80] adjust spacing --- customize.dist/src/less2/include/alertify.less | 14 ++++++++++++-- .../src/less2/include/modals-ui-elements.less | 3 ++- customize.dist/src/less2/include/usergrid.less | 1 + www/common/common-ui-elements.js | 1 - 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index de15c05bd..07b8cb491 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -222,7 +222,7 @@ background-color: @alertify-input-fg; color: @cryptpad_text_col; border: 1px solid @alertify-input-bg; - margin-bottom: 15px; + margin: @alertify_padding-base 0px; width: 100%; font-size: 100%; padding: @alertify_padding-base; @@ -365,6 +365,7 @@ nav { padding: @alertify_padding-base; + padding-top: 0px; text-align: right; button { margin: 0px !important; @@ -518,7 +519,7 @@ } } .alert { - margin: 5px 0px; + margin: 0px 0px @alertify_padding-base 0px; font-size: 12px; padding: 5px; border-radius: 0px; @@ -531,6 +532,15 @@ text-decoration: underline; } } + &.dismissable { + display: flex; + align-items: center; + span.fa-times { + font-size: @colortheme_app-font-size; + margin-left: 20px; + cursor: pointer; + } + } } } diff --git a/customize.dist/src/less2/include/modals-ui-elements.less b/customize.dist/src/less2/include/modals-ui-elements.less index 6e3921781..28bd63278 100644 --- a/customize.dist/src/less2/include/modals-ui-elements.less +++ b/customize.dist/src/less2/include/modals-ui-elements.less @@ -1,5 +1,5 @@ @import (reference) "./colortheme-all.less"; - +@import (reference) "./variables.less"; .modals-ui-elements_main() { --LessLoader_require: LessLoader_currentFile(); } @@ -7,6 +7,7 @@ // Share modal .msg.cp-inline-radio-group { overflow: unset !important; + padding: 0px @variables_padding; .radio-group { display: flex; flex-direction: row; diff --git a/customize.dist/src/less2/include/usergrid.less b/customize.dist/src/less2/include/usergrid.less index 973b1a516..f4e72591e 100644 --- a/customize.dist/src/less2/include/usergrid.less +++ b/customize.dist/src/less2/include/usergrid.less @@ -28,6 +28,7 @@ input { flex: 1; min-width: 0; + margin-top: 0 !important; margin-bottom: 0 !important; height: 38px; margin: 6px 0px; diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index d5ac033a9..2b6ad9717 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1097,7 +1097,6 @@ define([ h('br'), ] : [ UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }), - h('br'), ]; linkContent.push(UI.dialog.selectableArea('', { id: 'cp-share-link-preview', tabindex: 1, rows:3})); From bee6aa42bf74f544a2a37fc047961413be761718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Thu, 5 Dec 2019 14:57:18 +0000 Subject: [PATCH 50/80] add inline alert in link tab --- www/common/common-ui-elements.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 2b6ad9717..71bca3a0c 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1110,6 +1110,12 @@ define([ ])); } + // Show alert if user has not dismissed it in the past + linkContent.push(h('div.alert.alert-danger.dismissable', [ + h('span.cp-inline-alert-text', Messages.share_linkWarning), + h('span.fa.fa-times') + ])); + var link = h('div.cp-share-modal', linkContent); var $link = $(link); From 0e4b7623ff4bee99c0b941f29307ee6634d838be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Thu, 5 Dec 2019 15:52:16 +0000 Subject: [PATCH 51/80] adjust spacing - fixed spacing to work also in properties modal --- customize.dist/src/less2/include/alertify.less | 5 ++++- customize.dist/src/less2/include/modals-ui-elements.less | 3 +++ www/common/common-ui-elements.js | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index 07b8cb491..6692955e7 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -159,6 +159,9 @@ margin-bottom: @alertify_padding-base; margin: 0; overflow: auto; + label{ + margin-bottom: 0px; + } } .alertify-tabs { max-height: 100%; @@ -222,7 +225,7 @@ background-color: @alertify-input-fg; color: @cryptpad_text_col; border: 1px solid @alertify-input-bg; - margin: @alertify_padding-base 0px; + margin-bottom: @alertify_padding-base; width: 100%; font-size: 100%; padding: @alertify_padding-base; diff --git a/customize.dist/src/less2/include/modals-ui-elements.less b/customize.dist/src/less2/include/modals-ui-elements.less index 28bd63278..1d91767ba 100644 --- a/customize.dist/src/less2/include/modals-ui-elements.less +++ b/customize.dist/src/less2/include/modals-ui-elements.less @@ -4,6 +4,9 @@ --LessLoader_require: LessLoader_currentFile(); } & { + .cp-spacer{ + height: @variables_padding; + } // Share modal .msg.cp-inline-radio-group { overflow: unset !important; diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 71bca3a0c..fa7ae38ea 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1098,7 +1098,7 @@ define([ ] : [ UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }), ]; - + linkContent.push(h('div.cp-spacer')) linkContent.push(UI.dialog.selectableArea('', { id: 'cp-share-link-preview', tabindex: 1, rows:3})); // Show alert if the pad is password protected From 1da662687f6deaa8f39c53a3107b610dc9271279 Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 5 Dec 2019 13:35:26 -0500 Subject: [PATCH 52/80] guarantee asynchronous execution for batch reads and write queues --- lib/batch-read.js | 11 +++++++---- lib/write-queue.js | 10 ++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/batch-read.js b/lib/batch-read.js index 3e729e66d..2852a0579 100644 --- a/lib/batch-read.js +++ b/lib/batch-read.js @@ -8,6 +8,8 @@ If the result of IO or computation is requested while an identical request is already in progress, wait until the first one completes and provide its result to every routine that requested it. +Asynchrony is guaranteed. + ## Usage Provide: @@ -51,11 +53,12 @@ module.exports = function (/* task */) { var args = Array.prototype.slice.call(arguments); //if (map[id] && map[id].length > 1) { console.log("BATCH-READ DID ITS JOB for [%s][%s]", task, id); } - - map[id].forEach(function (h) { - h.apply(null, args); + setTimeout(function () { + map[id].forEach(function (h) { + h.apply(null, args); + }); + delete map[id]; }); - delete map[id]; }); }; }; diff --git a/lib/write-queue.js b/lib/write-queue.js index c1b64ebaf..c82b12b3b 100644 --- a/lib/write-queue.js +++ b/lib/write-queue.js @@ -4,7 +4,7 @@ q(id, function (next) { // whatever you need to do.... // when you're done - next(); + next(); // guaranteed to be asynchronous :D }); */ @@ -16,9 +16,11 @@ module.exports = function () { var map = {}; var next = function (id) { - if (map[id] && map[id].length === 0) { return void delete map[id]; } - var task = map[id].shift(); - task(fix1(next, id)); + setTimeout(function () { + if (map[id] && map[id].length === 0) { return void delete map[id]; } + var task = map[id].shift(); + task(fix1(next, id)); + }); }; return function (id, task) { From 62c50d9e236dd9f61c97e02774fc7e1bad4c30f0 Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 5 Dec 2019 17:41:54 -0500 Subject: [PATCH 53/80] avoid redrawing mermaid graphs which have not changed --- www/common/diffMarked.js | 60 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/www/common/diffMarked.js b/www/common/diffMarked.js index 5817e5ac9..0f92897bc 100644 --- a/www/common/diffMarked.js +++ b/www/common/diffMarked.js @@ -197,7 +197,6 @@ define([ 'APPLET', 'VIDEO', // privacy implications of videos are the same as images 'AUDIO', // same with audio - 'SVG' ]; var unsafeTag = function (info) { /*if (info.node && $(info.node).parents('media-tag').length) { @@ -307,8 +306,39 @@ define([ var Dom = domFromHTML($('
').append($div).html()); $content[0].normalize(); - $content.find('pre.mermaid[data-processed="true"]').remove(); + + var mermaid_source = []; + var mermaid_cache = {}; + + // iterate over the unrendered mermaid inputs, caching their source as you go + $(newDomFixed).find('pre.mermaid').each(function (index, el) { + if (el.childNodes.length === 1 && el.childNodes[0].nodeType === 3) { + var src = el.childNodes[0].wholeText; + el.setAttribute('mermaid-source', src); + mermaid_source[index] = src; + } + }); + + // iterate over rendered mermaid charts + $content.find('pre.mermaid:not([processed="true"])').each(function (index, el) { + // retrieve the attached source code which it was drawn + var src = el.getAttribute('mermaid-source'); + + // check if that source exists in the set of charts which are about to be rendered + if (mermaid_source.indexOf(src) === -1) { + // if it's not, then you can remove it + if (el.parentNode && el.parentNode.children.length) { + el.parentNode.removeChild(el); + } + } else if (el.childNodes.length === 1 && el.childNodes[0].nodeType !== 3) { + // otherwise, confirm that the content of the rendered chart is not a text node + // and keep a copy of it + mermaid_cache[src] = el.childNodes[0]; + } + }); + var oldDom = domFromHTML($content[0].outerHTML); + var patch = makeDiff(oldDom, Dom, id); if (typeof(patch) === 'string') { throw new Error(patch); @@ -348,8 +378,32 @@ define([ var target = document.getElementById($a.attr('data-href')); if (target) { target.scrollIntoView(); } }); + + // loop over mermaid elements in the rendered content + $content.find('pre.mermaid').each(function (index, el) { + // since you've simply drawn the content that was supplied via markdown + // you can assume that the index of your rendered charts matches that + // of those in the markdown source. + var src = mermaid_source[index]; + el.setAttribute('mermaid-source', src); + var cached = mermaid_cache[src]; + + // check if you had cached a pre-rendered instance of the supplied source + if (typeof(cached) !== 'object') { return; } + + // if there's a cached rendering, empty out the contained source code + // which would otherwise be drawn again. + // apparently this is the fastest way to empty out an element + while (el.firstChild) { el.removeChild(el.firstChild); } //el.innerHTML = ''; + // insert the cached graph + el.appendChild(cached); + // and set a flag indicating that this graph need not be reprocessed + el.setAttribute('data-processed', true); + }); + try { - Mermaid.init(); + // finally, draw any graphs which have changed and were thus not cached + Mermaid.init(undefined, $content.find('pre.mermaid:not([data-processed="true"])')); } catch (e) { console.error(e); } } }; From daf6482ace1ed6dcac791d42ae802f612afc1804 Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 5 Dec 2019 17:42:13 -0500 Subject: [PATCH 54/80] throttle markdown rendering in the code app --- www/code/inner.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/code/inner.js b/www/code/inner.js index 7c5e64c4f..e2ed086de 100644 --- a/www/code/inner.js +++ b/www/code/inner.js @@ -131,7 +131,7 @@ define([ if (['markdown', 'gfm'].indexOf(CodeMirror.highlightMode) === -1) { return; } if (!$previewButton.is('.cp-toolbar-button-active')) { return; } forceDrawPreview(); - }, 150); + }, 400); var previewTo; $previewButton.click(function () { From edd2274262490c3da253c4b0226c2541c1774873 Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 5 Dec 2019 17:42:37 -0500 Subject: [PATCH 55/80] add a few default styles for gantt charts --- www/code/mermaid.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/www/code/mermaid.css b/www/code/mermaid.css index 769933f0a..0802db0e0 100644 --- a/www/code/mermaid.css +++ b/www/code/mermaid.css @@ -121,6 +121,11 @@ text.actor { font-size: 11px; text-height: 14px; } +.sectionTitle, .titleText { + font-weight: bold; + text-decoration: underline; +} + /* Grid and axis */ .grid .tick { stroke: lightgrey; From 15a8054d31da3db88d65ad726471f9202f0b2a93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Fri, 6 Dec 2019 12:01:27 +0000 Subject: [PATCH 56/80] show messages when user has no contacts cases: - No contacts, logged in: show button to copy profile URL - Not logged in: show buttons to log in or register --- www/common/common-ui-elements.js | 47 +++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index eb8bb21a2..a932c586a 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1002,7 +1002,7 @@ define([ }); return { content: div, - button: shareButton + buttons: [shareButton] }; }; @@ -1125,10 +1125,42 @@ define([ var hasFriends = Object.keys(config.friends || {}).length !== 0; var onFriendShare = Util.mkEvent(); - var friendsObject = hasFriends ? createShareWithFriends(config, onFriendShare, getLinkValue) : { - content: h('p', Messages.team_noFriend), - button: {} + + var noContactsMessage = function(){ + if (common.isLoggedIn()) { + return { + content: h('p', Messages.share_noContactsLoggedIn), + buttons: [{ + className: 'primary', + name: Messages.share_copyProfileLink, + onClick: function () { + // XXX copy profile link + }, + keys: [13] + }] + } + } else { + return { + content: h('p', Messages.share_noContactsNotLoggedIn), + buttons: [{ + className: 'primary', + name: Messages.login_register, + onClick: function () { + // XXX link to register + } + }, { + className: 'primary', + name: Messages.login_login, + onClick: function () { + // XXX link to log in + } + } + ] + } + } }; + + var friendsObject = hasFriends ? createShareWithFriends(config, onFriendShare, getLinkValue) : noContactsMessage(); var friendsList = friendsObject.content; onFriendShare.reg(saveValue); @@ -1137,9 +1169,10 @@ define([ var contactsContent = h('div.cp-share-modal'); $(contactsContent).append(friendsList); - var contactButtons = [makeCancelButton(), - friendsObject.button]; - + console.log(friendsObject.content); + var contactButtons = friendsObject.buttons; + contactButtons.unshift(makeCancelButton()); + var frameContacts = UI.dialog.customModal(contactsContent, { buttons: contactButtons, onClose: config.onClose, From 3f77a800cfb1c8e4bfb3d25757ac150c9c024ae7 Mon Sep 17 00:00:00 2001 From: ansuz Date: Fri, 6 Dec 2019 09:14:33 -0500 Subject: [PATCH 57/80] revert addition of underlines to some mermaid titles --- www/code/mermaid.css | 1 - 1 file changed, 1 deletion(-) diff --git a/www/code/mermaid.css b/www/code/mermaid.css index 0802db0e0..60c366bb6 100644 --- a/www/code/mermaid.css +++ b/www/code/mermaid.css @@ -123,7 +123,6 @@ text.actor { } .sectionTitle, .titleText { font-weight: bold; - text-decoration: underline; } /* Grid and axis */ From 72a855aa6abe3ba003ca76eac7572253a7a8bc44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Fri, 6 Dec 2019 15:35:10 +0000 Subject: [PATCH 58/80] change link alert to warning --- www/common/common-ui-elements.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index fa7ae38ea..6fe865647 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1110,10 +1110,9 @@ define([ ])); } - // Show alert if user has not dismissed it in the past - linkContent.push(h('div.alert.alert-danger.dismissable', [ + linkContent.push(h('div.alert.alert-warning.dismissable', [ h('span.cp-inline-alert-text', Messages.share_linkWarning), - h('span.fa.fa-times') + h('span.fa.fa-times') // XXX dismiss message and remember ])); var link = h('div.cp-share-modal', linkContent); From 713d67439f00211bad67f37643b91c12079b263a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Fri, 6 Dec 2019 16:52:53 +0000 Subject: [PATCH 59/80] review --- .../src/less2/include/alertify.less | 6 ++-- .../src/less2/include/usergrid.less | 13 ++++----- www/common/common-ui-elements.js | 28 ++++--------------- 3 files changed, 13 insertions(+), 34 deletions(-) diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index 6692955e7..b1143ff38 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -159,8 +159,8 @@ margin-bottom: @alertify_padding-base; margin: 0; overflow: auto; - label{ - margin-bottom: 0px; + :last-child{ + margin-bottom: 0; } } .alertify-tabs { @@ -368,7 +368,6 @@ nav { padding: @alertify_padding-base; - padding-top: 0px; text-align: right; button { margin: 0px !important; @@ -521,6 +520,7 @@ overflow-x: auto; } } + // Bootstrap Alerts .alert { margin: 0px 0px @alertify_padding-base 0px; font-size: 12px; diff --git a/customize.dist/src/less2/include/usergrid.less b/customize.dist/src/less2/include/usergrid.less index f4e72591e..37c406d52 100644 --- a/customize.dist/src/less2/include/usergrid.less +++ b/customize.dist/src/less2/include/usergrid.less @@ -6,7 +6,9 @@ --LessLoader_require: LessLoader_currentFile(); }; & { + .cp-usergrid-container { + margin-bottom: 12px; // XXX add margin at bottom of user grids .cp-usergrid-grid { display: flex; flex-wrap: wrap; @@ -28,10 +30,9 @@ input { flex: 1; min-width: 0; - margin-top: 0 !important; + margin: 0; margin-bottom: 0 !important; height: 38px; - margin: 6px 0px; &::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */ color: @cryptpad_color_grey; opacity: 1; /* Firefox */ @@ -54,6 +55,7 @@ justify-content: center; align-items: center; padding: 5px; + margin: 3px; cursor: default; transition: order 0.5s, background-color 0.5s; margin-top: 1px; @@ -72,11 +74,6 @@ .cp-usergrid-user-avatar { min-height: 40px; } - &:not(.large) { - .cp-usergrid-user-name { - display: none; - } - } .cp-usergrid-user-name { overflow: hidden; @@ -89,7 +86,7 @@ } &:not(.large) { - .avatar_main(60px); + .avatar_main(40px); } &.large { .avatar_main(25px); diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 6fe865647..ccc837766 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -795,8 +795,6 @@ define([ var noOthers = icons.length === 0 ? '.cp-usergrid-empty' : ''; - var buttonSelect = h('button', Messages.share_selectAll); - var buttonDeselect = h('button', Messages.share_deselectAll); var inputFilter = h('input', { placeholder: Messages.share_filterFriend }); @@ -817,23 +815,8 @@ define([ $div.find('.cp-usergrid-user:not(.cp-selected):not([data-name*="'+name+'"])').hide(); } }; - $(inputFilter).on('keydown keyup change', redraw); - $(buttonSelect).click(function () { - $div.find('.cp-usergrid-user:not(.cp-selected):visible').addClass('cp-selected'); - onSelect(); - }); - $(buttonDeselect).click(function () { - $div.find('.cp-usergrid-user.cp-selected').removeClass('cp-selected').each(function (i, el) { - var order = $(el).attr('data-order'); - if (!order) { return; } - $(el).attr('style', 'order:'+order); - }); - redraw(); - onSelect(); - }); - $(div).append(h('div.cp-usergrid-grid', icons)); if (!config.noSelect) { $div.on('click', '.cp-usergrid-user', function () { @@ -1035,7 +1018,7 @@ define([ var makeFaqLink = function () { var link = h('span', [ - h('i.fa.fa-question-circle'), ' ', + h('i.fa.fa-question-circle'), ' ', // XXX remove and make it a margin h('a', {href: '#'}, Messages.passwordFaqLink) ]); $(link).click(function () { @@ -1098,13 +1081,13 @@ define([ ] : [ UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }), ]; - linkContent.push(h('div.cp-spacer')) + linkContent.push(h('div.cp-spacer')); linkContent.push(UI.dialog.selectableArea('', { id: 'cp-share-link-preview', tabindex: 1, rows:3})); // Show alert if the pad is password protected if (hasPassword) { linkContent.push(h('div.alert.alert-primary', [ - h('i.fa.fa-lock'), ' ', + h('i.fa.fa-lock'), ' ', // XXX remove and make it a margin Messages.share_linkPasswordAlert, h('br'), makeFaqLink() ])); @@ -1187,7 +1170,7 @@ define([ // Show alert if the pad is password protected if (hasPassword) { $contactsContent.append(h('div.alert.alert-primary', [ - h('i.fa.fa-unlock'), ' ', + h('i.fa.fa-unlock'), ' ', // XXX remove and make it a margin Messages.share_contactPasswordAlert, h('br'), makeFaqLink() ])); @@ -1317,6 +1300,7 @@ define([ return modal; }; + // XXX add password messages to file share UIElements.createFileShareModal = function (config) { var origin = config.origin; var pathname = config.pathname; @@ -1387,10 +1371,8 @@ define([ // Embed tab var embed = h('div.cp-share-modal', [ h('p', Messages.fileEmbedScript), - h('br'), UI.dialog.selectable(common.getMediatagScript()), h('p', Messages.fileEmbedTag), - h('br'), UI.dialog.selectable(common.getMediatagFromHref(fileData)), ]); var embedButtons = [{ From 9b5c3878b16963e82f03344bcad2932d763a42d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Mon, 9 Dec 2019 09:57:41 +0000 Subject: [PATCH 60/80] add password messages to file share modal --- www/common/common-ui-elements.js | 53 ++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index ccc837766..e9dc55471 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1311,6 +1311,21 @@ define([ if (!hashes.fileHash) { throw new Error("You must provide a file hash"); } var url = origin + pathname + '#' + hashes.fileHash; + // check if the file is password protected + var parsedHref = Hash.parsePadUrl(url); + var hasPassword = parsedHref.hashData.password; + + var makeFaqLink = function () { + var link = h('span', [ + h('i.fa.fa-question-circle'), ' ', // XXX remove and make it a margin + h('a', {href: '#'}, Messages.passwordFaqLink) + ]); + $(link).click(function () { + common.openURL(config.origin + "/faq.html#security-pad_password"); + }); + return link; + }; + var getLinkValue = function () { return url; }; var makeCancelButton = function() { @@ -1322,9 +1337,23 @@ define([ // Share link tab var linkContent = [ - UI.dialog.selectable(getLinkValue(), { id: 'cp-share-link-preview', tabindex: 1 }) + UI.dialog.selectableArea(getLinkValue(), { id: 'cp-share-link-preview', tabindex: 1, rows:2 }) ]; + // Show alert if the pad is password protected + if (hasPassword) { + linkContent.push(h('div.alert.alert-primary', [ + h('i.fa.fa-lock'), ' ', // XXX remove and make it a margin + Messages.share_linkPasswordAlert, h('br'), + makeFaqLink() + ])); + } + + linkContent.push(h('div.alert.alert-warning.dismissable', [ + h('span.cp-inline-alert-text', Messages.share_linkWarning), + h('span.fa.fa-times') // XXX dismiss message and remember + ])); + var link = h('div.cp-share-modal', linkContent); var linkButtons = [ @@ -1357,7 +1386,17 @@ define([ var friendsList = friendsObject.content; var contactsContent = h('div.cp-share-modal'); - $(contactsContent).append(friendsList); + var $contactsContent = $(contactsContent); + $contactsContent.append(friendsList); + + // Show alert if the pad is password protected + if (hasPassword) { + $contactsContent.append(h('div.alert.alert-primary', [ + h('i.fa.fa-unlock'), ' ', // XXX remove and make it a margin + Messages.share_contactPasswordAlert, h('br'), + makeFaqLink() + ])); + } var contactButtons = [makeCancelButton(), friendsObject.button]; @@ -1375,6 +1414,16 @@ define([ h('p', Messages.fileEmbedTag), UI.dialog.selectable(common.getMediatagFromHref(fileData)), ]); + + // Show alert if the pad is password protected + if (hasPassword) { + embed.append(h('div.alert.alert-primary', [ + h('i.fa.fa-lock'), ' ', + Messages.share_embedPasswordAlert, h('br'), + makeFaqLink() + ])); + } + var embedButtons = [{ className: 'cancel', name: Messages.cancel, From be40254f1aa79036b0631da082af3da43563efcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Mon, 9 Dec 2019 10:02:44 +0000 Subject: [PATCH 61/80] remove spaces in password messages - space between icon and text is now a margin --- www/common/common-ui-elements.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index e9dc55471..9338471a7 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1018,7 +1018,7 @@ define([ var makeFaqLink = function () { var link = h('span', [ - h('i.fa.fa-question-circle'), ' ', // XXX remove and make it a margin + h('i.fa.fa-question-circle'), h('a', {href: '#'}, Messages.passwordFaqLink) ]); $(link).click(function () { @@ -1033,7 +1033,6 @@ define([ var rights = h('div.msg.cp-inline-radio-group', [ h('label', Messages.share_linkAccess), - h('br'), h('div.radio-group',[ UI.createRadio('accessRights', 'cp-share-editable-false', Messages.share_linkView, true, { mark: {tabindex:1} }), @@ -1087,7 +1086,7 @@ define([ // Show alert if the pad is password protected if (hasPassword) { linkContent.push(h('div.alert.alert-primary', [ - h('i.fa.fa-lock'), ' ', // XXX remove and make it a margin + h('i.fa.fa-lock'), Messages.share_linkPasswordAlert, h('br'), makeFaqLink() ])); @@ -1170,7 +1169,7 @@ define([ // Show alert if the pad is password protected if (hasPassword) { $contactsContent.append(h('div.alert.alert-primary', [ - h('i.fa.fa-unlock'), ' ', // XXX remove and make it a margin + h('i.fa.fa-unlock'), Messages.share_contactPasswordAlert, h('br'), makeFaqLink() ])); @@ -1300,7 +1299,6 @@ define([ return modal; }; - // XXX add password messages to file share UIElements.createFileShareModal = function (config) { var origin = config.origin; var pathname = config.pathname; @@ -1317,7 +1315,7 @@ define([ var makeFaqLink = function () { var link = h('span', [ - h('i.fa.fa-question-circle'), ' ', // XXX remove and make it a margin + h('i.fa.fa-question-circle'), h('a', {href: '#'}, Messages.passwordFaqLink) ]); $(link).click(function () { @@ -1343,7 +1341,7 @@ define([ // Show alert if the pad is password protected if (hasPassword) { linkContent.push(h('div.alert.alert-primary', [ - h('i.fa.fa-lock'), ' ', // XXX remove and make it a margin + h('i.fa.fa-lock'), Messages.share_linkPasswordAlert, h('br'), makeFaqLink() ])); @@ -1392,7 +1390,7 @@ define([ // Show alert if the pad is password protected if (hasPassword) { $contactsContent.append(h('div.alert.alert-primary', [ - h('i.fa.fa-unlock'), ' ', // XXX remove and make it a margin + h('i.fa.fa-unlock'), Messages.share_contactPasswordAlert, h('br'), makeFaqLink() ])); From b558d6e35462a1fbf7a542b3cf7d4a599761eb7f Mon Sep 17 00:00:00 2001 From: yflory Date: Mon, 9 Dec 2019 11:03:11 +0100 Subject: [PATCH 62/80] Fix null item in kanban --- www/kanban/inner.js | 2 +- www/kanban/jkanban.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/www/kanban/inner.js b/www/kanban/inner.js index c2d845557..035794b2a 100644 --- a/www/kanban/inner.js +++ b/www/kanban/inner.js @@ -286,7 +286,7 @@ define([ kanban.inEditMode = true; // create a form to enter element var boardId = $(el.parentNode.parentNode).attr("data-id"); - var $item = $('
', {'class': 'kanban-item'}); + var $item = $('
', {'class': 'kanban-item new-item'}); var $input = getInput().val(name).appendTo($item); kanban.addForm(boardId, $item[0]); $input.focus(); diff --git a/www/kanban/jkanban.js b/www/kanban/jkanban.js index 5ef939f1b..f1f70955a 100644 --- a/www/kanban/jkanban.js +++ b/www/kanban/jkanban.js @@ -147,9 +147,13 @@ self.drake = self.dragula(self.boardContainer, { moves: function (el, source, handle, sibling) { if (self.options.readOnly) { return false; } + if (el.classList.contains('new-item')) { return false; } return handle.classList.contains('kanban-item'); }, accepts: function (el, target, source, sibling) { + if (sibling === null) { + return false; + } if (self.options.readOnly) { return false; } return true; }, From df9f2c9c293af7343b7f547132d4f82b5771b5f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Mon, 9 Dec 2019 11:14:05 +0000 Subject: [PATCH 63/80] dismiss warning about sharing links - remember if warning has been dismissed - include this in tips that can be reset - move the option to reset tips to the account settings --- www/common/common-ui-elements.js | 52 +++++++++++++++++++++++++++----- www/settings/inner.js | 4 +-- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 9338471a7..46befaac2 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1092,10 +1092,29 @@ define([ ])); } - linkContent.push(h('div.alert.alert-warning.dismissable', [ - h('span.cp-inline-alert-text', Messages.share_linkWarning), - h('span.fa.fa-times') // XXX dismiss message and remember - ])); + // warning about sharing links + var localStore = window.cryptpadStore; + var dismissButton = h('span.fa.fa-times'); + var shareLinkWarning = h('div.alert.alert-warning.dismissable', + { style: 'display: none;' }, + [ + h('span.cp-inline-alert-text', Messages.share_linkWarning), + dismissButton + ]); + linkContent.push(shareLinkWarning); + + localStore.get('hide-alert-shareLinkWarning', function (val) { + if (val === '1') { return; } + $(shareLinkWarning).show(); + + $(dismissButton).on('click', function () { + localStore.put('hide-alert-shareLinkWarning', '1'); + $(shareLinkWarning).remove(); + }); + + }); + + var link = h('div.cp-share-modal', linkContent); var $link = $(link); @@ -1347,10 +1366,27 @@ define([ ])); } - linkContent.push(h('div.alert.alert-warning.dismissable', [ - h('span.cp-inline-alert-text', Messages.share_linkWarning), - h('span.fa.fa-times') // XXX dismiss message and remember - ])); + // warning about sharing links + var localStore = window.cryptpadStore; + var dismissButton = h('span.fa.fa-times'); + var shareLinkWarning = h('div.alert.alert-warning.dismissable', + { style: 'display: none;' }, + [ + h('span.cp-inline-alert-text', Messages.share_linkWarning), + dismissButton + ]); + linkContent.push(shareLinkWarning); + + localStore.get('hide-alert-shareLinkWarning', function (val) { + if (val === '1') { return; } + $(shareLinkWarning).show(); + + $(dismissButton).on('click', function () { + localStore.put('hide-alert-shareLinkWarning', '1'); + $(shareLinkWarning).remove(); + }); + + }); var link = h('div.cp-share-modal', linkContent); diff --git a/www/settings/inner.js b/www/settings/inner.js index d67f62818..7c9dd0630 100644 --- a/www/settings/inner.js +++ b/www/settings/inner.js @@ -51,6 +51,7 @@ define([ 'cp-settings-info-block', 'cp-settings-displayname', 'cp-settings-language-selector', + 'cp-settings-resettips', 'cp-settings-logout-everywhere', 'cp-settings-autostore', 'cp-settings-userfeedback', @@ -67,7 +68,6 @@ define([ ], 'drive': [ 'cp-settings-drive-duplicate', - 'cp-settings-resettips', 'cp-settings-thumbnails', 'cp-settings-drive-backup', 'cp-settings-drive-import-local', @@ -835,7 +835,7 @@ define([ var localStore = window.cryptpadStore; $button.click(function () { Object.keys(localStore.store).forEach(function (k) { - if(k.slice(0, 9) === "hide-info") { + if(/^(hide-(info|alert))/.test(k)) { localStore.put(k, null); } }); From e9c0e1a71057974ff2239dd7c546800b07369e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Mon, 9 Dec 2019 11:15:52 +0000 Subject: [PATCH 64/80] icon spacing --- customize.dist/src/less2/include/alertify.less | 3 +++ 1 file changed, 3 insertions(+) diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index b1143ff38..96a8ae506 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -526,6 +526,9 @@ font-size: 12px; padding: 5px; border-radius: 0px; + i { + margin-right: 10px; + } &.alert-primary { background-color: @alertify-base; color: @alertify-fg; From f04d4e1010e1ba9f4275d6b3be9e6a5f2e3e1955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Mon, 9 Dec 2019 11:34:00 +0000 Subject: [PATCH 65/80] adjust spacing of usergrid --- customize.dist/src/less2/include/usergrid.less | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/customize.dist/src/less2/include/usergrid.less b/customize.dist/src/less2/include/usergrid.less index 37c406d52..a171b0950 100644 --- a/customize.dist/src/less2/include/usergrid.less +++ b/customize.dist/src/less2/include/usergrid.less @@ -8,7 +8,7 @@ & { .cp-usergrid-container { - margin-bottom: 12px; // XXX add margin at bottom of user grids + margin-bottom: 12px !important; // even when last child of .msg .cp-usergrid-grid { display: flex; flex-wrap: wrap; @@ -100,6 +100,7 @@ .cp-usergrid-user-name { margin-left: 5px; text-align: left; + line-height: 150%; color: @cryptpad_text_col; } } From bc593132381f3fe0d51bf19ed9a0870929f83bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Mon, 9 Dec 2019 11:37:20 +0000 Subject: [PATCH 66/80] lint --- customize.dist/src/less2/include/alertify.less | 4 ++-- customize.dist/src/less2/include/modals-ui-elements.less | 2 +- customize.dist/src/less2/include/usergrid.less | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index 96a8ae506..4bd5e298b 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -159,7 +159,7 @@ margin-bottom: @alertify_padding-base; margin: 0; overflow: auto; - :last-child{ + :last-child { margin-bottom: 0; } } @@ -520,7 +520,7 @@ overflow-x: auto; } } - // Bootstrap Alerts + // Bootstrap Alerts .alert { margin: 0px 0px @alertify_padding-base 0px; font-size: 12px; diff --git a/customize.dist/src/less2/include/modals-ui-elements.less b/customize.dist/src/less2/include/modals-ui-elements.less index 1d91767ba..21707eab8 100644 --- a/customize.dist/src/less2/include/modals-ui-elements.less +++ b/customize.dist/src/less2/include/modals-ui-elements.less @@ -4,7 +4,7 @@ --LessLoader_require: LessLoader_currentFile(); } & { - .cp-spacer{ + .cp-spacer { height: @variables_padding; } // Share modal diff --git a/customize.dist/src/less2/include/usergrid.less b/customize.dist/src/less2/include/usergrid.less index a171b0950..6ba8c2d07 100644 --- a/customize.dist/src/less2/include/usergrid.less +++ b/customize.dist/src/less2/include/usergrid.less @@ -6,7 +6,7 @@ --LessLoader_require: LessLoader_currentFile(); }; & { - + .cp-usergrid-container { margin-bottom: 12px !important; // even when last child of .msg .cp-usergrid-grid { From e8b2c5c4e8db3701335f90db4c93ca75a5e465bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Mon, 9 Dec 2019 14:01:15 +0000 Subject: [PATCH 67/80] use secondary buttons --- www/common/common-ui-elements.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index a932c586a..3a1402f6c 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1131,7 +1131,7 @@ define([ return { content: h('p', Messages.share_noContactsLoggedIn), buttons: [{ - className: 'primary', + className: 'secondary', name: Messages.share_copyProfileLink, onClick: function () { // XXX copy profile link @@ -1143,13 +1143,13 @@ define([ return { content: h('p', Messages.share_noContactsNotLoggedIn), buttons: [{ - className: 'primary', + className: 'secondary', name: Messages.login_register, onClick: function () { // XXX link to register } }, { - className: 'primary', + className: 'secondary', name: Messages.login_login, onClick: function () { // XXX link to log in @@ -1169,7 +1169,6 @@ define([ var contactsContent = h('div.cp-share-modal'); $(contactsContent).append(friendsList); - console.log(friendsObject.content); var contactButtons = friendsObject.buttons; contactButtons.unshift(makeCancelButton()); From 73a03e8d8051ad4ad727397980f52bd2a4e0c0aa Mon Sep 17 00:00:00 2001 From: yflory Date: Mon, 9 Dec 2019 15:04:58 +0100 Subject: [PATCH 68/80] Fix getFullHistory and getHistory errors --- www/common/outer/async-store.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index 15444f77b..c5b6f6a42 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -1708,6 +1708,7 @@ define([ var onMsg = function (msg) { if (completed) { return; } var parsed = parse(msg); + if (!parsed) { return; } if (parsed[0] === 'FULL_HISTORY_END') { cb(msgs); network.off('message', onMsg); @@ -1748,6 +1749,7 @@ define([ if (completed) { return; } if (sender !== hk) { return; } var parsed = parse(msg); + if (!parsed) { return; } // Ignore the metadata message if (parsed.validateKey && parsed.channel) { return; } From 1f48ee36efa196f2fe8bdde3142d1d3a3f034bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Mon, 9 Dec 2019 14:15:38 +0000 Subject: [PATCH 69/80] linting --- www/common/common-ui-elements.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 3a1402f6c..fd2955e56 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1138,7 +1138,7 @@ define([ }, keys: [13] }] - } + }; } else { return { content: h('p', Messages.share_noContactsNotLoggedIn), @@ -1156,7 +1156,7 @@ define([ } } ] - } + }; } }; From 111141628c51147e1ba27d29e029c136ea14ff73 Mon Sep 17 00:00:00 2001 From: yflory Date: Mon, 9 Dec 2019 16:02:24 +0100 Subject: [PATCH 70/80] lint compliance --- www/common/cryptpad-common.js | 7 +++---- www/common/outer/onlyoffice.js | 3 ++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index 3a96ad202..40db70457 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -1155,7 +1155,8 @@ define([ }); }; - common.changeOOPassword = function (data, cb) { + common.changeOOPassword = function (data, _cb) { + var cb = Util.once(Util.mkAsync(_cb)); var href = data.href; var newPassword = data.password; var teamId = data.teamId; @@ -1166,7 +1167,6 @@ define([ var warning = false; var newHash, newRoHref; - var oldChannel; var oldSecret; var oldMetadata; var oldRtChannel; @@ -1186,7 +1186,6 @@ define([ var Crypt, Crypto; var cryptgetVal; - var lastCp; var optsPut = { password: newPassword, metadata: { @@ -1298,7 +1297,7 @@ define([ return void cb(obj.error); } var msgs = obj; - newHistory = msgs.map(function (str) { + var newHistory = msgs.map(function (str) { try { var d = oldCrypto.decrypt(str, true, true); return newCrypto.encrypt(d); diff --git a/www/common/outer/onlyoffice.js b/www/common/outer/onlyoffice.js index cb88596aa..9c1863bc6 100644 --- a/www/common/outer/onlyoffice.js +++ b/www/common/outer/onlyoffice.js @@ -220,8 +220,9 @@ define([ ctx.store.anon_rpc.send("IS_NEW_CHANNEL", channel, function (e, response) { if (e) { return void cb({error: e}); } + var isNew; if (response && response.length && typeof(response[0]) === 'boolean') { - var isNew = response[0]; + isNew = response[0]; } else { cb({error: 'INVALID_RESPONSE'}); } From 06f46129fcf8d101db268db41116f5199fe5c7df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Mon, 9 Dec 2019 16:16:13 +0000 Subject: [PATCH 71/80] add functionality to buttons for no contacts --- www/common/common-ui-elements.js | 87 +++++++++++++++++-------------- www/common/sframe-common-outer.js | 10 ++-- 2 files changed, 52 insertions(+), 45 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index fd2955e56..e7d107e36 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1006,6 +1006,49 @@ define([ }; }; + var noContactsMessage = function(common){ + var metadataMgr = common.getMetadataMgr(); + var data = metadataMgr.getUserData(); + var origin = metadataMgr.getPrivateData().origin; + if (common.isLoggedIn()) { + return { + content: h('p', Messages.share_noContactsLoggedIn), + buttons: [{ + className: 'secondary', + name: Messages.share_copyProfileLink, + onClick: function () { + var profile = data.profile ? (origin + '/profile/#' + data.profile) : ''; + var success = Clipboard.copy(profile); + if (success) { UI.log(Messages.shareSuccess); } + }, + keys: [13] + }] + }; + } else { + return { + content: h('p', Messages.share_noContactsNotLoggedIn), + buttons: [{ + className: 'secondary', + name: Messages.login_register, + onClick: function () { + common.setLoginRedirect(function () { + common.openURL('/login/'); + }); + } + }, { + className: 'secondary', + name: Messages.login_login, + onClick: function () { + common.setLoginRedirect(function () { + common.openURL('/register/'); + }); + } + } + ] + }; + } + }; + UIElements.createShareModal = function (config) { var origin = config.origin; var pathname = config.pathname; @@ -1126,41 +1169,8 @@ define([ var hasFriends = Object.keys(config.friends || {}).length !== 0; var onFriendShare = Util.mkEvent(); - var noContactsMessage = function(){ - if (common.isLoggedIn()) { - return { - content: h('p', Messages.share_noContactsLoggedIn), - buttons: [{ - className: 'secondary', - name: Messages.share_copyProfileLink, - onClick: function () { - // XXX copy profile link - }, - keys: [13] - }] - }; - } else { - return { - content: h('p', Messages.share_noContactsNotLoggedIn), - buttons: [{ - className: 'secondary', - name: Messages.login_register, - onClick: function () { - // XXX link to register - } - }, { - className: 'secondary', - name: Messages.login_login, - onClick: function () { - // XXX link to log in - } - } - ] - }; - } - }; - var friendsObject = hasFriends ? createShareWithFriends(config, onFriendShare, getLinkValue) : noContactsMessage(); + var friendsObject = hasFriends ? createShareWithFriends(config, onFriendShare, getLinkValue) : noContactsMessage(common); var friendsList = friendsObject.content; onFriendShare.reg(saveValue); @@ -1332,17 +1342,14 @@ define([ // share with contacts tab var hasFriends = Object.keys(config.friends || {}).length !== 0; - var friendsObject = hasFriends ? createShareWithFriends(config, null, getLinkValue) : { - content: h('p', Messages.share_noContacts), - button: {} - }; + var friendsObject = hasFriends ? createShareWithFriends(config, null, getLinkValue) : noContactsMessage(common); var friendsList = friendsObject.content; var contactsContent = h('div.cp-share-modal'); $(contactsContent).append(friendsList); - var contactButtons = [makeCancelButton(), - friendsObject.button]; + var contactButtons = friendsObject.buttons; + contactButtons.unshift(makeCancelButton()); var frameContacts = UI.dialog.customModal(contactsContent, { buttons: contactButtons, diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index e439d04c1..0aa79cfd1 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -484,6 +484,11 @@ define([ Cryptpad.mailbox.execCommand(data, cb); }); + sframeChan.on('Q_SET_LOGIN_REDIRECT', function (data, cb) { + sessionStorage.redirectTo = window.location.href; + cb(); + }); + sframeChan.on('Q_STORE_IN_TEAM', function (data, cb) { Cryptpad.storeInTeam(data, cb); }); @@ -634,11 +639,6 @@ define([ Notifier.notify(data); }); - sframeChan.on('Q_SET_LOGIN_REDIRECT', function (data, cb) { - sessionStorage.redirectTo = window.location.href; - cb(); - }); - sframeChan.on('Q_MOVE_TO_TRASH', function (data, cb) { cb = cb || $.noop; if (readOnly && hashes.editHash) { From 516181acf21a995f2ca851a699e00394833ad99e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Mon, 9 Dec 2019 16:21:48 +0000 Subject: [PATCH 72/80] fix buttons for no contacts --- www/common/common-ui-elements.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index fb60f2751..2596ea82c 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1030,7 +1030,7 @@ define([ name: Messages.login_register, onClick: function () { common.setLoginRedirect(function () { - common.openURL('/login/'); + common.gotoURL('/register/'); }); } }, { @@ -1038,7 +1038,7 @@ define([ name: Messages.login_login, onClick: function () { common.setLoginRedirect(function () { - common.openURL('/register/'); + common.gotoURL('/login/'); }); } } From 294fb5acb5c59be58c65964c70d52e06dee7f897 Mon Sep 17 00:00:00 2001 From: ansuz Date: Mon, 9 Dec 2019 11:24:47 -0500 Subject: [PATCH 73/80] update version string --- customize.dist/pages.js | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/customize.dist/pages.js b/customize.dist/pages.js index b4cc4a0a4..0bb596ec8 100644 --- a/customize.dist/pages.js +++ b/customize.dist/pages.js @@ -103,7 +103,7 @@ define([ ])*/ ]) ]), - h('div.cp-version-footer', "CryptPad v3.6.0 (GoldenFrog)") + h('div.cp-version-footer', "CryptPad v3.7.0 (HimalayanQuail)") ]); }; diff --git a/package-lock.json b/package-lock.json index ac23d00fa..6643e22c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "cryptpad", - "version": "3.6.0", + "version": "3.7.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a84f9ef6c..ea1431153 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "cryptpad", "description": "realtime collaborative visual editor with zero knowlege server", - "version": "3.6.0", + "version": "3.7.0", "license": "AGPL-3.0+", "repository": { "type": "git", From af59f4c2c27289ed0bcf8a068ac3841926fe2c1e Mon Sep 17 00:00:00 2001 From: ansuz Date: Mon, 9 Dec 2019 18:30:23 -0500 Subject: [PATCH 74/80] guard against invoking a method of an undefined attribute, resulting in a memory puddle --- storage/file.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/storage/file.js b/storage/file.js index 0f97527ca..402982f6b 100644 --- a/storage/file.js +++ b/storage/file.js @@ -102,7 +102,9 @@ var getMetadataAtPath = function (Env, path, _cb) { var closeChannel = function (env, channelName, cb) { if (!env.channels[channelName]) { return void cb(); } try { - env.channels[channelName].writeStream.close(); + if (typeof(Util.find(env, [ 'channels', channelName, 'writeStream', 'close'])) === 'function') { + env.channels[channelName].writeStream.close(); + } delete env.channels[channelName]; env.openFiles--; cb(); From 3f71169fada18005d7eeca39e8f57fa6136a5719 Mon Sep 17 00:00:00 2001 From: ansuz Date: Mon, 9 Dec 2019 18:30:55 -0500 Subject: [PATCH 75/80] update changelog for HimalayanQuail --- CHANGELOG.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4f63651f..a056e5d56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,50 @@ +# HimalayanQuail (3.7.0) + +## Goals + +As we are getting closer to the end of our CryptPad Teams project we planned to spend this release addressing some of the difficulties that users have reported regarding the usage of our newer social features. + +## Update notes + +This release includes an upgrade to a newer version of JQuery which mitigates a minor vulnerability which could have contributed to the presence of an XSS attack. We weren't using the affected methods in the library, but there's no harm in updating as it will protect against the vulnerability affecting user data in the future. + +We've also made some non-critical fixes to the server code, so you'll need to restart after pulling the latest code to take advantage of these improvements. + +Update to 3.7.0 from 3.6.0 using the normal update procedure: + +1. stop your server +2. pull the latest code via git +3. run `bower update` +4. restart your server + +If you're using an up-to-date version of NPM you should find that running `npm update` prints a notice that one of the packages you've installed is seeking funding. Entering `npm fund` will print information about our OpenCollective funding campaign. If you're running a slightly older version of NPM and you wish to support CryptPad's development you can do so by visiting https://opencollective.com/cryptpad . + +## Features + +* Many users have contacted us via support tickets to ask how to add contacts on the platform. The easiest way is to share the link to your profile page. Once on that page registered users will be able to send a contact request which will appear in your notification tray. Because we believe you shouldn't have to read a manual to use CryptPad (and because we want to minimize how much time we spend answering support tickets) we've integrated this tip into the UI itself. Users that don't have any contacts on the platform will hopefully notice that the sharing menu's contacts tab now prompts them with this information, followed by a button to copy their profile page's URL to their clipboard. +* We've made a lot of other small changes that we hope will have a big impact on the usability of the sharing menu: + * the "Link" section of the modal which includes the URL generated from your chosen access rights has been restyled so that the URL is displayed in a multiline textarea so that users can better see the URL changing as they play with the other controls + * both the "Contacts" and "Link" section include short, unintrusive hints about how passwords interact with the different sharing methods: + * when sharing via a URL we indicate that the recipient will need to enter a password, allowing for the URL to be sent over an insecure channel without leaking your document's content + * when sharing directly with a contact via their encrypted mailbox the password is transferred automatically, since it is assumed that you intend for the recipient to gain access and the platform provides a secure channel through which all the relevant information can be delivered + * this information is only included in cases when the document is protected with a password to limit the amount of information the user has to process to complete their task + * we include brief and dismissable warning within the menu which indicates that URLs provide non-revocable access to documents so that new users of the platform understand the consequences of sharing + * in general we've tried to make the appearance of the modal more appealing and intuitive so that users naturally discover and adopt the workflows which are the most conducive to their privacy and security +* Our premium accounts platform authenticates that you are logged in on a given CryptPad instance by loading it in an iframe and requesting that it use one of your account's cryptographic keys to sign a message. Unfortunately, this process could be quite slow as it would load your CryptDrive and other information related to account, and some users reported that their browser timed out on this process. We've addressed this by loading only the account information required to prove your identity. +* We've also included some changes to CryptPad's server to allow users to share quotas between multiple accounts, though we still have work to do to make this behaviour functional on the web client. +* Spreadsheets now support password change! +* Kanban boards now render long column titles in a much more intuitive way, wrapping the text instead of truncating it. +* Our code editor now features support for Gantt charts in markdown mode via an improved Mermaidjs integration. We've also slowed down the rendering cycle so that updates are displayed once you stop typing for 400ms instead of 150ms, and improved the rendering methods so that all mermaid-generated charts are only redrawn if they have changed since the last time they were rendered. This results in a smoother reading experience while permitting other users to continue to edit the document. +* Finally, after a review of the code responsible for sanitizing the markdown code which we render as HTML, we've decided to remove SVG tags from our sanitizer's filter. This means that you can write SVG markup in the input field and see it rendered, in case you're into that kind of thing. + +## Bug fixes + +* It seems our "contacts" app broke along with the 3.5.0 release and nobody reported it. The regression was introduced when we made some changes to the teams chat integration. We've addressed the issue so that you can once again use the contacts app to chat directly with friends. +* We've found and fixed a "memory puddle" (a non-critical memory leak which was automatically mopped up every now and then). The fix probably won't have much noticeable impact but the server is now a little bit more correct +* We stumbled across a bug which wiped out the contents of a Kanban board and caused the application to crash if you navigated to the affected version of the document in history mode. If you notice that one of your documents was affected please contact us and we'll write a guide instructing you how to recover your content. +* We've found a few bugs lurking in our server which could have caused the amount of data stored in users' drives to be calculated incorrectly under very unlikely circumstances. We've fixed the issue and addressed a number of similar asynchrony-related code paths which should mitigate similar issues in the future. +* Lastly, we spotted some flaws in the code responsible for encrypting pad credentials in shared folders and teams such that viewers don't automatically gain access to the editing keys of a document when they should only have view access. There weren't any access control vulnerabilities, but an error was thrown under rare circumstances which could prevent affected users' drives from loading. We've guarded against the cause and made it such that any affected users will automatically repair their damaged drives. + # GoldenFrog release (3.6.0) ## Goals From bc8f6fd6839906fc72a6c50cc2b5c352da6736bc Mon Sep 17 00:00:00 2001 From: Weblate Date: Tue, 10 Dec 2019 10:07:36 +0000 Subject: [PATCH 76/80] Translated using Weblate (English) Currently translated at 100.0% (1155 of 1155 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/ Translated using Weblate (English) Currently translated at 100.0% (1154 of 1154 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/ Translated using Weblate (English) Currently translated at 100.0% (1153 of 1153 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/ Translated using Weblate (English) Currently translated at 100.0% (1152 of 1152 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/ Translated using Weblate (English) Currently translated at 100.0% (1151 of 1151 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/ Translated using Weblate (English) Currently translated at 100.0% (1151 of 1151 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/ Translated using Weblate (English) Currently translated at 100.0% (1150 of 1150 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/ Translated using Weblate (English) Currently translated at 100.0% (1149 of 1149 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/ Translated using Weblate (English) Currently translated at 100.0% (1148 of 1148 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/en/ --- www/common/translations/messages.json | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/www/common/translations/messages.json b/www/common/translations/messages.json index 3c2e39e5b..88fdc832b 100644 --- a/www/common/translations/messages.json +++ b/www/common/translations/messages.json @@ -779,6 +779,10 @@ "crypto": { "q": "What cryptography do you use?", "a": "CryptPad is based upon two open-source cryptography libraries: tweetnacl.js and scrypt-async.js.

Scrypt is a password-based key derivation algorithm. We use it to turn your username and password into a unique keyring which secures access to your CryptDrive such that only you can access your list of pads.

We use the xsalsa20-poly1305 and x25519-xsalsa20-poly1305 cyphers provided by tweetnacl to encrypt pads and chat history, respectively." + }, + "pad_password": { + "q": "What happens when I protect a pad/folder with a password?", + "a": "You can protect any pad or shared folder with a password when you create it. You can also use the properties menu to set/change/remove a password at any time.

Pad and shared folder passwords are intended to protect the link when you share it over potentially insecure channels such as email or text message. If someone intercepts your link but does not have the password they will not be able to read your document.

When sharing within CryptPad with your contacts or teams, communications are encrypted and we assume you want them to access your document. Therefore the password is remembered and sent with the pad when you share it. The recipient, or yourself, are not asked for it when they open the document." } }, "usability": { @@ -1164,7 +1168,7 @@ "owner_request_declined": "{0} has declined your offer to be an owner of {1}", "owner_removed": "{0} has removed your ownership of {1}", "owner_removedPending": "{0} has canceled your ownership offer for {1}", - "share_linkTeam": "Share with a team", + "share_linkTeam": "Add to team drive", "team_pickFriends": "Choose which friends to invite to this team", "team_inviteModalButton": "Invite", "team_noFriend": "You haven't connected with any friends on CryptPad yet.", @@ -1242,5 +1246,10 @@ "teams_table_admins": "Manage members", "teams_table_owners": "Manage team", "teams_table_role": "Role", - "pad_wordCount": "Words: {0}" + "pad_wordCount": "Words: {0}", + "share_linkWarning": "This link contains the keys to your document. Recipients will gain non-revokable access to your content.", + "share_linkPasswordAlert": "This item is password protected. When you send the link the recipient will have to enter the password.", + "share_contactPasswordAlert": "This item is password protected. Because you are sharing it with a CryptPad contact, the recipient will not have to enter the password.", + "share_embedPasswordAlert": "This item is password protected. When you embed this pad, viewers will be asked for the password.", + "passwordFaqLink": "Read more about passwords" } From 9743ea6e06fa0f77c5576b42a2e79041d83e123d Mon Sep 17 00:00:00 2001 From: Weblate Date: Tue, 10 Dec 2019 10:07:36 +0000 Subject: [PATCH 77/80] Translated using Weblate (French) Currently translated at 100.0% (1155 of 1155 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/fr/ --- www/common/translations/messages.fr.json | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/www/common/translations/messages.fr.json b/www/common/translations/messages.fr.json index b39e76785..90f5d75a0 100644 --- a/www/common/translations/messages.fr.json +++ b/www/common/translations/messages.fr.json @@ -761,6 +761,10 @@ "crypto": { "q": "Quelle cryptographie utilisez-vous ?", "a": "CryptPad est basé sur deux librairies open-source de cryptographie : tweetnacl.js et scrypt-async.js.
Scrypt est une fonction de dérivation de clé basée sur un mot de passe. Nous l'utilisons pour transformer votre nom d'utilisateur et votre mot de passe en un unique ensemble de clés qui sécurise l'accès à votre CryptDrive afin que vous seul puissiez accéder à votre liste de pads.
Nous utilisons les outils de chiffrement xsalsa20-poly1305 et x25519-xsalsa20-poly1305 fournis par tweetnacl pour chiffrer vos pads et l'historique du chat respectivement." + }, + "pad_password": { + "q": "Que se passe t'il quand je protège un pad/dossier avec un mot de passe ?", + "a": "Vous pouvez protéger tout nouveau pad ou dossier avec un mot de passe. Vous pouvez aussi utiliser le menu propriétés pour ajouter/changer/supprimer un mot de passe par la suite.

Les mots de passe sur les pads et dossiers partagés sont faits pour protéger les liens quand ils sont envoyés de manière non sécurisée (par exemple par email ou SMS). Si quelqu'un intercepte le lien sans avoir le mot de passe, ils n'auront pas accès à votre document.

Quand vous partagez avec vos contacts ou équipes sur CryptPad, les communications sont chiffrées et nous partons du principe que vous voulez donner l'accès. C'est pourquoi le mot de passe est alors stocké et envoyé avec le pad quand vous l'envoyez. Les destinataires, ou vous même, n'ont pas a le donner pour ouvrir le document." } }, "usability": { @@ -1162,7 +1166,7 @@ "owner_removed": "{0} a supprimé vos droits de propriétaire de {1}", "owner_removedPending": "{0} a annulé l'offre de co-propriété reçue pour {1}", "padNotPinnedVariable": "Ce pad va expirer après {4} jours d'inactivité, {0}connectez-vous{1} ou {2}enregistrez-vous{3} pour le préserver.", - "share_linkTeam": "Partager avec une équipe", + "share_linkTeam": "Ajouter au CryptDrive d'une équipe", "team_pickFriends": "Choisissez les amis à inviter dans cette équipe", "team_inviteModalButton": "Inviter", "team_noFriend": "Vous n'avez pas encore ajouté d'ami sur CryptPad.", @@ -1242,5 +1246,10 @@ "teams_table_owners": "Gérer l'équipe", "teams_table_role": "Rôle", "share_contactCategory": "Contacts", - "pad_wordCount": "Mots : {0}" + "pad_wordCount": "Mots : {0}", + "share_linkWarning": "Ce lien contient les clés de votre document. Le destinataire aura un accès irrévocable à votre contenu.", + "share_linkPasswordAlert": "Cet élément est protégé par un mot de passe. Quand vous partagez le lien, le destinataire doit saisir le mot de passe.", + "share_contactPasswordAlert": "Cet élément est protégé par un mot de passe. Quand vous le partagez avec un contact CryptPad, le destinataire n'a pas a saisir le mot de passe.", + "share_embedPasswordAlert": "Cet élément est protégé par un mot de passe. Quand vous l'intégrez à une page, les visiteurs doivent saisir le mot de passe.", + "passwordFaqLink": "En lire plus sur les mots de passe" } From 9d9835ddb57881d75c82a6f4f6a90d9d9f6a14b0 Mon Sep 17 00:00:00 2001 From: Weblate Date: Tue, 10 Dec 2019 10:07:36 +0000 Subject: [PATCH 78/80] Translated using Weblate (German) Currently translated at 100.0% (1155 of 1155 strings) Translation: CryptPad/App Translate-URL: http://weblate.cryptpad.fr/projects/cryptpad/app/de/ --- www/common/translations/messages.de.json | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/www/common/translations/messages.de.json b/www/common/translations/messages.de.json index de40bbfec..d2f6c1998 100644 --- a/www/common/translations/messages.de.json +++ b/www/common/translations/messages.de.json @@ -754,6 +754,10 @@ "crypto": { "q": "Welche Kryptografie benutzt ihr?", "a": "CryptPad basiert auf zwei quelloffenen Kryptografiebibliotheken: tweetnacl.js und scrypt-async.js.

Scrypt ist eine Passwort-basierte Schlüsselableitungsfunktion. Wir werden sie, um deinen Benutzernamen und dein Passwort in ein einzigartiges Schlüsselpaar umzuwandeln. Dieses sichert den Zugang zu deinem CryptDrive, so dass nur du auf die Liste deiner Pads zugreifen kannst.

Wir verwenden die Verschlüsselung xsalsa20-poly1305 und x25519-xsalsa20-poly1305 von tweetnacl, um Dokumente und den Chatverlauf zu verschlüsseln." + }, + "pad_password": { + "q": "Was passiert, wenn ich einen Ordner oder ein Pad mit einem Passwort schütze?", + "a": "Du kannst Pads oder geteilte Ordner bei der Erstellung mit einem Passwort schützen. Du kannst auch jederzeit im Eigenschaften-Menü ein Passwort setzen/ändern/entfernen.

Passwörter für Pads und geteilte Ordner sollen den Link schützen, wenn du ihn über einen unsicheren Kanal wie Mail oder Textnachricht teilst. Wenn jemand den Link abfängt, aber nicht das Passwort kennt, kann er nicht auf dein Dokument zugreifen.

Beim Teilen mit Kontakten oder Teams innerhalb von CryptPad wird die Kommunikation verschlüsselt und es wird angenommen, dass der Empfänger auf das Dokument zugreifen darf. Daher wird das Passwort zusammen mit dem Pad geteilt. Der Empfänger, und du selbst, werden beim Öffnen des Dokuments nicht danach gefragt." } }, "usability": { @@ -1160,7 +1164,7 @@ "owner_request_declined": "{0} hat deine Einladung abgelehnt, ein Eigentümer von {1} zu sein", "owner_removed": "{0} hat dich als Eigentümer von {1} entfernt", "owner_removedPending": "{0} hat die Einladung zur Eigentümerschaft von {1} zurückgezogen", - "share_linkTeam": "Mit einem Team teilen", + "share_linkTeam": "Zu Team-Drive hinzufügen", "team_inviteModalButton": "Einladen", "team_pickFriends": "Freunde auswählen, um sie in dieses Team einzuladen", "team_noFriend": "Du bist derzeit mit keinen Freunden auf CryptPad verbunden.", @@ -1242,5 +1246,10 @@ "teams_table_owners": "Team verwalten", "teams_table_role": "Rolle", "share_contactCategory": "Kontakte", - "pad_wordCount": "Wörter: {0}" + "pad_wordCount": "Wörter: {0}", + "share_linkWarning": "Dieser Link enthält die Schlüssel zu deinem Dokument. Empfänger erhalten unwiderruflichen Zugriff zu deinen Inhalten.", + "share_linkPasswordAlert": "Dieses Element ist passwortgeschützt. Wenn du diesen Link teilst, muss der Empfänger das Passwort eingeben.", + "share_contactPasswordAlert": "Dieses Element ist passwortgeschützt. Weil du es mit einem CryptPad-Kontakt teilst, muss der Empfänger das Passwort nicht eingeben.", + "share_embedPasswordAlert": "Dieses Element ist passwortgeschützt. Wenn du dieses Pad einbettest, werden Betrachter nach dem Passwort gefragt.", + "passwordFaqLink": "Mehr über Passwörter erfahren" } From 8293a125a9890f2d6d5fa4eb156416ff7619b9a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Benqu=C3=A9?= Date: Tue, 10 Dec 2019 13:41:55 +0000 Subject: [PATCH 79/80] add label to contacts list --- www/common/common-ui-elements.js | 2 +- www/common/translations/messages.fr.json | 2 +- www/common/translations/messages.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 2596ea82c..b897642c2 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -876,7 +876,7 @@ define([ delete friends[curve]; }); - var friendsList = UIElements.getUserGrid(null, { + var friendsList = UIElements.getUserGrid(Messages.share_linkFriends, { common: common, data: friends, noFilter: false, diff --git a/www/common/translations/messages.fr.json b/www/common/translations/messages.fr.json index 90f5d75a0..3b3b3cdd4 100644 --- a/www/common/translations/messages.fr.json +++ b/www/common/translations/messages.fr.json @@ -1076,7 +1076,7 @@ "share_selectAll": "Tout", "share_deselectAll": "Aucun", "share_filterFriend": "Rechercher par nom", - "share_linkFriends": "Partager avec des amis", + "share_linkFriends": "Partager avec des contacts", "share_withFriends": "Partager", "notifications_dismiss": "Cacher", "fm_info_sharedFolderHistory": "Vous regardez l'historique de votre dossier partagé {0}
Votre CryptDrive restera en lecture seule pendant la navigation.", diff --git a/www/common/translations/messages.json b/www/common/translations/messages.json index 88fdc832b..69d460e86 100644 --- a/www/common/translations/messages.json +++ b/www/common/translations/messages.json @@ -1093,7 +1093,7 @@ "share_selectAll": "Select all", "share_deselectAll": "Deselect all", "share_filterFriend": "Search by name", - "share_linkFriends": "Share with friends", + "share_linkFriends": "Share with contacts", "share_withFriends": "Share", "notifications_dismiss": "Dismiss", "fm_info_sharedFolderHistory": "This is only the history of your shared folder: {0}
Your CryptDrive will stay in read-only mode while you navigate.", From e169e02d9463849f7fdcab5c89789a2cde42a149 Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 10 Dec 2019 16:27:12 +0100 Subject: [PATCH 80/80] Use large icons in team invite usergrid --- www/common/common-ui-elements.js | 1 + 1 file changed, 1 insertion(+) diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index b897642c2..d9610c822 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -1575,6 +1575,7 @@ define([ var list = UIElements.getUserGrid(Messages.team_pickFriends, { common: common, data: config.friends, + large: true }, refreshButton); $div = $(list.div); refreshButton();