From d58497ae8ef7324d2d408da869b6f688b61752ef Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Mon, 25 Mar 2024 13:36:38 +0100 Subject: [PATCH 001/140] Tighten eslint rules --- .eslintrc.js | 3 --- config/config.example.js | 2 -- lib/challenge-commands/totp.js | 1 - lib/commands/admin-rpc.js | 1 - lib/commands/block.js | 1 - lib/commands/core.js | 1 - lib/commands/quota.js | 1 - lib/env.js | 2 -- lib/hk-util.js | 1 - lib/log.js | 2 -- lib/storage/blob.js | 1 - lib/storage/file.js | 1 - lib/stream-file.js | 2 -- lib/workers/db-worker.js | 2 -- lib/workers/index.js | 1 - scripts/TestSelenium.js | 1 - scripts/build.js | 2 -- scripts/check-accounts.js | 1 - scripts/issue-jwt.js | 1 - scripts/tests/test-lkh.js | 1 - scripts/tests/test-mailbox.js | 2 -- scripts/tests/test-rpc.js | 2 -- server.js | 3 --- www/common/outer/serviceworker.js | 4 ++-- www/common/outer/sharedworker.js | 4 ++-- www/common/outer/webworker.js | 4 ++-- 26 files changed, 6 insertions(+), 41 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 523d0fb26..209a4718e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -49,13 +49,10 @@ module.exports = { // TODO remove these exceptions from the eslint defaults 'no-irregular-whitespace': ['off'], - 'no-unused-vars': ['warn'], 'no-self-assign': ['off'], 'no-empty': ['off'], 'no-useless-escape': ['off'], - 'no-redeclare': ['off'], 'no-extra-boolean-cast': ['off'], - 'no-global-assign': ['off'], 'no-prototype-builtins': ['off'], } }; diff --git a/config/config.example.js b/config/config.example.js index d6ebb4a50..e4d6c804f 100644 --- a/config/config.example.js +++ b/config/config.example.js @@ -2,8 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals module */ - /* DISCLAIMER: There are two recommended methods of running a CryptPad instance: diff --git a/lib/challenge-commands/totp.js b/lib/challenge-commands/totp.js index ca44e0010..a4ecfaa06 100644 --- a/lib/challenge-commands/totp.js +++ b/lib/challenge-commands/totp.js @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals Buffer */ const B32 = require("thirty-two"); const OTP = require("notp"); const nThen = require("nthen"); diff --git a/lib/commands/admin-rpc.js b/lib/commands/admin-rpc.js index 954c1c4c1..bce956147 100644 --- a/lib/commands/admin-rpc.js +++ b/lib/commands/admin-rpc.js @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals process */ const nThen = require("nthen"); const getFolderSize = require("get-folder-size"); const Util = require("../common-util"); diff --git a/lib/commands/block.js b/lib/commands/block.js index 1d64364df..c1bee1d65 100644 --- a/lib/commands/block.js +++ b/lib/commands/block.js @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals Buffer*/ const Block = module.exports; const Nacl = require("tweetnacl/nacl-fast"); const nThen = require("nthen"); diff --git a/lib/commands/core.js b/lib/commands/core.js index 79f3f40e8..6c92af74f 100644 --- a/lib/commands/core.js +++ b/lib/commands/core.js @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals process */ const Core = module.exports; const Util = require("../common-util"); const escapeKeyCharacters = Util.escapeKeyCharacters; diff --git a/lib/commands/quota.js b/lib/commands/quota.js index 7a92dbda9..4c068fad0 100644 --- a/lib/commands/quota.js +++ b/lib/commands/quota.js @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals Buffer*/ const Quota = module.exports; //const Util = require("../common-util"); diff --git a/lib/env.js b/lib/env.js index 1a8b3917e..d3748750f 100644 --- a/lib/env.js +++ b/lib/env.js @@ -2,8 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals process */ - const { existsSync, readdirSync } = require('node:fs'); const Crypto = require('crypto'); diff --git a/lib/hk-util.js b/lib/hk-util.js index da0a63ab8..7080d3d4a 100644 --- a/lib/hk-util.js +++ b/lib/hk-util.js @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* global Buffer */ var HK = module.exports; const nThen = require('nthen'); diff --git a/lib/log.js b/lib/log.js index c5b27fb85..c0a825daf 100644 --- a/lib/log.js +++ b/lib/log.js @@ -39,8 +39,6 @@ var handlers = {}; handlers[level] = function (ctx, content) { console.error(content); }; }); -var noop = function () {}; - var createLogType = function (ctx, type) { if (logLevels.indexOf(type) < logLevels.indexOf(ctx.logLevel)) { return noop; diff --git a/lib/storage/blob.js b/lib/storage/blob.js index b029b95c5..aeb9c1f70 100644 --- a/lib/storage/blob.js +++ b/lib/storage/blob.js @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals Buffer */ var Fs = require("fs"); var Fse = require("fs-extra"); var Path = require("path"); diff --git a/lib/storage/file.js b/lib/storage/file.js index d8617f300..2c2888f7a 100644 --- a/lib/storage/file.js +++ b/lib/storage/file.js @@ -3,7 +3,6 @@ // SPDX-License-Identifier: AGPL-3.0-or-later /*@flow*/ -/* globals Buffer */ var Fs = require("fs"); var Fse = require("fs-extra"); var Path = require("path"); diff --git a/lib/stream-file.js b/lib/stream-file.js index 372148836..18e691373 100644 --- a/lib/stream-file.js +++ b/lib/stream-file.js @@ -2,8 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* global Buffer */ - const ToPull = require('stream-to-pull-stream'); const Pull = require('pull-stream'); diff --git a/lib/workers/db-worker.js b/lib/workers/db-worker.js index 9878d2c22..63b2a8497 100644 --- a/lib/workers/db-worker.js +++ b/lib/workers/db-worker.js @@ -2,8 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals process, Buffer */ - const HK = require("../hk-util"); const Store = require("../storage/file"); const BlobStore = require("../storage/blob"); diff --git a/lib/workers/index.js b/lib/workers/index.js index 6db3f8bbd..55487c848 100644 --- a/lib/workers/index.js +++ b/lib/workers/index.js @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* global process */ const Util = require("../common-util"); const nThen = require('nthen'); const OS = require("os"); diff --git a/scripts/TestSelenium.js b/scripts/TestSelenium.js index f5930e69a..0447671ea 100644 --- a/scripts/TestSelenium.js +++ b/scripts/TestSelenium.js @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* global process */ var WebDriver = require("selenium-webdriver"); var nThen = require('nthen'); diff --git a/scripts/build.js b/scripts/build.js index b04b830f3..5cb823286 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -2,8 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals process */ - var Fs = require("fs"); var Fse = require("fs-extra"); var Path = require("path"); diff --git a/scripts/check-accounts.js b/scripts/check-accounts.js index 8b15616b9..81835f5c8 100644 --- a/scripts/check-accounts.js +++ b/scripts/check-accounts.js @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals Buffer */ var Https = require('https'); var Config = require("../lib/load-config"); var Package = require("../package.json"); diff --git a/scripts/issue-jwt.js b/scripts/issue-jwt.js index da36caa8e..c7efb80f5 100644 --- a/scripts/issue-jwt.js +++ b/scripts/issue-jwt.js @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals process */ const jwt = require("jsonwebtoken"); const Sessions = require("../lib/storage/sessions.js"); diff --git a/scripts/tests/test-lkh.js b/scripts/tests/test-lkh.js index f346ba385..38bc140c4 100644 --- a/scripts/tests/test-lkh.js +++ b/scripts/tests/test-lkh.js @@ -2,7 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals process */ var Client = require("../../lib/client"); var Nacl = require("tweetnacl/nacl-fast"); var nThen = require("nthen"); diff --git a/scripts/tests/test-mailbox.js b/scripts/tests/test-mailbox.js index 3b88c7939..f5611a6e3 100644 --- a/scripts/tests/test-mailbox.js +++ b/scripts/tests/test-mailbox.js @@ -2,8 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals process */ - var Client = require("../../lib/client/"); var Crypto = require("../../www/components/chainpad-crypto"); var Mailbox = Crypto.Mailbox; diff --git a/scripts/tests/test-rpc.js b/scripts/tests/test-rpc.js index 632de4424..9963bc997 100644 --- a/scripts/tests/test-rpc.js +++ b/scripts/tests/test-rpc.js @@ -2,8 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* globals process */ - var Client = require("../../lib/client/"); var Crypto = require("../../www/components/chainpad-crypto"); var Mailbox = Crypto.Mailbox; diff --git a/server.js b/server.js index f8e8ffd94..e84bec70b 100644 --- a/server.js +++ b/server.js @@ -2,9 +2,6 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -/* - globals process -*/ var Express = require('express'); var Http = require('http'); var Fs = require('fs'); diff --git a/www/common/outer/serviceworker.js b/www/common/outer/serviceworker.js index 106e4d848..5bd343980 100644 --- a/www/common/outer/serviceworker.js +++ b/www/common/outer/serviceworker.js @@ -6,8 +6,8 @@ importScripts('/components/requirejs/require.js'); -window = self; -localStorage = { +window = self; // eslint-disable-line no-global-assign +localStorage = { // eslint-disable-line no-global-assign setItem: function (k, v) { localStorage[k] = v; }, getItem: function (k) { return localStorage[k]; } }; diff --git a/www/common/outer/sharedworker.js b/www/common/outer/sharedworker.js index d7743dbf6..59c818ab8 100644 --- a/www/common/outer/sharedworker.js +++ b/www/common/outer/sharedworker.js @@ -6,8 +6,8 @@ importScripts('/components/requirejs/require.js'); -window = self; -localStorage = { +window = self; // eslint-disable-line no-global-assign +localStorage = { // eslint-disable-line no-global-assign setItem: function (k, v) { localStorage[k] = v; }, getItem: function (k) { return localStorage[k]; } }; diff --git a/www/common/outer/webworker.js b/www/common/outer/webworker.js index 96d174848..d5cc0b7d9 100644 --- a/www/common/outer/webworker.js +++ b/www/common/outer/webworker.js @@ -6,8 +6,8 @@ importScripts('/components/requirejs/require.js'); -window = self; -localStorage = { +window = self; // eslint-disable-line no-global-assign +localStorage = { // eslint-disable-line no-global-assign setItem: function (k, v) { localStorage[k] = v; }, getItem: function (k) { return localStorage[k]; } }; From 4d748bd9080aca1fa07b7fc2271646d3264e8a07 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Wed, 27 Mar 2024 11:33:25 +0100 Subject: [PATCH 002/140] Remove duplicate args_isString --- lib/decrees.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/decrees.js b/lib/decrees.js index 79a978398..317d492df 100644 --- a/lib/decrees.js +++ b/lib/decrees.js @@ -169,6 +169,7 @@ var isInteger = function (n) { var args_isString = function (args) { return !(!Array.isArray(args) || !isString(args[0])); }; + var args_isInteger = function (args) { return !(!Array.isArray(args) || !isInteger(args[0])); }; @@ -211,10 +212,6 @@ commands.SET_ARCHIVE_RETENTION_TIME = makeIntegerSetter('archiveRetentionTime'); // CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_ACCOUNT_RETENTION_TIME', [365]]], console.log) commands.SET_ACCOUNT_RETENTION_TIME = makeIntegerSetter('accountRetentionTime'); -var args_isString = function (args) { - return Array.isArray(args) && typeof(args[0]) === "string"; -}; - // CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_ADMIN_EMAIL', ['admin@website.tld']]], console.log) commands.SET_ADMIN_EMAIL = makeGenericSetter('adminEmail', args_isString); From 41fd888a39795ec437096f93ea23baba024039b2 Mon Sep 17 00:00:00 2001 From: mathilde-cryptpad <156299270+mathilde-cryptpad@users.noreply.github.com> Date: Tue, 18 Jun 2024 09:58:51 +0200 Subject: [PATCH 003/140] update Nginx examples with the new http2 option --- docs/example-advanced.nginx.conf | 6 ++++-- docs/example.nginx.conf | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/example-advanced.nginx.conf b/docs/example-advanced.nginx.conf index d49d8207f..9902c31bf 100644 --- a/docs/example-advanced.nginx.conf +++ b/docs/example-advanced.nginx.conf @@ -9,11 +9,13 @@ # in production and require professional support please contact sales@cryptpad.fr server { - listen 443 ssl http2; - listen [::]:443 ssl http2; + listen 443 ssl; + listen [::]:443 ssl; + http2 on; # Let's Encrypt webroot include letsencrypt-webroot; + # Include mime.types to be able to support .mjs files (see "types" below) include mime.types; diff --git a/docs/example.nginx.conf b/docs/example.nginx.conf index 8bd4fc3a1..dee2cbbc4 100644 --- a/docs/example.nginx.conf +++ b/docs/example.nginx.conf @@ -9,8 +9,9 @@ # in production and require professional support please contact sales@cryptpad.fr server { - listen 443 ssl http2; - listen [::]:443 ssl http2; + listen 443 ssl; + listen [::]:443 ssl; + http2 on; # Let's Encrypt webroot include letsencrypt-webroot; From c971cf1527023fd3a0f43b2910be73d13d3524e2 Mon Sep 17 00:00:00 2001 From: mathilde-cryptpad <156299270+mathilde-cryptpad@users.noreply.github.com> Date: Tue, 18 Jun 2024 11:10:19 +0200 Subject: [PATCH 004/140] clarify how to use the different ports, see #1212 --- config/config.example.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/config/config.example.js b/config/config.example.js index e4d6c804f..23695de61 100644 --- a/config/config.example.js +++ b/config/config.example.js @@ -89,7 +89,10 @@ module.exports = { /* httpSafePort allows you to specify an alternative port from which * the node process should serve sandboxed assets. The default value is - * that of your httpPort + 1. You probably don't need to change this. + * that of your httpPort + 1. You probably don't need to change this as + * it's only meant to be used in development environements and shouldn't + * be setup on production ones where traffic needs to be directed to the + * main httpPort. * */ //httpSafePort: 3001, From 83b52a221f31e8eb1669b6d729ab4a10d329a299 Mon Sep 17 00:00:00 2001 From: Fabrice Mouhartem Date: Tue, 9 Apr 2024 15:00:12 +0200 Subject: [PATCH 005/140] #1089: Contextual menu `open` on anonymous drive - Related to https://github.com/cryptpad/cryptpad/issues/1089#issuecomment-2044954222 --- www/common/drive-ui.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index 65ded1fb8..0434a7fdd 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -1201,7 +1201,8 @@ define([ // falsy (open in preview if default is not using the app) var defaultInApp = ['application/pdf']; var openFile = function (el, isRo, app) { - var data = manager.getFileData(el); + // On anonymous drive, `el` already contains file data + var data = el.channel ? el : manager.getFileData(el); if (data.static) { if (data.href) { From 5a4d78a56ca23885355bee128a8c0b6bc486a4a7 Mon Sep 17 00:00:00 2001 From: Fabrice Mouhartem Date: Tue, 9 Apr 2024 15:08:51 +0200 Subject: [PATCH 006/140] maintenance: fix typo in comments (minor) --- 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 0434a7fdd..8cc1a330d 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -1197,7 +1197,7 @@ define([ }); }; - // `app`: true (force open wiht the app), false (force open in preview), + // `app`: true (force open with the app), false (force open in preview), // falsy (open in preview if default is not using the app) var defaultInApp = ['application/pdf']; var openFile = function (el, isRo, app) { From 46f8c04b3c27fab7036f7fa99ce06990bbe79312 Mon Sep 17 00:00:00 2001 From: Fabrice Mouhartem Date: Tue, 9 Apr 2024 15:12:40 +0200 Subject: [PATCH 007/140] =?UTF-8?q?maintenance:=20another=20typo=20in=20th?= =?UTF-8?q?e=20comments=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 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 8cc1a330d..7a9d02633 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -1201,7 +1201,7 @@ define([ // falsy (open in preview if default is not using the app) var defaultInApp = ['application/pdf']; var openFile = function (el, isRo, app) { - // On anonymous drive, `el` already contains file data + // In anonymous drives, `el` already contains file data var data = el.channel ? el : manager.getFileData(el); if (data.static) { From ceeebd679a1eccc0b1a7fb3f69cb8676993002a0 Mon Sep 17 00:00:00 2001 From: Fabrice Mouhartem Date: Thu, 11 Apr 2024 17:26:35 +0200 Subject: [PATCH 008/140] Remove redraw in notification dropdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Created square angles on the right side of the notification dropdown when hovering above the dismiss (❌) button - Fix #1465 --- customize.dist/src/less2/include/notifications.less | 9 --------- 1 file changed, 9 deletions(-) diff --git a/customize.dist/src/less2/include/notifications.less b/customize.dist/src/less2/include/notifications.less index a0dab0725..6a69b8beb 100644 --- a/customize.dist/src/less2/include/notifications.less +++ b/customize.dist/src/less2/include/notifications.less @@ -36,9 +36,6 @@ } .cp-reminder, .cp-avatar { cursor: pointer; - &:hover { - background-color: @cp_dropdown-bg-hover; - } } .cp-avatar { .avatar_main(30px); @@ -61,9 +58,6 @@ } &.cp-clickable { cursor: pointer; - &:hover { - background-color: @cp_dropdown-bg-hover; - } } } .cp-notification-dismiss { @@ -73,9 +67,6 @@ align-items: center; justify-content: center; cursor: pointer; - &:hover { - background-color: @cp_dropdown-bg-hover; - } } } } From ec59395bca4b4d36c0cbc133b2d5173596918ba1 Mon Sep 17 00:00:00 2001 From: daria Date: Wed, 17 Apr 2024 15:09:54 +0300 Subject: [PATCH 009/140] add outline to focused elements on Code/Markdown tools --- customize.dist/src/less2/include/toolbar.less | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/customize.dist/src/less2/include/toolbar.less b/customize.dist/src/less2/include/toolbar.less index 05111c6b0..7a1690900 100644 --- a/customize.dist/src/less2/include/toolbar.less +++ b/customize.dist/src/less2/include/toolbar.less @@ -77,6 +77,12 @@ &:hover { background-color: contrast(@cp_toolbar-bg, darken(@cp_toolbar-bg, 5%), lighten(@cp_toolbar-bg, 5%)); } + &:focus { + outline: @cryptpad_color_brand solid 2px; + } + } + button:nth-of-type(1){ + margin-left: 0.3rem; } } From 97ccc169254cca286baaebcf59e8b919880954ee Mon Sep 17 00:00:00 2001 From: daria Date: Thu, 25 Apr 2024 13:57:41 +0300 Subject: [PATCH 010/140] add shortcut for getting out of Code editor --- www/common/sframe-common-codemirror.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/www/common/sframe-common-codemirror.js b/www/common/sframe-common-codemirror.js index 1d5943255..2cf288bdd 100644 --- a/www/common/sframe-common-codemirror.js +++ b/www/common/sframe-common-codemirror.js @@ -176,6 +176,11 @@ define([ else { editor.execCommand("insertTab"); } } }, + //remove focus from editor + "Shift-Enter": function () { + document.activeElement.blur(); + document.querySelector('[tabindex="0"]').focus(); + }, "Shift-Tab": function () { editor.execCommand("indentLess"); }, From ef0c8cd39f4237021106c0357d809761b1e1b112 Mon Sep 17 00:00:00 2001 From: daria Date: Fri, 10 May 2024 13:34:38 +0300 Subject: [PATCH 011/140] change shortcut for getting out of text editors Code/Slides --- www/common/sframe-common-codemirror.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/www/common/sframe-common-codemirror.js b/www/common/sframe-common-codemirror.js index 2cf288bdd..2e84c2d11 100644 --- a/www/common/sframe-common-codemirror.js +++ b/www/common/sframe-common-codemirror.js @@ -177,9 +177,9 @@ define([ } }, //remove focus from editor - "Shift-Enter": function () { + "Esc": function () { document.activeElement.blur(); - document.querySelector('[tabindex="0"]').focus(); + document.querySelector('.cp-toolbar-link-logo').focus(); }, "Shift-Tab": function () { editor.execCommand("indentLess"); From e6ab5a90ac21a75504107b6a739701d88a412db4 Mon Sep 17 00:00:00 2001 From: mathilde-cryptpad <156299270+mathilde-cryptpad@users.noreply.github.com> Date: Fri, 21 Jun 2024 16:12:00 +0200 Subject: [PATCH 012/140] explain with easier words the purpose of httpSafePort --- config/config.example.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/config/config.example.js b/config/config.example.js index 23695de61..63a75f059 100644 --- a/config/config.example.js +++ b/config/config.example.js @@ -87,12 +87,10 @@ module.exports = { */ //httpPort: 3000, -/* httpSafePort allows you to specify an alternative port from which - * the node process should serve sandboxed assets. The default value is - * that of your httpPort + 1. You probably don't need to change this as - * it's only meant to be used in development environements and shouldn't - * be setup on production ones where traffic needs to be directed to the - * main httpPort. +/* httpSafePort purpose is to emulate another origin for the sandbox when + * you don't have two domains at hand (i.e. when httpSafeOrigin not defined). + * It is meant to be used only in case where you are working on a local + * development instance. The default value is your httpPort + 1. * */ //httpSafePort: 3001, From 5f269fcff8eada9487239cc5cd0018e75d213dc4 Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 21 Jun 2024 16:19:07 +0200 Subject: [PATCH 013/140] lint compliance --- customize.dist/src/less2/include/toolbar.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/customize.dist/src/less2/include/toolbar.less b/customize.dist/src/less2/include/toolbar.less index 7a1690900..76333017b 100644 --- a/customize.dist/src/less2/include/toolbar.less +++ b/customize.dist/src/less2/include/toolbar.less @@ -81,7 +81,7 @@ outline: @cryptpad_color_brand solid 2px; } } - button:nth-of-type(1){ + button:nth-of-type(1) { margin-left: 0.3rem; } } From 792d27c89609bbfb9e2c8d0730e322f862dc8243 Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 21 Jun 2024 18:29:54 +0200 Subject: [PATCH 014/140] Fix CodeMirror focus issue --- www/common/sframe-common-codemirror.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/www/common/sframe-common-codemirror.js b/www/common/sframe-common-codemirror.js index 2e84c2d11..aa1bde788 100644 --- a/www/common/sframe-common-codemirror.js +++ b/www/common/sframe-common-codemirror.js @@ -178,8 +178,7 @@ define([ }, //remove focus from editor "Esc": function () { - document.activeElement.blur(); - document.querySelector('.cp-toolbar-link-logo').focus(); + editor.display.input.blur(); }, "Shift-Tab": function () { editor.execCommand("indentLess"); From 90d27e68a98eba8f03db41c46d8065d1be3e1657 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Mon, 12 Feb 2024 08:42:08 +0100 Subject: [PATCH 015/140] [wip] started with API proof of concept --- www/common/onlyoffice/inner.js | 7 +++++-- www/common/onlyoffice/oo-api.js | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 www/common/onlyoffice/oo-api.js diff --git a/www/common/onlyoffice/inner.js b/www/common/onlyoffice/inner.js index 5aab870ac..fd2212497 100644 --- a/www/common/onlyoffice/inner.js +++ b/www/common/onlyoffice/inner.js @@ -26,6 +26,7 @@ define([ '/common/outer/worker-channel.js', '/common/outer/x2t.js', + '/common/onlyoffice/oo-api.js', '/components/file-saver/FileSaver.min.js', 'css!/components/bootstrap/dist/css/bootstrap.min.css', @@ -53,7 +54,8 @@ define([ EmptyDoc, EmptySlide, Channel, - X2T) + X2T, + OOApi) { var saveAs = window.saveAs; var Nacl = window.nacl; @@ -2116,7 +2118,8 @@ Uncaught TypeError: Cannot read property 'calculatedType' of null }, void 0, common.getCache()); }; - APP.docEditor = new window.DocsAPI.DocEditor("cp-app-oo-placeholder-a", APP.ooconfig); + console.log(OOApi); + APP.docEditor = new OOApi.OnlyOfficeEditor("cp-app-oo-placeholder-a", APP.ooconfig); ooLoaded = true; makeChannel(); }; diff --git a/www/common/onlyoffice/oo-api.js b/www/common/onlyoffice/oo-api.js new file mode 100644 index 000000000..5cfb812b1 --- /dev/null +++ b/www/common/onlyoffice/oo-api.js @@ -0,0 +1,15 @@ +define([], function() { + class OnlyOfficeEditor { + constructor(placeholderId, config) { + this.editor = new window.DocsAPI.DocEditor(placeholderId, config); + } + + destroyEditor() { + this.editor.destroyEditor(); + } + } + + return { + OnlyOfficeEditor + }; +}); From d66420496e370af77e7048b25102425ccb22b066 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Wed, 27 Mar 2024 15:41:59 +0100 Subject: [PATCH 016/140] Split onlyoffice/inner in smaller functions --- www/common/common-util.js | 29 ++ www/common/onlyoffice/inner.js | 477 ++++++++++++++++---------------- www/common/onlyoffice/oo-api.js | 27 +- 3 files changed, 297 insertions(+), 236 deletions(-) diff --git a/www/common/common-util.js b/www/common/common-util.js index fd96f12c4..95b346a67 100644 --- a/www/common/common-util.js +++ b/www/common/common-util.js @@ -758,6 +758,35 @@ return ver || undefined; }; + Util.get = function(obj, key, defaultValue = undefined) { + if (typeof key === "string") { + key = key.split("."); + } + + for (const k of key) { + if (obj == null) { + return defaultValue; + } + obj = obj[k]; + } + + if (obj == null) { + return defaultValue; + } + return obj; + }; + + Util.deepAssign = function(target, source) { + if (typeof target != "object") { + return source; + } + + const result = Object.assign({}, target); + for (const key of Object.keys(source)) { + result[key] = Util.deepAssign(target[key], source[key]); + } + return result; + }; if (typeof(module) !== 'undefined' && module.exports) { module.exports = Util; diff --git a/www/common/onlyoffice/inner.js b/www/common/onlyoffice/inner.js index fd2212497..9f2969509 100644 --- a/www/common/onlyoffice/inner.js +++ b/www/common/onlyoffice/inner.js @@ -16,7 +16,6 @@ define([ '/common/hyperscript.js', '/api/config', '/customize/messages.js', - '/customize/application_config.js', '/components/chainpad/chainpad.dist.js', '/file/file-crypto.js', '/common/onlyoffice/history.js', @@ -46,7 +45,6 @@ define([ h, ApiConfig, Messages, - AppConfig, ChainPad, FileCrypto, History, @@ -1652,24 +1650,228 @@ define([ // to be downloaded and decrypted before converting to xlsx var downloadImages = {}; - var firstOO = true; - startOO = function (blob, file, force) { - if (APP.ooconfig && !force) { return void console.error('already started'); } - var url = URL.createObjectURL(blob); - var lock = !APP.history && (APP.migrate); + const onAppReady = function() { + APP.docEditor.getIframe().setAttribute('tabindex', '-1'); + var css = // Old OO + //'#id-toolbar-full .toolbar-group:nth-child(2), #id-toolbar-full .separator:nth-child(3) { display: none; }' + + //'#fm-btn-save { display: none !important; }' + + //'#panel-settings-general tr.autosave { display: none !important; }' + + //'#panel-settings-general tr.coauth { display: none !important; }' + + //'#header { display: none !important; }' + + '#title-doc-name { display: none !important; }' + + '#title-user-name { display: none !important; }' + + (supportsXLSX() ? '' : '#slot-btn-dt-print { display: none !important; }') + + // New OO: + 'section[data-tab="ins"] .separator:nth-last-child(2) { display: none !important; }' + // separator + '#slot-btn-insequation { display: none !important; }' + // Insert equation + //'#asc-gen125 { display: none !important; }' + // Disable presenter mode + //'.toolbar .tabs .ribtab:not(.canedit) { display: none !important; }' + // Switch collaborative mode + '#fm-btn-info { display: none !important; }' + // Author name, doc title, etc. in "File" (menu entry) + '#panel-info { display: none !important; }' + // Same but content + '#image-button-from-url { display: none !important; }' + // Inline image settings: replace with url + '.cp-from-url, #textart-button-from-url { display: none !important; }' + // Spellcheck language + '.statusbar .cnt-lang { display: none !important; }' + // Spellcheck language + '.statusbar #btn-doc-spell { display: none !important; }' + // Spellcheck button + '#file-menu-panel .devider { display: none !important; }' + // separator in the "File" menu + '#left-btn-spellcheck, #left-btn-about { display: none !important; }'+ + 'div.btn-users.dropdown-toggle { display: none; !important }'; + if (readOnly) { + css += '#toolbar { display: none !important; }'; + //css += '#app-title { display: none !important; }'; // OnlyOffice logo + doc title + //css += '#file-menu-panel { top: 28px !important; }'; // Position of the "File" menu + } + APP.docEditor.injectCSS(css); + setTimeout(function () { + $(window).trigger('resize'); + }); + if (UI.findOKButton().length) { + UI.findOKButton().on('focusout', function () { + window.setTimeout(function () { UI.findOKButton().focus(); }); + }); + } + }; - var fromContent = metadataMgr.getPrivateData().fromContent; - if (!firstOO) { fromContent = undefined; } - firstOO = false; + const onError = function() { + console.error(arguments); + if (APP.isDownload) { + var sframeChan = common.getSframeChannel(); + sframeChan.event('EV_OOIFRAME_DONE', ''); + } + }; - // Starting from version 3, we can use the view mode again - // defined but never used - //var mode = (content && content.version > 2 && lock) ? "view" : "edit"; + const onDocumentReady = function(lock, lang, fromContent, file, force) { + evOnSync.fire(); + var onMigrateRdy = Util.mkEvent(); + onMigrateRdy.reg(function () { + var div = h('div.cp-oo-x2tXls', [ + h('span.fa.fa-spin.fa-spinner'), + h('span', Messages.oo_sheetMigration_loading) + ]); + APP.migrateModal = UI.openCustomModal(UI.dialog.customModal(div, {buttons: []})); + makeCheckpoint(true); + }); + // DEPRECATED: from version 3, the queue is sent again during init + if (APP.migrate && ((content.version || 1) <= 2)) { + // The doc is ready, fix the worksheets IDs and push the queue + fixSheets(); + // Push changes since last cp + ooChannel.ready = true; + var changes = []; + var changesIndex; + ooChannel.queue.forEach(function (data) { + Array.prototype.push.apply(changes, data.msg.changes); + changesIndex = data.msg.changesIndex; + //ooChannel.send(data.msg); + }); + ooChannel.cpIndex += ooChannel.queue.length; + var last = ooChannel.queue.pop(); + if (last) { ooChannel.lastHash = last.hash; } - var lang = (window.cryptpadLanguage || navigator.language || navigator.userLanguage || '').slice(0,2); + var onDocUnlock = function () { + // Migration required but read-only: continue... + if (readOnly) { + setEditable(true); + try { getEditor().asc_setRestriction(true); } catch (e) {} + } else { + // No changes after the cp: migrate now + onMigrateRdy.fire(); + } + }; - // Config - APP.ooconfig = { + + // Send the changes all at once + if (changes.length) { + setTimeout(function () { + ooChannel.send({ + type: 'saveChanges', + changesIndex: changesIndex, + changes: changes, + locks: [] + }); + APP.onDocumentUnlock = onDocUnlock; + }, 5000); + return; + } + onDocUnlock(); + return; + } + + if (lock || readOnly) { + try { getEditor().asc_setRestriction(true); } catch (e) {} + //getEditor().setViewModeDisconnect(); // can't be used anymore, display an OO error popup + } else { + setEditable(true); + deleteOfflineLocks(); + handleNewLocks({}, content.locks); + if (APP.unsavedChanges) { + var unsaved = APP.unsavedChanges; + delete APP.unsavedChanges; + rtChannel.sendMsg(unsaved, null, function (err, hash) { + if (err) { return void UI.alert(Messages.oo_lostEdits); } + // This is supposed to be a "send" function to tell our OO + // to unlock the cell. We use this to know that the patch was + // correctly sent so that we can apply it to our OO too. + ooChannel.send(unsaved); + ooChannel.cpIndex++; + ooChannel.lastHash = hash; + }); + } + + if (APP.startNew) { + var w = getWindow(); + if (lang === "fr") { lang = 'fr-fr'; } + var l = w.Common.util.LanguageInfo.getLocalLanguageCode(lang); + getEditor().asc_setDefaultLanguage(l); + } + + if (APP.oldCursor) { + var app = common.getMetadataMgr().getPrivateData().ooType; + var d; + if (app === 'doc') { + d = getEditor().GetDocument().Document; + } else if (app === 'presentation') { + d = getEditor().GetPresentation().Presentation; + } + if (d) { + d.SetSelectionState(APP.oldCursor); + d.UpdateSelection(); + } + delete APP.oldCursor; + } + } + delete APP.startNew; + + if (fromContent && !lock && Array.isArray(fromContent.content)) { + makePatch(fromContent.content); + } + + if (APP.isDownload) { + delete APP.isDownload; + var bin = getContent(); + if (!supportsXLSX()) { + return void sframeChan.event('EV_OOIFRAME_DONE', bin, {raw: true}); + } + nThen(function (waitFor) { + // wait for all the images to be loaded before converting + Object.keys(downloadImages).forEach(function (name) { + downloadImages[name].reg(waitFor()); + }); + }).nThen(function () { + x2tConvertData(bin, 'filename.bin', file.type, function (xlsData) { + sframeChan.event('EV_OOIFRAME_DONE', xlsData, {raw: true}); + }); + }); + return; + } + + + if (isLockedModal.modal && force) { + isLockedModal.modal.closeModal(); + delete isLockedModal.modal; + if (!APP.history) { + $('#cp-app-oo-editor > iframe')[0].contentWindow.focus(); + } + } + + if (APP.template) { + try { getEditor().asc_setRestriction(true); } catch (e) {} + //getEditor().setViewModeDisconnect(); + UI.removeLoadingScreen(); + makeCheckpoint(true); + return; + } + + APP.onLocal(); // Add our data to the userlist + + if (APP.history) { + try { + getEditor().asc_setRestriction(true); + } catch (e) {} + } + + if (lock && !readOnly) { // Lock = !history && migrate + onMigrateRdy.fire(); + } + + if (APP.initCheckpoint) { + getEditor().asc_setRestriction(true); + makeCheckpoint(true); + } + + // Check if history can/should be trimmed + var cp = getLastCp(); + if (cp && cp.file && cp.hash) { + var channels = [{ + channel: content.channel, + lastKnownHash: cp.hash + }]; + common.checkTrimHistory(channels); + } + }; + + const createOOConfig = function(blob, file, lock, fromContent, lang, force) { + const url = URL.createObjectURL(blob); + return { "document": { "fileType": file.type, "key": "fresh", @@ -1698,226 +1900,30 @@ define([ "lang": lang }, "events": { - "onAppReady": function(/*evt*/) { - var $iframe = $('iframe[name="frameEditor"]').contents(); - $iframe.prop('tabindex', '-1'); - var $tb = $iframe.find('head'); - var css = // Old OO - //'#id-toolbar-full .toolbar-group:nth-child(2), #id-toolbar-full .separator:nth-child(3) { display: none; }' + - //'#fm-btn-save { display: none !important; }' + - //'#panel-settings-general tr.autosave { display: none !important; }' + - //'#panel-settings-general tr.coauth { display: none !important; }' + - //'#header { display: none !important; }' + - '#title-doc-name { display: none !important; }' + - '#title-user-name { display: none !important; }' + - (supportsXLSX() ? '' : '#slot-btn-dt-print { display: none !important; }') + - // New OO: - 'section[data-tab="ins"] .separator:nth-last-child(2) { display: none !important; }' + // separator - '#slot-btn-insequation { display: none !important; }' + // Insert equation - //'#asc-gen125 { display: none !important; }' + // Disable presenter mode - //'.toolbar .tabs .ribtab:not(.canedit) { display: none !important; }' + // Switch collaborative mode - '#fm-btn-info { display: none !important; }' + // Author name, doc title, etc. in "File" (menu entry) - '#panel-info { display: none !important; }' + // Same but content - '#image-button-from-url { display: none !important; }' + // Inline image settings: replace with url - '.cp-from-url, #textart-button-from-url { display: none !important; }' + // Spellcheck language - '.statusbar .cnt-lang { display: none !important; }' + // Spellcheck language - '.statusbar #btn-doc-spell { display: none !important; }' + // Spellcheck button - '#file-menu-panel .devider { display: none !important; }' + // separator in the "File" menu - '#left-btn-spellcheck, #left-btn-about { display: none !important; }'+ - 'div.btn-users.dropdown-toggle { display: none; !important }'; - if (readOnly) { - css += '#toolbar { display: none !important; }'; - //css += '#app-title { display: none !important; }'; // OnlyOffice logo + doc title - //css += '#file-menu-panel { top: 28px !important; }'; // Position of the "File" menu - } - $('