From 304fc6e970597417d72249c65b06ab3e656dc028 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Thu, 14 Sep 2023 15:17:32 +0200 Subject: [PATCH 01/28] Upgrade draw.io to 21.7.5 --- docs/example-advanced.nginx.conf | 2 +- lib/http-worker.js | 2 +- package-lock.json | 2 +- package.json | 2 +- scripts/copy-components.js | 2 +- www/diagram/inner.js | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/example-advanced.nginx.conf b/docs/example-advanced.nginx.conf index 5a0accab1..b3b8d36f1 100644 --- a/docs/example-advanced.nginx.conf +++ b/docs/example-advanced.nginx.conf @@ -163,7 +163,7 @@ server { if ($uri ~ ^\/unsafeiframe\/inner\.html.*$) { set $unsafe 1; } # draw.io uses inline script tags in it's index.html. The hashes are added here. - if ($uri ~ ^\/components\/drawio\/src\/main\/webapp\/index.html.*$) { + if ($uri ~ ^\/components\/drawio-cp\/src\/main\/webapp\/index.html.*$) { set $scriptSrc "'self' 'sha256-dLMFD7ijAw6AVaqecS7kbPcFFzkxQ+yeZSsKpOdLxps=' 'sha256-6g514VrT/cZFZltSaKxIVNFF46+MFaTSDTPB8WfYK+c=' resource: https://${main_domain}"; } diff --git a/lib/http-worker.js b/lib/http-worker.js index 3ade5af71..a88d3d713 100644 --- a/lib/http-worker.js +++ b/lib/http-worker.js @@ -147,7 +147,7 @@ var setHeaders = function (req, res) { type = 'office'; } else if (/^\/api\/(broadcast|config)/.test(req.url)) { type = 'api'; - } else if (/^\/components\/drawio\/src\/main\/webapp\/index.html.*$/.test(req.url)) { + } else if (/^\/components\/drawio-cp\/src\/main\/webapp\/index.html.*$/.test(req.url)) { type = 'diagram'; } else { type = 'standard'; diff --git a/package-lock.json b/package-lock.json index 189259d0b..c7cb9ea59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "components-font-awesome": "^4.6.3", "croppie": "^2.5.0", "dragula": "3.7.2", - "drawio": "cryptpad/drawio-npm#npm", + "drawio-cp": "github:cryptpad/drawio-npm#npm-21.7.5", "express": "~4.18.2", "file-saver": "1.3.1", "fs-extra": "^7.0.0", diff --git a/package.json b/package.json index 5554f4da5..6cfb724db 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "requirejs-plugins": "^1.0.2", "scrypt-async": "1.2.0", "sortablejs": "^1.6.0", - "drawio": "cryptpad/drawio-npm#npm", + "drawio-cp": "github:cryptpad/drawio-npm#npm-21.7.5", "pako": "^2.1.0", "x2js": "^3.4.4" }, diff --git a/scripts/copy-components.js b/scripts/copy-components.js index 2aa66ada8..c1f946501 100644 --- a/scripts/copy-components.js +++ b/scripts/copy-components.js @@ -40,7 +40,7 @@ Fse.rmSync(oldComponentsPath, { recursive: true, force: true }); "saferphore", "nthen", "netflux-websocket", - "drawio", + "drawio-cp", "pako", "x2js" ].forEach(l => { diff --git a/www/diagram/inner.js b/www/diagram/inner.js index 3b05c261e..bf2b917aa 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -168,7 +168,7 @@ define([ // starting the CryptPad framework framework.start(); - drawioFrame.src = '/components/drawio/src/main/webapp/index.html?' + drawioFrame.src = '/components/drawio-cp/src/main/webapp/index.html?' + new URLSearchParams({ // pages: 0, // dev: 1, From 8d6942ba610507c5b7ab375aeaf8d7fd1a64f319 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Fri, 22 Sep 2023 09:56:35 +0200 Subject: [PATCH 02/28] WIP play with open dialog --- package-lock.json | 11 +++++++---- package.json | 2 +- scripts/copy-components.js | 1 + www/diagram/inner.js | 6 +++--- www/diagram/open.html | 11 +++++++++++ www/diagram/open.js | 8 ++++++++ 6 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 www/diagram/open.html create mode 100644 www/diagram/open.js diff --git a/package-lock.json b/package-lock.json index c7cb9ea59..cd746d06e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "components-font-awesome": "^4.6.3", "croppie": "^2.5.0", "dragula": "3.7.2", - "drawio-cp": "github:cryptpad/drawio-npm#npm-21.7.5", + "drawio-cp": "../drawio-npm", "express": "~4.18.2", "file-saver": "1.3.1", "fs-extra": "^7.0.0", @@ -68,6 +68,9 @@ "url": "https://opencollective.com/cryptpad" } }, + "../drawio-npm": { + "version": "21.7.5" + }, "node_modules/@mcrowe/minibloom": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@mcrowe/minibloom/-/minibloom-0.2.0.tgz", @@ -914,9 +917,9 @@ }, "node_modules/ckeditor": { "name": "ckeditor4", - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/ckeditor4/-/ckeditor4-4.22.1.tgz", - "integrity": "sha512-Yj4vTHX5YxHwc48gNqUqTm+KLkRr9tuyb4O2VIABu4oKHWRNVIdLdy6vUNe/XNx+RiTavMejfA1MVOU/MxLjqQ==" + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/ckeditor4/-/ckeditor4-4.23.0.tgz", + "integrity": "sha512-K9DUzTa7roj8JffKLm6nOxDF02aPURDK8m7oFibvvkyAaomj24qOgpVdt7yvszmIubeJLbAB6q4k7Euk8jzD1A==" }, "node_modules/class-utils": { "version": "0.3.6", diff --git a/package.json b/package.json index 6cfb724db..a9b646d76 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "requirejs-plugins": "^1.0.2", "scrypt-async": "1.2.0", "sortablejs": "^1.6.0", - "drawio-cp": "github:cryptpad/drawio-npm#npm-21.7.5", + "drawio-cp": "../drawio-npm", "pako": "^2.1.0", "x2js": "^3.4.4" }, diff --git a/scripts/copy-components.js b/scripts/copy-components.js index c1f946501..577100c81 100644 --- a/scripts/copy-components.js +++ b/scripts/copy-components.js @@ -46,5 +46,6 @@ Fse.rmSync(oldComponentsPath, { recursive: true, force: true }); ].forEach(l => { const source = Path.join("node_modules", l); const destination = Path.join(componentsPath, l); + Fs.rmSync(destination, { recursive: true }); Fs.cpSync(source, destination, { recursive: true }); }); diff --git a/www/diagram/inner.js b/www/diagram/inner.js index bf2b917aa..f3388492a 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -170,13 +170,12 @@ define([ drawioFrame.src = '/components/drawio-cp/src/main/webapp/index.html?' + new URLSearchParams({ - // pages: 0, - // dev: 1, test: 1, stealth: 1, embed: 1, drafts: 0, - plugins: 0, + // plugins: 0, + p: '/cryptpad.js', chrome: framework.isReadOnly() ? 0 : 1, dark: window.CryptPad_theme === "dark" ? 1 : 0, @@ -185,6 +184,7 @@ define([ noSaveBtn: 1, saveAndExit: 0, noExitBtn: 1, + browser: 0, modified: 'unsavedChanges', proto: 'json', diff --git a/www/diagram/open.html b/www/diagram/open.html new file mode 100644 index 000000000..48fbc66bf --- /dev/null +++ b/www/diagram/open.html @@ -0,0 +1,11 @@ + + + + + + + + Hello World! + + + diff --git a/www/diagram/open.js b/www/diagram/open.js new file mode 100644 index 000000000..3ff6dcb84 --- /dev/null +++ b/www/diagram/open.js @@ -0,0 +1,8 @@ +window.addEventListener('load', () => { + const img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAABhGlDQ1BJQ0MgcHJvZmlsZQAAKJF9kTtIw1AUhv+mSlUqDnYQcQhSnSyIijhqFYpQIdQKrTqY3PQFTRqSFBdHwbXg4GOx6uDirKuDqyAIPkBcXZwUXaTEc5NCixgPHO7Hf89/OPdcQKiXmWZ1jAOabpupRFzMZFfF0Cu6EaEMYFhmljEnSUn4xtc91VHcxXgv/7o/o1fNWQwIiMSzzDBt4g3i6U3b4LxPHGFFWSU+Jx4zaUDiR64rHr9xLrgs8J4RM52aJ44Qi4U2VtqYFU2NeIo4qmo69RcyHquctzhr5SprzslfGM7pK8tcpxxCAotYggQRCqoooQwbMTp1Uiyk6D7u4x90/RK5FHKVwMixgAo0yK4f/A9+79bKT054ncJxoPPFcT5GgNAu0Kg5zvex4zROgOAzcKW3/JU6MPNJeq2lRY+Avm3g4rqlKXvA5Q4w8GTIpuxKQUohnwfez+ibskD/LdCz5u2teY/TByBNu0reAAeHwGiBeq/7vLurfW//1jT39wMoP3KJ0fwekQAAAAlwSFlzAAAuIwAALiMBeKU/dgAAAAd0SU1FB+cJFAkDEsK7OicAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAJElEQVQI12P8//8/AzbAxIADQCUYGRnRGQSMwqcDIoTgkuwqAOKDDw0zjEG/AAAAAElFTkSuQmCC'; + const btn = document.querySelector('button'); + btn.addEventListener('click', () => { + debugger; + window.parent.openFile.setData(img, 'test.png'); + }); +}); From 2dbd2b6ce7c9fa919c724b638c440e7e43ac6c3b Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Wed, 27 Sep 2023 14:38:37 +0200 Subject: [PATCH 03/28] openFilePicker now also returns fileType --- www/secureiframe/inner.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/www/secureiframe/inner.js b/www/secureiframe/inner.js index a93fc5e26..2aea4c1ee 100644 --- a/www/secureiframe/inner.js +++ b/www/secureiframe/inner.js @@ -117,6 +117,7 @@ define([ var key = Hash.encodeBase64(secret.keys.cryptKey); sframeChan.event("EV_SECURE_ACTION", { type: parsed.type, + fileType: data.fileType, href: data.url, src: src, name: data.name, @@ -230,7 +231,7 @@ define([ if (data.static) { $span.attr('title', Util.fixHTML(data.href)); } $span.click(function () { if (typeof onFilePicked === "function") { - onFilePicked({url: data.href, name: name, static: data.static, password: data.password}); + onFilePicked({url: data.href, name: name, static: data.static, password: data.password, fileType: data.fileType}); } }); From d1b2da8cce410e20b1afbade7896e9b5fc00dafa Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Wed, 27 Sep 2023 14:45:16 +0200 Subject: [PATCH 04/28] Can add image from CryptPad. Size is missing. --- scripts/copy-components.js | 2 +- www/diagram/inner.js | 75 +++++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/scripts/copy-components.js b/scripts/copy-components.js index 577100c81..24831aca7 100644 --- a/scripts/copy-components.js +++ b/scripts/copy-components.js @@ -46,6 +46,6 @@ Fse.rmSync(oldComponentsPath, { recursive: true, force: true }); ].forEach(l => { const source = Path.join("node_modules", l); const destination = Path.join(componentsPath, l); - Fs.rmSync(destination, { recursive: true }); + Fs.rmSync(destination, { recursive: true, force: true }); Fs.cpSync(source, destination, { recursive: true }); }); diff --git a/www/diagram/inner.js b/www/diagram/inner.js index f3388492a..8d92bd55e 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -4,6 +4,8 @@ define([ '/customize/messages.js', // translation keys '/components/pako/dist/pako.min.js', '/components/x2js/x2js.js', + '/common/common-util.js', + '/file/file-crypto.js', '/components/tweetnacl/nacl-fast.min.js', 'less!/diagram/app-diagram.less', 'css!/diagram/drawio.css', @@ -11,8 +13,11 @@ define([ Framework, Messages, pako, - X2JS) { + X2JS, + Util, + FileCrypto) { const Nacl = window.nacl; + const APP = window.APP = {}; // As described here: https://drawio-app.com/extracting-the-xml-from-mxfiles/ const decompressDrawioXml = function(xmlDocStr) { @@ -55,6 +60,8 @@ define([ // This is the main initialization loop var onFrameworkReady = function (framework) { + console.log('XXX framework', framework); + const common = framework._.sfCommon; // TODO do not access internals var EMPTY_DRAWIO = ""; var drawioFrame = document.querySelector('#cp-app-diagram-content'); var x2js = new X2JS(); @@ -121,6 +128,70 @@ define([ autosave: onDrawioAutosave, }; + const createDataUrl = (mimeType, blob) => { + return new Promise((resolve) => { + const reader = new FileReader(); + reader.addEventListener( + "load", + () => { + resolve(reader.result); + }, + false + ); + + const fixedBlob = new Blob([blob], {type: mimeType}); + reader.readAsDataURL(fixedBlob); + }); + }; + + APP.getImageURL = function(data, callback) { + Util.fetch(data.src, function (err, u8) { + if (err) { + console.error(err); + return void callback(""); + } + try { + FileCrypto.decrypt(u8, Nacl.util.decodeBase64(data.key), async (err, res) => { + if (err || !res.content) { + console.error("Decrypting failed"); + return void callback(""); + } + console.log('XXX res', res); + + try { + const dataUrl = await createDataUrl(data.fileType, res.content); + callback(dataUrl); + } catch (e) {} + }); + } catch (e) { + console.error(e); + callback(""); + } + }, void 0, common.getCache()); + }; + + APP.addImage = function() { + return new Promise((resolve) => { + common.openFilePicker({ + types: ['file'], + where: ['root'], + filter: { + fileType: ['image/'] + } + }, (data) => { + console.log('XXX data', data); + // TODO wait for realtime.onSettle + APP.getImageURL(data, function(url) { + common.setPadAttribute('atime', +new Date(), null, data.href); + resolve({ + name: data.name, + url: url + }); + }); + }); + }); + }; + // This is the function from which you will receive updates from CryptPad framework.onContentUpdate(function (newContent) { lastContent = newContent; @@ -175,7 +246,7 @@ define([ embed: 1, drafts: 0, // plugins: 0, - p: '/cryptpad.js', + p: 'cryptpad', chrome: framework.isReadOnly() ? 0 : 1, dark: window.CryptPad_theme === "dark" ? 1 : 0, From 62770db3d09a8d7a77c90c9b354992c224165569 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Wed, 27 Sep 2023 15:38:47 +0200 Subject: [PATCH 05/28] Clean up code --- www/diagram/inner.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/www/diagram/inner.js b/www/diagram/inner.js index 8d92bd55e..79ccf0a06 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -60,8 +60,7 @@ define([ // This is the main initialization loop var onFrameworkReady = function (framework) { - console.log('XXX framework', framework); - const common = framework._.sfCommon; // TODO do not access internals + const common = framework._.sfCommon; var EMPTY_DRAWIO = ""; var drawioFrame = document.querySelector('#cp-app-diagram-content'); var x2js = new X2JS(); @@ -156,7 +155,6 @@ define([ console.error("Decrypting failed"); return void callback(""); } - console.log('XXX res', res); try { const dataUrl = await createDataUrl(data.fileType, res.content); @@ -179,12 +177,11 @@ define([ fileType: ['image/'] } }, (data) => { - console.log('XXX data', data); - // TODO wait for realtime.onSettle APP.getImageURL(data, function(url) { common.setPadAttribute('atime', +new Date(), null, data.href); resolve({ name: data.name, + fileType: data.fileType, url: url }); }); From f4aa3731eb878d0fcd7afd6211169d43245221fe Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Fri, 29 Sep 2023 09:12:17 +0200 Subject: [PATCH 06/28] Fix npm lint --- www/diagram/inner.js | 7 ++----- www/diagram/open.html | 11 ----------- www/diagram/open.js | 8 -------- 3 files changed, 2 insertions(+), 24 deletions(-) delete mode 100644 www/diagram/open.html delete mode 100644 www/diagram/open.js diff --git a/www/diagram/inner.js b/www/diagram/inner.js index 79ccf0a06..829e681cf 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -150,16 +150,13 @@ define([ return void callback(""); } try { - FileCrypto.decrypt(u8, Nacl.util.decodeBase64(data.key), async (err, res) => { + FileCrypto.decrypt(u8, Nacl.util.decodeBase64(data.key), (err, res) => { if (err || !res.content) { console.error("Decrypting failed"); return void callback(""); } - try { - const dataUrl = await createDataUrl(data.fileType, res.content); - callback(dataUrl); - } catch (e) {} + createDataUrl(data.fileType, res.content).then(callback); }); } catch (e) { console.error(e); diff --git a/www/diagram/open.html b/www/diagram/open.html deleted file mode 100644 index 48fbc66bf..000000000 --- a/www/diagram/open.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - Hello World! - - - diff --git a/www/diagram/open.js b/www/diagram/open.js deleted file mode 100644 index 3ff6dcb84..000000000 --- a/www/diagram/open.js +++ /dev/null @@ -1,8 +0,0 @@ -window.addEventListener('load', () => { - const img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAABhGlDQ1BJQ0MgcHJvZmlsZQAAKJF9kTtIw1AUhv+mSlUqDnYQcQhSnSyIijhqFYpQIdQKrTqY3PQFTRqSFBdHwbXg4GOx6uDirKuDqyAIPkBcXZwUXaTEc5NCixgPHO7Hf89/OPdcQKiXmWZ1jAOabpupRFzMZFfF0Cu6EaEMYFhmljEnSUn4xtc91VHcxXgv/7o/o1fNWQwIiMSzzDBt4g3i6U3b4LxPHGFFWSU+Jx4zaUDiR64rHr9xLrgs8J4RM52aJ44Qi4U2VtqYFU2NeIo4qmo69RcyHquctzhr5SprzslfGM7pK8tcpxxCAotYggQRCqoooQwbMTp1Uiyk6D7u4x90/RK5FHKVwMixgAo0yK4f/A9+79bKT054ncJxoPPFcT5GgNAu0Kg5zvex4zROgOAzcKW3/JU6MPNJeq2lRY+Avm3g4rqlKXvA5Q4w8GTIpuxKQUohnwfez+ibskD/LdCz5u2teY/TByBNu0reAAeHwGiBeq/7vLurfW//1jT39wMoP3KJ0fwekQAAAAlwSFlzAAAuIwAALiMBeKU/dgAAAAd0SU1FB+cJFAkDEsK7OicAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAJElEQVQI12P8//8/AzbAxIADQCUYGRnRGQSMwqcDIoTgkuwqAOKDDw0zjEG/AAAAAElFTkSuQmCC'; - const btn = document.querySelector('button'); - btn.addEventListener('click', () => { - debugger; - window.parent.openFile.setData(img, 'test.png'); - }); -}); From 2945e6fce9b9d78924ecbc5614d34a2a26268131 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Tue, 10 Oct 2023 11:33:43 +0200 Subject: [PATCH 07/28] Pass blobs to draw.io --- www/common/sframe-common-file.js | 1 + www/diagram/inner.js | 25 +++++++------------------ 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/www/common/sframe-common-file.js b/www/common/sframe-common-file.js index 813678c0e..87236f277 100644 --- a/www/common/sframe-common-file.js +++ b/www/common/sframe-common-file.js @@ -92,6 +92,7 @@ define([ var data = {}; data.name = file.metadata.name; + data.fileType = file.metadata.type; data.url = href; data.password = file.password; if (file.metadata.type.slice(0,6) === 'image/') { diff --git a/www/diagram/inner.js b/www/diagram/inner.js index 829e681cf..89cab27dd 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -127,23 +127,12 @@ define([ autosave: onDrawioAutosave, }; - const createDataUrl = (mimeType, blob) => { - return new Promise((resolve) => { - const reader = new FileReader(); - reader.addEventListener( - "load", - () => { - resolve(reader.result); - }, - false - ); - - const fixedBlob = new Blob([blob], {type: mimeType}); - reader.readAsDataURL(fixedBlob); - }); + const setBlobType = (blob, mimeType) => { + const fixedBlob = new Blob([blob], {type: mimeType}); + return fixedBlob; }; - APP.getImageURL = function(data, callback) { + APP.getImage = function(data, callback) { Util.fetch(data.src, function (err, u8) { if (err) { console.error(err); @@ -156,7 +145,7 @@ define([ return void callback(""); } - createDataUrl(data.fileType, res.content).then(callback); + callback(setBlobType(res.content, data.fileType)); }); } catch (e) { console.error(e); @@ -174,12 +163,12 @@ define([ fileType: ['image/'] } }, (data) => { - APP.getImageURL(data, function(url) { + APP.getImage(data, function(blob) { common.setPadAttribute('atime', +new Date(), null, data.href); resolve({ name: data.name, fileType: data.fileType, - url: url + blob: blob }); }); }); From bd0ace126183ef095a4387822b508f974c839922 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Thu, 12 Oct 2023 16:18:10 +0200 Subject: [PATCH 08/28] Adding an image from Nextcloud works --- www/common/sframe-app-framework.js | 61 +++++++++++++++++++++++++++++- www/common/sframe-common-outer.js | 5 +++ www/cryptpad-api.js | 6 ++- www/diagram/inner.js | 51 ++----------------------- www/integration/main.js | 8 +++- 5 files changed, 80 insertions(+), 51 deletions(-) diff --git a/www/common/sframe-app-framework.js b/www/common/sframe-app-framework.js index c0c4e9106..9ae44dc27 100644 --- a/www/common/sframe-app-framework.js +++ b/www/common/sframe-app-framework.js @@ -16,6 +16,7 @@ define([ '/common/inner/snapshots.js', '/customize/application_config.js', '/components/chainpad/chainpad.dist.js', + '/file/file-crypto.js', '/common/test.js', '/components/file-saver/FileSaver.min.js', @@ -38,7 +39,8 @@ define([ Feedback, Snapshots, AppConfig, - ChainPad /*, + ChainPad, + FileCrypto /*, /* Test */) { var SaveAs = window.saveAs; @@ -64,6 +66,7 @@ define([ var create = function (options, cb) { var evContentUpdate = Util.mkEvent(); var evIntegrationSave = Util.mkEvent(); + var evIntegrationInsertImage = Util.mkEvent(); var evCursorUpdate = Util.mkEvent(); var evEditableStateChange = Util.mkEvent(); var evOnReady = Util.mkEvent(true); @@ -643,6 +646,9 @@ define([ const integrationHasUnsavedChanges = function(unsavedChanges, cb) { sframeChan.query('Q_INTEGRATION_HAS_UNSAVED_CHANGES', unsavedChanges, cb); }; + const integrationOnInsertImage = function(data, cb) { + sframeChan.query('Q_INTEGRATION_ON_INSERT_IMAGE', data, cb, {raw: true}); + }; var inte = common.createIntegration(onLocal, cpNfInner.chainpad, integrationSave, integrationHasUnsavedChanges); if (inte) { @@ -650,6 +656,7 @@ define([ evIntegrationSave.reg(function () { inte.changed(); }); + evIntegrationInsertImage.reg(integrationOnInsertImage); } if (firstConnection) { sframeChan.on('Q_INTEGRATION_NEEDSAVE', function (data, cb) { @@ -1119,6 +1126,58 @@ define([ // Call this after all of the handlers are setup. start: evStart.fire, + // Call this, when the user wants to add an image from drive. + insertImage: function(data, cb) { // TODO Move function somwhere else + if (integration) { + evIntegrationInsertImage.fire(data, cb); + return; + } + + const setBlobType = (blob, mimeType) => { + const fixedBlob = new Blob([blob], {type: mimeType}); + return fixedBlob; + }; + + const getImage = function(data, callback) { + Util.fetch(data.src, function (err, u8) { + if (err) { + console.error(err); + return void callback(""); + } + try { + FileCrypto.decrypt(u8, nacl.util.decodeBase64(data.key), (err, res) => { + if (err || !res.content) { + console.error("Decrypting failed"); + return void callback(""); + } + + callback(setBlobType(res.content, data.fileType)); + }); + } catch (e) { + console.error(e); + callback(""); + } + }, void 0, common.getCache()); + }; + + common.openFilePicker({ + types: ['file'], + where: ['root'], + filter: { + fileType: ['image/', 'application/x-drawio'] + } + }, (data) => { + getImage(data, function(blob) { + common.setPadAttribute('atime', +new Date(), null, data.href); + cb({ + name: data.name, + fileType: data.fileType, + blob: blob + }); + }); + }); + }, + // Determine the internal state of the framework. getState: function () { return state; }, diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index 4ccda4b68..61b93f135 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -2009,6 +2009,11 @@ define([ cfg.integrationUtils.onHasUnsavedChanges(obj, cb); } }); + sframeChan.on('Q_INTEGRATION_ON_INSERT_IMAGE', function (data, cb) { + if (cfg.integrationUtils && cfg.integrationUtils.onInsertImage) { + cfg.integrationUtils.onInsertImage(data, cb); + } + }); integrationSave = function (cb) { sframeChan.query('Q_INTEGRATION_NEEDSAVE', null, cb); }; diff --git a/www/cryptpad-api.js b/www/cryptpad-api.js index 556bd5fd6..d66f2c6bb 100644 --- a/www/cryptpad-api.js +++ b/www/cryptpad-api.js @@ -162,6 +162,9 @@ config.events.onHasUnsavedChanges(unsavedChanges); cb(); }); + chan.on('ON_INSERT_IMAGE', function(data, cb) { + config.events.onInsertImage(data, cb); + }); }); }); @@ -180,6 +183,7 @@ * @param {object} config.events Event handlers. * @param {function} events.onSave (blob, callback) The save function to store the document when edited. * @param {function} events.onNewKey (data, callback) The function called when a new key is used. + * @param {function} events.onInsertImage (data, callback) The function called the user wants to add an image. * @param {string} config.documentType The editor to load in CryptPad. * @return {promise} */ @@ -202,7 +206,7 @@ if (!config) { return reject('Missing args: no data provided'); } if(['document.url', 'document.fileType', 'documentType', 'events.onSave', 'events.onHasUnsavedChanges', - 'events.onNewKey'].some(function (k) { + 'events.onNewKey', 'events.onInsertImage'].some(function (k) { var s = k.split('.'); var c = config; return s.some(function (key) { diff --git a/www/diagram/inner.js b/www/diagram/inner.js index 89cab27dd..25b475cee 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -4,8 +4,6 @@ define([ '/customize/messages.js', // translation keys '/components/pako/dist/pako.min.js', '/components/x2js/x2js.js', - '/common/common-util.js', - '/file/file-crypto.js', '/components/tweetnacl/nacl-fast.min.js', 'less!/diagram/app-diagram.less', 'css!/diagram/drawio.css', @@ -13,9 +11,7 @@ define([ Framework, Messages, pako, - X2JS, - Util, - FileCrypto) { + X2JS) { const Nacl = window.nacl; const APP = window.APP = {}; @@ -127,50 +123,11 @@ define([ autosave: onDrawioAutosave, }; - const setBlobType = (blob, mimeType) => { - const fixedBlob = new Blob([blob], {type: mimeType}); - return fixedBlob; - }; - - APP.getImage = function(data, callback) { - Util.fetch(data.src, function (err, u8) { - if (err) { - console.error(err); - return void callback(""); - } - try { - FileCrypto.decrypt(u8, Nacl.util.decodeBase64(data.key), (err, res) => { - if (err || !res.content) { - console.error("Decrypting failed"); - return void callback(""); - } - - callback(setBlobType(res.content, data.fileType)); - }); - } catch (e) { - console.error(e); - callback(""); - } - }, void 0, common.getCache()); - }; - APP.addImage = function() { return new Promise((resolve) => { - common.openFilePicker({ - types: ['file'], - where: ['root'], - filter: { - fileType: ['image/'] - } - }, (data) => { - APP.getImage(data, function(blob) { - common.setPadAttribute('atime', +new Date(), null, data.href); - resolve({ - name: data.name, - fileType: data.fileType, - blob: blob - }); - }); + framework.insertImage({}, (_, image) => { + console.log('XXX image', image); + resolve(image); }); }); }; diff --git a/www/integration/main.js b/www/integration/main.js index c36c6869f..c4795bef1 100644 --- a/www/integration/main.js +++ b/www/integration/main.js @@ -10,7 +10,7 @@ define([ console.warn('INIT'); var p = window.parent; var txid = getTxid(); - p.postMessage(JSON.stringify({ q: 'INTEGRATION_READY', txid: txid }), '*'); + p.postMessage({ q: 'INTEGRATION_READY', txid: txid }, '*'); var makeChan = function () { var handlers = {}; @@ -118,6 +118,9 @@ define([ var onHasUnsavedChanges = function (unsavedChanges, cb) { chan.send('HAS_UNSAVED_CHANGES', unsavedChanges, cb); }; + var onInsertImage = function (data, cb) { + chan.send('ON_INSERT_IMAGE', data, cb); + }; chan.on('START', function (data) { console.warn('INNER START', data); @@ -135,7 +138,8 @@ define([ utils: { save: save, reload: reload, - onHasUnsavedChanges: onHasUnsavedChanges + onHasUnsavedChanges: onHasUnsavedChanges, + onInsertImage: onInsertImage } }; require(['/common/sframe-app-outer.js'], function () { From b1e8122ee4997e2196620b42df9a1714ff31c7e5 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Mon, 16 Oct 2023 12:47:47 +0200 Subject: [PATCH 09/28] Move image dialog to its own module --- www/common/image-dialog.js | 60 ++++++++++++++++++++++++++ www/common/sframe-app-framework.js | 67 ++++-------------------------- www/diagram/inner.js | 1 - 3 files changed, 68 insertions(+), 60 deletions(-) create mode 100644 www/common/image-dialog.js diff --git a/www/common/image-dialog.js b/www/common/image-dialog.js new file mode 100644 index 000000000..998e2057f --- /dev/null +++ b/www/common/image-dialog.js @@ -0,0 +1,60 @@ +define([ + '/common/common-util.js', + '/file/file-crypto.js', +], function( + Util, + FileCrypto, +) { + + const setBlobType = (blob, mimeType) => { + const fixedBlob = new Blob([blob], {type: mimeType}); + return fixedBlob; + }; + + const getImage = function(common, data, callback) { + Util.fetch(data.src, function (err, u8) { + if (err) { + console.error(err); + return void callback(""); + } + try { + FileCrypto.decrypt(u8, nacl.util.decodeBase64(data.key), (err, res) => { + if (err || !res.content) { + console.error("Decrypting failed"); + return void callback(""); + } + + callback(setBlobType(res.content, data.fileType)); + }); + } catch (e) { + console.error(e); + callback(""); + } + }, void 0, common.getCache()); + }; + + return { + openImageDialog: function(common, integrationChannel, data, cb) { + if (integrationChannel) { + integrationChannel.query('Q_INTEGRATION_ON_INSERT_IMAGE', data, cb, {raw: true}); + return; + } + common.openFilePicker({ + types: ['file'], + where: ['root'], + filter: { + fileType: ['image/', 'application/x-drawio'] + } + }, (data) => { + getImage(data, function(blob) { + common.setPadAttribute('atime', +new Date(), null, data.href); + cb({ + name: data.name, + fileType: data.fileType, + blob: blob + }); + }); + }); + } + }; +}); diff --git a/www/common/sframe-app-framework.js b/www/common/sframe-app-framework.js index 9ae44dc27..78d9bbb2f 100644 --- a/www/common/sframe-app-framework.js +++ b/www/common/sframe-app-framework.js @@ -16,7 +16,6 @@ define([ '/common/inner/snapshots.js', '/customize/application_config.js', '/components/chainpad/chainpad.dist.js', - '/file/file-crypto.js', '/common/test.js', '/components/file-saver/FileSaver.min.js', @@ -39,8 +38,7 @@ define([ Feedback, Snapshots, AppConfig, - ChainPad, - FileCrypto /*, + ChainPad /*, /* Test */) { var SaveAs = window.saveAs; @@ -66,7 +64,6 @@ define([ var create = function (options, cb) { var evContentUpdate = Util.mkEvent(); var evIntegrationSave = Util.mkEvent(); - var evIntegrationInsertImage = Util.mkEvent(); var evCursorUpdate = Util.mkEvent(); var evEditableStateChange = Util.mkEvent(); var evOnReady = Util.mkEvent(true); @@ -87,6 +84,7 @@ define([ var state = STATE.DISCONNECTED; var firstConnection = true; var integration; + let integrationChannel; var toolbarContainer = options.toolbarContainer || (function () { throw new Error("toolbarContainer must be specified"); }()); @@ -622,12 +620,12 @@ define([ if (privateDat.integration) { common.openIntegrationChannel(onLocal); - var sframeChan = common.getSframeChannel(); + integrationChannel = common.getSframeChannel(); var integrationSave = function (cb) { var ext = privateDat.integrationConfig.fileType; var upload = Util.once(function (_blob) { - sframeChan.query('Q_INTEGRATION_SAVE', { + integrationChannel.query('Q_INTEGRATION_SAVE', { blob: _blob }, cb, { raw: true @@ -644,10 +642,7 @@ define([ } }; const integrationHasUnsavedChanges = function(unsavedChanges, cb) { - sframeChan.query('Q_INTEGRATION_HAS_UNSAVED_CHANGES', unsavedChanges, cb); - }; - const integrationOnInsertImage = function(data, cb) { - sframeChan.query('Q_INTEGRATION_ON_INSERT_IMAGE', data, cb, {raw: true}); + integrationChannel.query('Q_INTEGRATION_HAS_UNSAVED_CHANGES', unsavedChanges, cb); }; var inte = common.createIntegration(onLocal, cpNfInner.chainpad, integrationSave, integrationHasUnsavedChanges); @@ -656,10 +651,9 @@ define([ evIntegrationSave.reg(function () { inte.changed(); }); - evIntegrationInsertImage.reg(integrationOnInsertImage); } if (firstConnection) { - sframeChan.on('Q_INTEGRATION_NEEDSAVE', function (data, cb) { + integrationChannel.on('Q_INTEGRATION_NEEDSAVE', function (data, cb) { integrationSave(function (obj) { if (obj && obj.error) { console.error(obj.error); } cb(); @@ -1128,53 +1122,8 @@ define([ // Call this, when the user wants to add an image from drive. insertImage: function(data, cb) { // TODO Move function somwhere else - if (integration) { - evIntegrationInsertImage.fire(data, cb); - return; - } - - const setBlobType = (blob, mimeType) => { - const fixedBlob = new Blob([blob], {type: mimeType}); - return fixedBlob; - }; - - const getImage = function(data, callback) { - Util.fetch(data.src, function (err, u8) { - if (err) { - console.error(err); - return void callback(""); - } - try { - FileCrypto.decrypt(u8, nacl.util.decodeBase64(data.key), (err, res) => { - if (err || !res.content) { - console.error("Decrypting failed"); - return void callback(""); - } - - callback(setBlobType(res.content, data.fileType)); - }); - } catch (e) { - console.error(e); - callback(""); - } - }, void 0, common.getCache()); - }; - - common.openFilePicker({ - types: ['file'], - where: ['root'], - filter: { - fileType: ['image/', 'application/x-drawio'] - } - }, (data) => { - getImage(data, function(blob) { - common.setPadAttribute('atime', +new Date(), null, data.href); - cb({ - name: data.name, - fileType: data.fileType, - blob: blob - }); - }); + require(['/common/image-dialog.js'], function(imageDialog) { + imageDialog.openImageDialog(common, integrationChannel, data, cb); }); }, diff --git a/www/diagram/inner.js b/www/diagram/inner.js index 25b475cee..112ebd11d 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -126,7 +126,6 @@ define([ APP.addImage = function() { return new Promise((resolve) => { framework.insertImage({}, (_, image) => { - console.log('XXX image', image); resolve(image); }); }); From 2d63fec04009d4e7c78b6d0eb82d709f70829b25 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Tue, 17 Oct 2023 10:19:26 +0200 Subject: [PATCH 10/28] Fix image import from cryptpad --- www/common/image-dialog.js | 5 +++-- www/diagram/inner.js | 2 +- www/integration/main.js | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/www/common/image-dialog.js b/www/common/image-dialog.js index 998e2057f..246f7f387 100644 --- a/www/common/image-dialog.js +++ b/www/common/image-dialog.js @@ -36,7 +36,8 @@ define([ return { openImageDialog: function(common, integrationChannel, data, cb) { if (integrationChannel) { - integrationChannel.query('Q_INTEGRATION_ON_INSERT_IMAGE', data, cb, {raw: true}); + const ignoreFirstParam = (_, image) => cb(image); + integrationChannel.query('Q_INTEGRATION_ON_INSERT_IMAGE', data, ignoreFirstParam, {raw: true}); return; } common.openFilePicker({ @@ -46,7 +47,7 @@ define([ fileType: ['image/', 'application/x-drawio'] } }, (data) => { - getImage(data, function(blob) { + getImage(common, data, function(blob) { common.setPadAttribute('atime', +new Date(), null, data.href); cb({ name: data.name, diff --git a/www/diagram/inner.js b/www/diagram/inner.js index 112ebd11d..4359f45d3 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -125,7 +125,7 @@ define([ APP.addImage = function() { return new Promise((resolve) => { - framework.insertImage({}, (_, image) => { + framework.insertImage({}, (image) => { resolve(image); }); }); diff --git a/www/integration/main.js b/www/integration/main.js index c4795bef1..fb3cfadce 100644 --- a/www/integration/main.js +++ b/www/integration/main.js @@ -34,6 +34,7 @@ define([ // On new command var msg = data.msg; + if (!msg) { return; } var txid = data.txid; if (commands[msg.q]) { commands[msg.q](msg.data, function (args) { From 2611785a500c33630be2aaedc6f9b539428e2449 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Tue, 17 Oct 2023 13:48:53 +0200 Subject: [PATCH 11/28] Fix draw.io dependency --- package-lock.json | 34 ++++++++++++++++++---------------- package.json | 2 +- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index cd746d06e..2b6f0c305 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "components-font-awesome": "^4.6.3", "croppie": "^2.5.0", "dragula": "3.7.2", - "drawio-cp": "../drawio-npm", + "drawio-cp": "github:cryptpad/drawio-npm#npm-21.8.2", "express": "~4.18.2", "file-saver": "1.3.1", "fs-extra": "^7.0.0", @@ -68,9 +68,6 @@ "url": "https://opencollective.com/cryptpad" } }, - "../drawio-npm": { - "version": "21.7.5" - }, "node_modules/@mcrowe/minibloom": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@mcrowe/minibloom/-/minibloom-0.2.0.tgz", @@ -1889,9 +1886,12 @@ "dev": true }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/gar": { "version": "1.0.4", @@ -2023,12 +2023,9 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", "engines": { "node": ">= 0.4.0" } @@ -3186,9 +3183,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.0.tgz", + "integrity": "sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4592,6 +4589,11 @@ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" }, + "node_modules/undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" + }, "node_modules/union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", diff --git a/package.json b/package.json index a9b646d76..8ced5f4a5 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "requirejs-plugins": "^1.0.2", "scrypt-async": "1.2.0", "sortablejs": "^1.6.0", - "drawio-cp": "../drawio-npm", + "drawio-cp": "github:cryptpad/drawio-npm#npm-21.8.2", "pako": "^2.1.0", "x2js": "^3.4.4" }, From 7f55498bcc5c47e9f8e70a7fce44e5c623165641 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Tue, 17 Oct 2023 14:09:07 +0200 Subject: [PATCH 12/28] Update draw.io dependency and remove unneeded CSP headers --- docs/example-advanced.nginx.conf | 4 ++-- lib/defaults.js | 4 ---- lib/http-worker.js | 4 ---- package-lock.json | 2 +- package.json | 2 +- scripts/copy-components.js | 2 +- www/diagram/inner.js | 2 +- 7 files changed, 6 insertions(+), 14 deletions(-) diff --git a/docs/example-advanced.nginx.conf b/docs/example-advanced.nginx.conf index b3b8d36f1..16d45087a 100644 --- a/docs/example-advanced.nginx.conf +++ b/docs/example-advanced.nginx.conf @@ -163,8 +163,8 @@ server { if ($uri ~ ^\/unsafeiframe\/inner\.html.*$) { set $unsafe 1; } # draw.io uses inline script tags in it's index.html. The hashes are added here. - if ($uri ~ ^\/components\/drawio-cp\/src\/main\/webapp\/index.html.*$) { - set $scriptSrc "'self' 'sha256-dLMFD7ijAw6AVaqecS7kbPcFFzkxQ+yeZSsKpOdLxps=' 'sha256-6g514VrT/cZFZltSaKxIVNFF46+MFaTSDTPB8WfYK+c=' resource: https://${main_domain}"; + if ($uri ~ ^\/components\/drawio\/src\/main\/webapp\/index.html.*$) { + set $scriptSrc "'self' resource: https://${main_domain}"; } # privileged contexts allow a few more rights than unprivileged contexts, though limits are still applied diff --git a/lib/defaults.js b/lib/defaults.js index 969842189..ef85e9470 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -48,10 +48,6 @@ Default.padContentSecurity = function (Env) { return (Default.commonCSP(Env).join('; ') + "script-src 'self' 'unsafe-eval' 'unsafe-inline' resource: " + Env.httpUnsafeOrigin).replace(/\s+/g, ' '); }; -Default.diagramContentSecurity = function (Env) { - return (Default.commonCSP(Env).join('; ') + "script-src 'self' 'sha256-dLMFD7ijAw6AVaqecS7kbPcFFzkxQ+yeZSsKpOdLxps=' 'sha256-6g514VrT/cZFZltSaKxIVNFF46+MFaTSDTPB8WfYK+c=' resource: " + Env.httpUnsafeOrigin).replace(/\s+/g, ' '); -}; - Default.httpHeaders = function (Env) { return { "X-XSS-Protection": "1; mode=block", diff --git a/lib/http-worker.js b/lib/http-worker.js index a88d3d713..8bc11800c 100644 --- a/lib/http-worker.js +++ b/lib/http-worker.js @@ -123,8 +123,6 @@ var getHeaders = function (Env, type) { var csp; if (type === 'office') { csp = Default.padContentSecurity(Env); - } else if (type === 'diagram') { - csp = Default.diagramContentSecurity(Env); } else { csp = Default.contentSecurity(Env); } @@ -147,8 +145,6 @@ var setHeaders = function (req, res) { type = 'office'; } else if (/^\/api\/(broadcast|config)/.test(req.url)) { type = 'api'; - } else if (/^\/components\/drawio-cp\/src\/main\/webapp\/index.html.*$/.test(req.url)) { - type = 'diagram'; } else { type = 'standard'; } diff --git a/package-lock.json b/package-lock.json index 2b6f0c305..46e21f23e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "components-font-awesome": "^4.6.3", "croppie": "^2.5.0", "dragula": "3.7.2", - "drawio-cp": "github:cryptpad/drawio-npm#npm-21.8.2", + "drawio": "github:cryptpad/drawio-npm#npm-21.8.2", "express": "~4.18.2", "file-saver": "1.3.1", "fs-extra": "^7.0.0", diff --git a/package.json b/package.json index 8ced5f4a5..f1f36b015 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "requirejs-plugins": "^1.0.2", "scrypt-async": "1.2.0", "sortablejs": "^1.6.0", - "drawio-cp": "github:cryptpad/drawio-npm#npm-21.8.2", + "drawio": "github:cryptpad/drawio-npm#npm-21.8.2", "pako": "^2.1.0", "x2js": "^3.4.4" }, diff --git a/scripts/copy-components.js b/scripts/copy-components.js index 24831aca7..cd0903373 100644 --- a/scripts/copy-components.js +++ b/scripts/copy-components.js @@ -40,7 +40,7 @@ Fse.rmSync(oldComponentsPath, { recursive: true, force: true }); "saferphore", "nthen", "netflux-websocket", - "drawio-cp", + "drawio", "pako", "x2js" ].forEach(l => { diff --git a/www/diagram/inner.js b/www/diagram/inner.js index 4359f45d3..411ad21b6 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -178,7 +178,7 @@ define([ // starting the CryptPad framework framework.start(); - drawioFrame.src = '/components/drawio-cp/src/main/webapp/index.html?' + drawioFrame.src = '/components/drawio/src/main/webapp/index.html?' + new URLSearchParams({ test: 1, stealth: 1, From e7142962a6d43574a8d86332565b6338c0b14014 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Tue, 17 Oct 2023 16:47:23 +0200 Subject: [PATCH 13/28] Fix package-lock after rebase --- package-lock.json | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 46e21f23e..cb1761aaa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -914,9 +914,9 @@ }, "node_modules/ckeditor": { "name": "ckeditor4", - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/ckeditor4/-/ckeditor4-4.23.0.tgz", - "integrity": "sha512-K9DUzTa7roj8JffKLm6nOxDF02aPURDK8m7oFibvvkyAaomj24qOgpVdt7yvszmIubeJLbAB6q4k7Euk8jzD1A==" + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/ckeditor4/-/ckeditor4-4.22.1.tgz", + "integrity": "sha512-Yj4vTHX5YxHwc48gNqUqTm+KLkRr9tuyb4O2VIABu4oKHWRNVIdLdy6vUNe/XNx+RiTavMejfA1MVOU/MxLjqQ==" }, "node_modules/class-utils": { "version": "0.3.6", @@ -4589,11 +4589,6 @@ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" }, - "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" - }, "node_modules/union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", From dc0bf5533d3cf6793748035c150022c268525e35 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Wed, 18 Oct 2023 15:35:05 +0200 Subject: [PATCH 14/28] Correct wording for integrated diagram --- package-lock.json | 27 +++++++++++++++++---------- package.json | 2 +- www/common/sframe-app-framework.js | 4 +++- www/diagram/inner.js | 2 +- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index cb1761aaa..d7547442c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "components-font-awesome": "^4.6.3", "croppie": "^2.5.0", "dragula": "3.7.2", - "drawio": "github:cryptpad/drawio-npm#npm-21.8.2", + "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+1", "express": "~4.18.2", "file-saver": "1.3.1", "fs-extra": "^7.0.0", @@ -106,9 +106,9 @@ } }, "node_modules/@types/http-proxy": { - "version": "1.17.12", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.12.tgz", - "integrity": "sha512-kQtujO08dVtQ2wXAuSFfk9ASy3sug4+ogFR8Kd8UgP8PEuc1/G/8yjYRmp//PcDNJEUKOza/MrQu15bouEUCiw==", + "version": "1.17.13", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.13.tgz", + "integrity": "sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==", "dependencies": { "@types/node": "*" } @@ -120,9 +120,12 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.6.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.3.tgz", - "integrity": "sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA==" + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "dependencies": { + "undici-types": "~5.25.1" + } }, "node_modules/@xmldom/xmldom": { "version": "0.8.10", @@ -1344,9 +1347,8 @@ } }, "node_modules/drawio": { - "name": "drawio-cp", - "version": "21.7.5", - "resolved": "git+ssh://git@github.com/cryptpad/drawio-npm.git#b430ab78be9944f19721c3489c9ce95bc1abe2ca" + "version": "21.8.2+1", + "resolved": "git+ssh://git@github.com/cryptpad/drawio-npm.git#c1708e16bb816dd3bc9b95bd8f3ecf33216d8597" }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", @@ -4589,6 +4591,11 @@ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" }, + "node_modules/undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" + }, "node_modules/union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", diff --git a/package.json b/package.json index f1f36b015..cecc49fd1 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "requirejs-plugins": "^1.0.2", "scrypt-async": "1.2.0", "sortablejs": "^1.6.0", - "drawio": "github:cryptpad/drawio-npm#npm-21.8.2", + "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+1", "pako": "^2.1.0", "x2js": "^3.4.4" }, diff --git a/www/common/sframe-app-framework.js b/www/common/sframe-app-framework.js index 78d9bbb2f..27147ce51 100644 --- a/www/common/sframe-app-framework.js +++ b/www/common/sframe-app-framework.js @@ -1121,7 +1121,7 @@ define([ start: evStart.fire, // Call this, when the user wants to add an image from drive. - insertImage: function(data, cb) { // TODO Move function somwhere else + insertImage: function(data, cb) { require(['/common/image-dialog.js'], function(imageDialog) { imageDialog.openImageDialog(common, integrationChannel, data, cb); }); @@ -1130,6 +1130,8 @@ define([ // Determine the internal state of the framework. getState: function () { return state; }, + isIntegrated: function() { return cpNfInner.metadataMgr.getPrivateData().integration; }, + // Internals _: { sfCommon: common, diff --git a/www/diagram/inner.js b/www/diagram/inner.js index 411ad21b6..f7b2c83ac 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -184,8 +184,8 @@ define([ stealth: 1, embed: 1, drafts: 0, - // plugins: 0, p: 'cryptpad', + integrated: framework.isIntegrated() ? 'true' : 'false', chrome: framework.isReadOnly() ? 0 : 1, dark: window.CryptPad_theme === "dark" ? 1 : 0, From 98735a2f6ca1b610324353d71e53a1d64d92aad3 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Thu, 19 Oct 2023 08:52:30 +0200 Subject: [PATCH 15/28] Fix lint warnings --- www/common/image-dialog.js | 4 +++- www/common/onlyoffice/inner.js | 1 - www/diagram/inner.js | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/www/common/image-dialog.js b/www/common/image-dialog.js index 246f7f387..df7d13aea 100644 --- a/www/common/image-dialog.js +++ b/www/common/image-dialog.js @@ -1,9 +1,11 @@ +/* globals nacl */ + define([ '/common/common-util.js', '/file/file-crypto.js', ], function( Util, - FileCrypto, + FileCrypto ) { const setBlobType = (blob, mimeType) => { diff --git a/www/common/onlyoffice/inner.js b/www/common/onlyoffice/inner.js index 6de5d2e68..874f30938 100644 --- a/www/common/onlyoffice/inner.js +++ b/www/common/onlyoffice/inner.js @@ -1365,7 +1365,6 @@ define([ endSaveChanges: true, isExcel: true, deleteIndex: null, - excelAdditionalInfo: null, unlock: false, releaseLocks: true, reSave: true, diff --git a/www/diagram/inner.js b/www/diagram/inner.js index f7b2c83ac..1ac1a5bed 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -56,7 +56,6 @@ define([ // This is the main initialization loop var onFrameworkReady = function (framework) { - const common = framework._.sfCommon; var EMPTY_DRAWIO = ""; var drawioFrame = document.querySelector('#cp-app-diagram-content'); var x2js = new X2JS(); From 049fa08250eadcaddbc560557b92674966451cb0 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Wed, 8 Nov 2023 15:38:52 +0100 Subject: [PATCH 16/28] WIP build cryptpad: urls for images --- package-lock.json | 9 ++-- package.json | 2 +- www/common/image-dialog.js | 94 ++++++++++++++++++++++++++++---------- 3 files changed, 78 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index d7547442c..ba74fc690 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "components-font-awesome": "^4.6.3", "croppie": "^2.5.0", "dragula": "3.7.2", - "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+1", + "drawio": "file:../drawio-npm", "express": "~4.18.2", "file-saver": "1.3.1", "fs-extra": "^7.0.0", @@ -68,6 +68,9 @@ "url": "https://opencollective.com/cryptpad" } }, + "../drawio-npm": { + "version": "21.8.2+1" + }, "node_modules/@mcrowe/minibloom": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@mcrowe/minibloom/-/minibloom-0.2.0.tgz", @@ -1347,8 +1350,8 @@ } }, "node_modules/drawio": { - "version": "21.8.2+1", - "resolved": "git+ssh://git@github.com/cryptpad/drawio-npm.git#c1708e16bb816dd3bc9b95bd8f3ecf33216d8597" + "resolved": "../drawio-npm", + "link": true }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", diff --git a/package.json b/package.json index cecc49fd1..19f583950 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "requirejs-plugins": "^1.0.2", "scrypt-async": "1.2.0", "sortablejs": "^1.6.0", - "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+1", + "drawio": "file:../drawio-npm", "pako": "^2.1.0", "x2js": "^3.4.4" }, diff --git a/www/common/image-dialog.js b/www/common/image-dialog.js index df7d13aea..950e09f48 100644 --- a/www/common/image-dialog.js +++ b/www/common/image-dialog.js @@ -3,17 +3,64 @@ define([ '/common/common-util.js', '/file/file-crypto.js', + '/common/common-hash.js', ], function( Util, - FileCrypto + FileCrypto, + Hash ) { + const getCryptPadUrl = function(src, key, type) { + const url = new URL(src); + const params = new URLSearchParams(); + params.set('type', type); + url.search = params.toString(); + url.protocol = url.protocol === 'https:' ? 'cryptpads:' : 'cryptpad:'; + url.hash = key; + return url.href; + }; + + const parseCryptPadUrl = function(href) { + const url = new URL(href); + url.protocol = url.protocol === 'cryptpads:' ? 'https:' : 'http:'; + const key = url.hash.substring(1); // remove leading '#' + const type = url.searchParams.get('type'); + url.search = ''; + url.hash = ''; + return { src: url.href, key, type }; + } + const setBlobType = (blob, mimeType) => { const fixedBlob = new Blob([blob], {type: mimeType}); return fixedBlob; }; - const getImage = function(common, data, callback) { + const loadImage = function(common, href) { + return new Promise((resolve, reject) => { + const { src, key, type } = parseCryptPadUrl(href); + Util.fetch(src, function (err, u8) { + if (err) { + console.error(err); + return void reject(err); + } + try { + FileCrypto.decrypt(u8, nacl.util.decodeBase64(key), (err, res) => { + if (err || !res.content) { + console.error("Decrypting failed"); + return void reject(err); + } + + resolve(setBlobType(res.content, type)); + }); + } catch (e) { + console.error(e); + reject(err); + } + }, void 0, common.getCache()); + }); + }; + + const getImage = function(common, data, callback) { // TODO remove Util.fetch(data.src, function (err, u8) { if (err) { console.error(err); @@ -35,29 +82,30 @@ define([ }, void 0, common.getCache()); }; - return { - openImageDialog: function(common, integrationChannel, data, cb) { - if (integrationChannel) { - const ignoreFirstParam = (_, image) => cb(image); - integrationChannel.query('Q_INTEGRATION_ON_INSERT_IMAGE', data, ignoreFirstParam, {raw: true}); - return; + const openImageDialog = function(common, integrationChannel, data, cb) { + if (integrationChannel) { + const ignoreFirstParam = (_, image) => cb(image); + integrationChannel.query('Q_INTEGRATION_ON_INSERT_IMAGE', data, ignoreFirstParam, {raw: true}); + return; + } + common.openFilePicker({ + types: ['file'], + where: ['root'], + filter: { + fileType: ['image/', 'application/x-drawio'] } - common.openFilePicker({ - types: ['file'], - where: ['root'], - filter: { - fileType: ['image/', 'application/x-drawio'] - } - }, (data) => { - getImage(common, data, function(blob) { - common.setPadAttribute('atime', +new Date(), null, data.href); - cb({ - name: data.name, - fileType: data.fileType, - blob: blob - }); + }, (data) => { + loadImage(common, getCryptPadUrl(data.src, data.key, data.fileType)).then((blob) => { + cb({ + name: data.name, + fileType: data.fileType, + blob: blob }); }); - } + }); + }; + + return { + openImageDialog, }; }); From 3d022013aa741d78ca698992964a90c1a7d19e93 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Thu, 9 Nov 2023 11:46:27 +0100 Subject: [PATCH 17/28] WIP pass urls instead of blobs to draw.io --- www/common/image-dialog.js | 96 ++------------------------------------ www/diagram/inner.js | 60 ++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 96 deletions(-) diff --git a/www/common/image-dialog.js b/www/common/image-dialog.js index 950e09f48..4a648e0d5 100644 --- a/www/common/image-dialog.js +++ b/www/common/image-dialog.js @@ -1,86 +1,4 @@ -/* globals nacl */ - -define([ - '/common/common-util.js', - '/file/file-crypto.js', - '/common/common-hash.js', -], function( - Util, - FileCrypto, - Hash -) { - - const getCryptPadUrl = function(src, key, type) { - const url = new URL(src); - const params = new URLSearchParams(); - params.set('type', type); - url.search = params.toString(); - url.protocol = url.protocol === 'https:' ? 'cryptpads:' : 'cryptpad:'; - url.hash = key; - return url.href; - }; - - const parseCryptPadUrl = function(href) { - const url = new URL(href); - url.protocol = url.protocol === 'cryptpads:' ? 'https:' : 'http:'; - const key = url.hash.substring(1); // remove leading '#' - const type = url.searchParams.get('type'); - url.search = ''; - url.hash = ''; - return { src: url.href, key, type }; - } - - const setBlobType = (blob, mimeType) => { - const fixedBlob = new Blob([blob], {type: mimeType}); - return fixedBlob; - }; - - const loadImage = function(common, href) { - return new Promise((resolve, reject) => { - const { src, key, type } = parseCryptPadUrl(href); - Util.fetch(src, function (err, u8) { - if (err) { - console.error(err); - return void reject(err); - } - try { - FileCrypto.decrypt(u8, nacl.util.decodeBase64(key), (err, res) => { - if (err || !res.content) { - console.error("Decrypting failed"); - return void reject(err); - } - - resolve(setBlobType(res.content, type)); - }); - } catch (e) { - console.error(e); - reject(err); - } - }, void 0, common.getCache()); - }); - }; - - const getImage = function(common, data, callback) { // TODO remove - Util.fetch(data.src, function (err, u8) { - if (err) { - console.error(err); - return void callback(""); - } - try { - FileCrypto.decrypt(u8, nacl.util.decodeBase64(data.key), (err, res) => { - if (err || !res.content) { - console.error("Decrypting failed"); - return void callback(""); - } - - callback(setBlobType(res.content, data.fileType)); - }); - } catch (e) { - console.error(e); - callback(""); - } - }, void 0, common.getCache()); - }; +define([], function() { const openImageDialog = function(common, integrationChannel, data, cb) { if (integrationChannel) { @@ -92,17 +10,9 @@ define([ types: ['file'], where: ['root'], filter: { - fileType: ['image/', 'application/x-drawio'] + fileType: ['image/'] } - }, (data) => { - loadImage(common, getCryptPadUrl(data.src, data.key, data.fileType)).then((blob) => { - cb({ - name: data.name, - fileType: data.fileType, - blob: blob - }); - }); - }); + }, cb); }; return { diff --git a/www/diagram/inner.js b/www/diagram/inner.js index 1ac1a5bed..a30fa01f7 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -4,6 +4,8 @@ define([ '/customize/messages.js', // translation keys '/components/pako/dist/pako.min.js', '/components/x2js/x2js.js', + '/common/common-util.js', + '/file/file-crypto.js', '/components/tweetnacl/nacl-fast.min.js', 'less!/diagram/app-diagram.less', 'css!/diagram/drawio.css', @@ -11,7 +13,9 @@ define([ Framework, Messages, pako, - X2JS) { + X2JS, + Util, + FileCrypto) { const Nacl = window.nacl; const APP = window.APP = {}; @@ -122,10 +126,60 @@ define([ autosave: onDrawioAutosave, }; + const getCryptPadUrl = function(src, key, type) { + const url = new URL(src); + const params = new URLSearchParams(); + params.set('type', type); + url.search = params.toString(); + url.protocol = url.protocol === 'https:' ? 'cryptpads:' : 'cryptpad:'; + url.hash = key; + return url.href; + }; + + const parseCryptPadUrl = function(href) { + const url = new URL(href); + url.protocol = url.protocol === 'cryptpads:' ? 'https:' : 'http:'; + const key = url.hash.substring(1); // remove leading '#' + const type = url.searchParams.get('type'); + url.search = ''; + url.hash = ''; + return { src: url.href, key, type }; + } + + const setBlobType = (blob, mimeType) => { + const fixedBlob = new Blob([blob], {type: mimeType}); + return fixedBlob; + }; + + APP.loadImage = function(href) { + return new Promise((resolve, reject) => { + const { src, key, type } = parseCryptPadUrl(href); + Util.fetch(src, function (err, u8) { + if (err) { + console.error(err); + return void reject(err); + } + try { + FileCrypto.decrypt(u8, nacl.util.decodeBase64(key), (err, res) => { + if (err || !res.content) { + console.error("Decrypting failed"); + return void reject(err); + } + + resolve(setBlobType(res.content, type)); + }); + } catch (e) { + console.error(e); + reject(err); + } + }, void 0, framework._.sfCommon.getCache()); + }); + }; + APP.addImage = function() { return new Promise((resolve) => { - framework.insertImage({}, (image) => { - resolve(image); + framework.insertImage({}, (imageData) => { + resolve(getCryptPadUrl(imageData.src, imageData.key, imageData.fileType)); }); }); }; From 4924c8664a35b4cc77ebeeff17afdbf2a57999be Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Thu, 16 Nov 2023 10:23:22 +0100 Subject: [PATCH 18/28] Simplify CryptPad URLs --- www/diagram/inner.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/www/diagram/inner.js b/www/diagram/inner.js index a30fa01f7..2af3caef4 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -130,15 +130,16 @@ define([ const url = new URL(src); const params = new URLSearchParams(); params.set('type', type); + params.set('protocol', url.protocol); url.search = params.toString(); - url.protocol = url.protocol === 'https:' ? 'cryptpads:' : 'cryptpad:'; + url.protocol = 'cryptpad:'; url.hash = key; return url.href; }; const parseCryptPadUrl = function(href) { const url = new URL(href); - url.protocol = url.protocol === 'cryptpads:' ? 'https:' : 'http:'; + url.protocol = url.searchParams.get('protocol'); const key = url.hash.substring(1); // remove leading '#' const type = url.searchParams.get('type'); url.search = ''; From 4407b5c048357bd0404d943c1debc5ba54b3d478 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Tue, 28 Nov 2023 09:57:01 +0100 Subject: [PATCH 19/28] Handle old version Nextcloud image import --- package-lock.json | 483 +++++++++++-------------------------- package.json | 2 +- www/common/image-dialog.js | 6 +- www/diagram/inner.js | 11 +- 4 files changed, 156 insertions(+), 346 deletions(-) diff --git a/package-lock.json b/package-lock.json index ba74fc690..bb832d524 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "components-font-awesome": "^4.6.3", "croppie": "^2.5.0", "dragula": "3.7.2", - "drawio": "file:../drawio-npm", + "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+2", "express": "~4.18.2", "file-saver": "1.3.1", "fs-extra": "^7.0.0", @@ -68,9 +68,6 @@ "url": "https://opencollective.com/cryptpad" } }, - "../drawio-npm": { - "version": "21.8.2+1" - }, "node_modules/@mcrowe/minibloom": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@mcrowe/minibloom/-/minibloom-0.2.0.tgz", @@ -109,9 +106,9 @@ } }, "node_modules/@types/http-proxy": { - "version": "1.17.13", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.13.tgz", - "integrity": "sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==", + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", "dependencies": { "@types/node": "*" } @@ -123,11 +120,11 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "version": "20.10.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", + "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", "dependencies": { - "undici-types": "~5.25.1" + "undici-types": "~5.26.4" } }, "node_modules/@xmldom/xmldom": { @@ -798,12 +795,13 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -951,66 +949,17 @@ "node": ">=0.10.0" } }, - "node_modules/class-utils/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/class-utils/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/cli": { @@ -1041,9 +990,9 @@ } }, "node_modules/codemirror": { - "version": "5.65.15", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.15.tgz", - "integrity": "sha512-YC4EHbbwQeubZzxLl5G4nlbLc1T21QTrKGaOal/Pkm9dVDMZXMH7+ieSPEOZCtO9I68i8/oteJKOxzHC2zR+0g==" + "version": "5.65.16", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.16.tgz", + "integrity": "sha512-br21LjYmSlVL0vFCPWPfhzUCT34FM/pAdK7rRIZwa0rrtrIdotvP4Oh4GUHsu2E3IrQMCfRkL/fN3ytMNxVQvg==" }, "node_modules/collection-visit": { "version": "1.0.0", @@ -1064,9 +1013,12 @@ "dev": true }, "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/components-font-awesome": { "version": "4.7.0", @@ -1227,6 +1179,19 @@ "node": ">=0.10" } }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", @@ -1350,8 +1315,8 @@ } }, "node_modules/drawio": { - "resolved": "../drawio-npm", - "link": true + "version": "21.8.2+2", + "resolved": "git+ssh://git@github.com/cryptpad/drawio-npm.git#d216a8ac7ac190ec1d6a61b06651916a0aa3d09e" }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", @@ -1466,66 +1431,17 @@ "node": ">=0.10.0" } }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/expand-brackets/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/express": { @@ -1916,14 +1832,14 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2022,17 +1938,31 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.2.0.tgz", "integrity": "sha512-zGRpnr2l5w/s8PxkrquUJoVeR06KvqPelrYqiSyQV7QEBqCYivpb6UzXYWC6JDBVtNFOT0rzJRFhkfJgxzmILA==" }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "engines": { - "node": ">= 0.4.0" + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { @@ -2120,6 +2050,17 @@ "node": ">=0.10.0" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/html2canvas": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", @@ -2277,22 +2218,14 @@ } }, "node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", + "integrity": "sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==", "dependencies": { - "kind-of": "^6.0.0" + "hasown": "^2.0.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, "node_modules/is-arrayish": { @@ -2307,43 +2240,26 @@ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz", + "integrity": "sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==", "dependencies": { - "kind-of": "^6.0.0" + "hasown": "^2.0.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-descriptor/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/is-directory": { @@ -3133,47 +3049,16 @@ "node": ">=0.10.0" } }, - "node_modules/object-copy/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-copy/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/object-copy/node_modules/kind-of": { @@ -3188,9 +3073,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.0.tgz", - "integrity": "sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3945,6 +3830,20 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/set-getter": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.1.tgz", @@ -4086,66 +3985,17 @@ "node": ">=0.10.0" } }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/snapdragon/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dev": true, "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/snapdragon/node_modules/source-map": { @@ -4158,9 +4008,9 @@ } }, "node_modules/sortablejs": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz", - "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==" + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.1.tgz", + "integrity": "sha512-P5Cjvb0UG1ZVNiDPj/n4V+DinttXG6K8n7vM/HQf0C25K3YKQTQY6fsr/sEGsJGpQ9exmPxluHxKBc0mLKU1lQ==" }, "node_modules/sortify": { "version": "1.0.4", @@ -4266,61 +4116,16 @@ "node": ">=0.10.0" } }, - "node_modules/static-extend/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/static-extend/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/statuses": { @@ -4595,9 +4400,9 @@ "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" }, "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/union-value": { "version": "1.0.1", diff --git a/package.json b/package.json index 19f583950..94a4df7e9 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "requirejs-plugins": "^1.0.2", "scrypt-async": "1.2.0", "sortablejs": "^1.6.0", - "drawio": "file:../drawio-npm", + "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+2", "pako": "^2.1.0", "x2js": "^3.4.4" }, diff --git a/www/common/image-dialog.js b/www/common/image-dialog.js index 4a648e0d5..31de9b6a5 100644 --- a/www/common/image-dialog.js +++ b/www/common/image-dialog.js @@ -2,8 +2,10 @@ define([], function() { const openImageDialog = function(common, integrationChannel, data, cb) { if (integrationChannel) { - const ignoreFirstParam = (_, image) => cb(image); - integrationChannel.query('Q_INTEGRATION_ON_INSERT_IMAGE', data, ignoreFirstParam, {raw: true}); + const handleImage = (_, image) => { + cb(image); + }; + integrationChannel.query('Q_INTEGRATION_ON_INSERT_IMAGE', data, handleImage, {raw: true}); return; } common.openFilePicker({ diff --git a/www/diagram/inner.js b/www/diagram/inner.js index 2af3caef4..2dd854e27 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -132,9 +132,8 @@ define([ params.set('type', type); params.set('protocol', url.protocol); url.search = params.toString(); - url.protocol = 'cryptpad:'; url.hash = key; - return url.href; + return url.href.replace(/https?:\/\//, 'cryptpad://'); }; const parseCryptPadUrl = function(href) { @@ -161,7 +160,7 @@ define([ return void reject(err); } try { - FileCrypto.decrypt(u8, nacl.util.decodeBase64(key), (err, res) => { + FileCrypto.decrypt(u8, Nacl.util.decodeBase64(key), (err, res) => { if (err || !res.content) { console.error("Decrypting failed"); return void reject(err); @@ -180,7 +179,11 @@ define([ APP.addImage = function() { return new Promise((resolve) => { framework.insertImage({}, (imageData) => { - resolve(getCryptPadUrl(imageData.src, imageData.key, imageData.fileType)); + if (imageData.blob) { + resolve(imageData.blob); + } else { + resolve(getCryptPadUrl(imageData.src, imageData.key, imageData.fileType)); + } }); }); }; From 15c3d9433e4f4b96a1d653c44be04d29e539cde0 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Wed, 6 Dec 2023 15:48:04 +0100 Subject: [PATCH 20/28] Embed images in diagrams when exporting them --- www/diagram/export.js | 80 +++++++++++++++++++++++++++++++++++++++++-- www/diagram/inner.js | 70 +++++++------------------------------ www/diagram/util.js | 66 +++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+), 61 deletions(-) create mode 100644 www/diagram/util.js diff --git a/www/diagram/export.js b/www/diagram/export.js index 1b7089559..07b12a463 100644 --- a/www/diagram/export.js +++ b/www/diagram/export.js @@ -4,15 +4,89 @@ define([ '/components/x2js/x2js.js', + '/diagram/util.js', ], function ( - X2JS) { + X2JS, + DiagramUtil, +) { const x2js = new X2JS(); const jsonContentAsXML = (content) => x2js.js2xml(content); + const parseDrawioStyle = (styleAttrValue) => { + if (!styleAttrValue) return; + + const result = {}; + for (const part of styleAttrValue.split(';')) { + const s = part.split(/=(.*)/); + result[s[0]] = s[1]; + } + + return result; + }; + + const stringifyDrawioStyle = (styleAttrValue) => { + const parts = []; + for (const [key, value] of Object.entries(styleAttrValue)) { + parts.push(`${key}=${value}`); + } + return parts.join(';'); + }; + + const findCryptPadImages = (doc) => { + return Array.from(doc .querySelectorAll('mxCell')) + .map((element) => [element, parseDrawioStyle(element.getAttribute('style'))]) + .filter(([element, style]) => style && style.image && style.image.startsWith('cryptpad://')) + }; + + const parseXML = (xmlStr) => { + const parser = new DOMParser(); + const doc = parser.parseFromString(xmlStr, "application/xml"); + const errorNode = doc.querySelector("parsererror"); + if (errorNode) { + throw Error("error while parsing " + errorNode); + } + return doc; + }; + + const blobToImage = (blob) => { + return new Promise((resolve) => { + const reader = new FileReader(); + reader.onloadend = function() { + resolve(reader.result); + }; + reader.readAsDataURL(blob); + }); + }; + + const loadImage = async (url) => { + const blob = await DiagramUtil.loadImage(url); + return await blobToImage(blob); + }; + return { - main: function(userDoc, cb) { + main: async function(userDoc, cb) { delete userDoc.metadata; - cb(jsonContentAsXML(userDoc), '.drawio'); + + const xml = jsonContentAsXML(userDoc); + + let doc; + try { + doc = parseXML(xml); + } catch(e) { + console.error(e); + return; + } + + const elements = findCryptPadImages(doc) + .map(([element, style]) => [element, style, loadImage(style.image)]); + + for (const [element, style, imagePromise] of elements) { + const dataUrl = await imagePromise; + style.image = dataUrl.replace(';base64', ''); // ';' breaks draw.ios style format + element.setAttribute('style', stringifyDrawioStyle(style)); + } + + cb(new XMLSerializer().serializeToString(doc), '.drawio'); } }; }); diff --git a/www/diagram/inner.js b/www/diagram/inner.js index 7a7baade9..ace3d6bae 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -8,8 +8,7 @@ define([ '/customize/messages.js', // translation keys '/components/pako/dist/pako.min.js', '/components/x2js/x2js.js', - '/common/common-util.js', - '/file/file-crypto.js', + '/diagram/util.js', '/components/tweetnacl/nacl-fast.min.js', 'less!/diagram/app-diagram.less', 'css!/diagram/drawio.css', @@ -18,8 +17,8 @@ define([ Messages, pako, X2JS, - Util, - FileCrypto) { + DiagramUtil, +) { const Nacl = window.nacl; const APP = window.APP = {}; @@ -130,63 +129,14 @@ define([ autosave: onDrawioAutosave, }; - const getCryptPadUrl = function(src, key, type) { - const url = new URL(src); - const params = new URLSearchParams(); - params.set('type', type); - params.set('protocol', url.protocol); - url.search = params.toString(); - url.hash = key; - return url.href.replace(/https?:\/\//, 'cryptpad://'); - }; - - const parseCryptPadUrl = function(href) { - const url = new URL(href); - url.protocol = url.searchParams.get('protocol'); - const key = url.hash.substring(1); // remove leading '#' - const type = url.searchParams.get('type'); - url.search = ''; - url.hash = ''; - return { src: url.href, key, type }; - } - - const setBlobType = (blob, mimeType) => { - const fixedBlob = new Blob([blob], {type: mimeType}); - return fixedBlob; - }; - - APP.loadImage = function(href) { - return new Promise((resolve, reject) => { - const { src, key, type } = parseCryptPadUrl(href); - Util.fetch(src, function (err, u8) { - if (err) { - console.error(err); - return void reject(err); - } - try { - FileCrypto.decrypt(u8, Nacl.util.decodeBase64(key), (err, res) => { - if (err || !res.content) { - console.error("Decrypting failed"); - return void reject(err); - } - - resolve(setBlobType(res.content, type)); - }); - } catch (e) { - console.error(e); - reject(err); - } - }, void 0, framework._.sfCommon.getCache()); - }); - }; - + APP.loadImage = DiagramUtil.loadImage; APP.addImage = function() { return new Promise((resolve) => { framework.insertImage({}, (imageData) => { if (imageData.blob) { resolve(imageData.blob); } else { - resolve(getCryptPadUrl(imageData.src, imageData.key, imageData.fileType)); + resolve(DiagramUtil.getCryptPadUrl(imageData.src, imageData.key, imageData.fileType)); } }); }); @@ -218,9 +168,13 @@ define([ framework.setFileExporter( '.drawio', - () => { - return new Blob([jsonContentAsXML(lastContent)], {type: 'application/x-drawio'}); - } + (cb) => { + require(['/diagram/export.js'], (exporter) => { + exporter.main(lastContent, (xml) => { + cb(new Blob([xml], {type: 'application/x-drawio'})); + }); + }); + }, true ); framework.onEditableChange(function () { diff --git a/www/diagram/util.js b/www/diagram/util.js new file mode 100644 index 000000000..7099183af --- /dev/null +++ b/www/diagram/util.js @@ -0,0 +1,66 @@ +define([ + '/common/common-util.js', + '/file/file-crypto.js', + '/common/outer/cache-store.js', +], function ( + Util, + FileCrypto, + Cache, +) { + const Nacl = window.nacl; + + const parseCryptPadUrl = function(href) { + const url = new URL(href); + const protocol = url.searchParams.get('protocol'); + const key = url.hash.substring(1); // remove leading '#' + const type = url.searchParams.get('type'); + url.search = ''; + url.hash = ''; + return { src: url.href.replace(/cryptpad?:\/\//, `${protocol}//`), key, type }; + } + + const getCryptPadUrl = function(src, key, type) { + const url = new URL(src); + const params = new URLSearchParams(); + params.set('type', type); + params.set('protocol', url.protocol); + url.search = params.toString(); + url.hash = key; + return url.href.replace(/https?:\/\//, 'cryptpad://'); + }; + + const setBlobType = (blob, mimeType) => { + const fixedBlob = new Blob([blob], {type: mimeType}); + return fixedBlob; + }; + + return { + parseCryptPadUrl, + getCryptPadUrl, + + loadImage: function(href) { + return new Promise((resolve, reject) => { + const { src, key, type } = parseCryptPadUrl(href); + Util.fetch(src, function (err, u8) { + if (err) { + console.error(err); + return void reject(err); + } + try { + FileCrypto.decrypt(u8, Nacl.util.decodeBase64(key), (err, res) => { + if (err || !res.content) { + console.error("Decrypting failed"); + return void reject(err); + } + + resolve(setBlobType(res.content, type)); + }); + } catch (e) { + console.error(e); + reject(err); + } + }, void 0, Cache); + }); + } + }; +}); From 5c8e8c5bff65e85f837dac1d3dae938df4d3bbc1 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Thu, 7 Dec 2023 09:20:18 +0100 Subject: [PATCH 21/28] Fix eslint warnings --- www/diagram/export.js | 59 +++++++++++++++++++++++-------------------- www/diagram/inner.js | 2 +- www/diagram/util.js | 4 +-- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/www/diagram/export.js b/www/diagram/export.js index 07b12a463..6f59957b0 100644 --- a/www/diagram/export.js +++ b/www/diagram/export.js @@ -7,13 +7,15 @@ define([ '/diagram/util.js', ], function ( X2JS, - DiagramUtil, + DiagramUtil ) { const x2js = new X2JS(); const jsonContentAsXML = (content) => x2js.js2xml(content); const parseDrawioStyle = (styleAttrValue) => { - if (!styleAttrValue) return; + if (!styleAttrValue) { + return; + } const result = {}; for (const part of styleAttrValue.split(';')) { @@ -32,10 +34,31 @@ define([ return parts.join(';'); }; - const findCryptPadImages = (doc) => { + const blobToImage = (blob) => { + return new Promise((resolve) => { + const reader = new FileReader(); + reader.onloadend = function() { + resolve(reader.result); + }; + reader.readAsDataURL(blob); + }); + }; + + const loadImage = (url) => { + return DiagramUtil.loadImage(url).then((blob) => blobToImage(blob)); + }; + + const loadCryptPadImages = (doc) => { return Array.from(doc .querySelectorAll('mxCell')) .map((element) => [element, parseDrawioStyle(element.getAttribute('style'))]) .filter(([element, style]) => style && style.image && style.image.startsWith('cryptpad://')) + .map(([element, style]) => { + return loadImage(style.image) + .then((dataUrl) => { + style.image = dataUrl.replace(';base64', ''); // ';' breaks draw.ios style format + element.setAttribute('style', stringifyDrawioStyle(style)); + }); + }); }; const parseXML = (xmlStr) => { @@ -48,23 +71,8 @@ define([ return doc; }; - const blobToImage = (blob) => { - return new Promise((resolve) => { - const reader = new FileReader(); - reader.onloadend = function() { - resolve(reader.result); - }; - reader.readAsDataURL(blob); - }); - }; - - const loadImage = async (url) => { - const blob = await DiagramUtil.loadImage(url); - return await blobToImage(blob); - }; - return { - main: async function(userDoc, cb) { + main: function(userDoc, cb) { delete userDoc.metadata; const xml = jsonContentAsXML(userDoc); @@ -77,16 +85,11 @@ define([ return; } - const elements = findCryptPadImages(doc) - .map(([element, style]) => [element, style, loadImage(style.image)]); + const promises = loadCryptPadImages(doc); - for (const [element, style, imagePromise] of elements) { - const dataUrl = await imagePromise; - style.image = dataUrl.replace(';base64', ''); // ';' breaks draw.ios style format - element.setAttribute('style', stringifyDrawioStyle(style)); - } - - cb(new XMLSerializer().serializeToString(doc), '.drawio'); + Promise.all(promises).then(() => { + cb(new XMLSerializer().serializeToString(doc), '.drawio'); + }); } }; }); diff --git a/www/diagram/inner.js b/www/diagram/inner.js index ace3d6bae..387abaa59 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -17,7 +17,7 @@ define([ Messages, pako, X2JS, - DiagramUtil, + DiagramUtil ) { const Nacl = window.nacl; const APP = window.APP = {}; diff --git a/www/diagram/util.js b/www/diagram/util.js index 7099183af..ec0249446 100644 --- a/www/diagram/util.js +++ b/www/diagram/util.js @@ -5,7 +5,7 @@ define([ ], function ( Util, FileCrypto, - Cache, + Cache ) { const Nacl = window.nacl; @@ -17,7 +17,7 @@ define([ url.search = ''; url.hash = ''; return { src: url.href.replace(/cryptpad?:\/\//, `${protocol}//`), key, type }; - } + }; const getCryptPadUrl = function(src, key, type) { const url = new URL(src); From 3fedc35bed14732de32ad5958614e4e7b656bd5f Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Thu, 7 Dec 2023 09:27:00 +0100 Subject: [PATCH 22/28] Disable internal diagram export which is broken for images --- package-lock.json | 10 +++++----- package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index bb832d524..2807a8521 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "components-font-awesome": "^4.6.3", "croppie": "^2.5.0", "dragula": "3.7.2", - "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+2", + "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+3", "express": "~4.18.2", "file-saver": "1.3.1", "fs-extra": "^7.0.0", @@ -120,9 +120,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.10.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", - "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", + "version": "20.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", + "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", "dependencies": { "undici-types": "~5.26.4" } @@ -1316,7 +1316,7 @@ }, "node_modules/drawio": { "version": "21.8.2+2", - "resolved": "git+ssh://git@github.com/cryptpad/drawio-npm.git#d216a8ac7ac190ec1d6a61b06651916a0aa3d09e" + "resolved": "git+ssh://git@github.com/cryptpad/drawio-npm.git#20bb1d9ac9ee504002fa39c44c6585b6ac7f2282" }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", diff --git a/package.json b/package.json index 94a4df7e9..b076ce14d 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "requirejs-plugins": "^1.0.2", "scrypt-async": "1.2.0", "sortablejs": "^1.6.0", - "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+2", + "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+3", "pako": "^2.1.0", "x2js": "^3.4.4" }, From 4385a9dd5a41e658a3c9334981766c9d96b1b77a Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Fri, 8 Dec 2023 15:01:34 +0100 Subject: [PATCH 23/28] WIP --- package-lock.json | 9 ++++++--- package.json | 2 +- www/diagram/inner.js | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2807a8521..a1eed724c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "components-font-awesome": "^4.6.3", "croppie": "^2.5.0", "dragula": "3.7.2", - "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+3", + "drawio": "file:../drawio-npm", "express": "~4.18.2", "file-saver": "1.3.1", "fs-extra": "^7.0.0", @@ -68,6 +68,9 @@ "url": "https://opencollective.com/cryptpad" } }, + "../drawio-npm": { + "version": "21.8.2+3" + }, "node_modules/@mcrowe/minibloom": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@mcrowe/minibloom/-/minibloom-0.2.0.tgz", @@ -1315,8 +1318,8 @@ } }, "node_modules/drawio": { - "version": "21.8.2+2", - "resolved": "git+ssh://git@github.com/cryptpad/drawio-npm.git#20bb1d9ac9ee504002fa39c44c6585b6ac7f2282" + "resolved": "../drawio-npm", + "link": true }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", diff --git a/package.json b/package.json index b076ce14d..19f583950 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "requirejs-plugins": "^1.0.2", "scrypt-async": "1.2.0", "sortablejs": "^1.6.0", - "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+3", + "drawio": "file:../drawio-npm", "pako": "^2.1.0", "x2js": "^3.4.4" }, diff --git a/www/diagram/inner.js b/www/diagram/inner.js index 387abaa59..ce2842587 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -135,6 +135,8 @@ define([ framework.insertImage({}, (imageData) => { if (imageData.blob) { resolve(imageData.blob); + } else if (imageData.url) { + resolve(imageData.url); } else { resolve(DiagramUtil.getCryptPadUrl(imageData.src, imageData.key, imageData.fileType)); } From a96856bb3d1dba7a76863ae819c42f7e960a3686 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Fri, 22 Dec 2023 09:00:59 +0100 Subject: [PATCH 24/28] Allow loading diagram images from Nextcloud https://github.com/cryptpad/cryptpad/issues/1297 --- lib/defaults.js | 4 ++++ lib/http-worker.js | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/lib/defaults.js b/lib/defaults.js index 3d342a659..b149acabc 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -52,6 +52,10 @@ Default.padContentSecurity = function (Env) { return (Default.commonCSP(Env).join('; ') + "script-src 'self' 'unsafe-eval' 'unsafe-inline' resource: " + Env.httpUnsafeOrigin).replace(/\s+/g, ' '); }; +Default.diagramContentSecurity = function (Env) { + return (Default.commonCSP(Env).join('; ') + "script-src 'self' resource: " + Env.httpUnsafeOrigin).replace('img-src ', 'img-src http: https: ').replace(/\s+/g, ' '); +}; + Default.httpHeaders = function (Env) { return { "X-XSS-Protection": "1; mode=block", diff --git a/lib/http-worker.js b/lib/http-worker.js index fbcacbeb4..be59617e5 100644 --- a/lib/http-worker.js +++ b/lib/http-worker.js @@ -127,6 +127,8 @@ var getHeaders = function (Env, type) { var csp; if (type === 'office') { csp = Default.padContentSecurity(Env); + } else if (type === 'diagram') { + csp = Default.diagramContentSecurity(Env); } else { csp = Default.contentSecurity(Env); } @@ -149,6 +151,8 @@ var setHeaders = function (req, res) { type = 'office'; } else if (/^\/api\/(broadcast|config)/.test(req.url)) { type = 'api'; + } else if (/^\/components\/drawio\/src\/main\/webapp\/index.html.*$/.test(req.url)) { + type = 'diagram'; } else { type = 'standard'; } From e681525b637e4b2e3ed015d4d08bca98d0500445 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Fri, 22 Dec 2023 10:35:39 +0100 Subject: [PATCH 25/28] Upgrade to draw.io 21.8.2+4 --- package-lock.json | 15 ++++++--------- package.json | 2 +- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index a1eed724c..31b83902f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "components-font-awesome": "^4.6.3", "croppie": "^2.5.0", "dragula": "3.7.2", - "drawio": "file:../drawio-npm", + "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+4", "express": "~4.18.2", "file-saver": "1.3.1", "fs-extra": "^7.0.0", @@ -68,9 +68,6 @@ "url": "https://opencollective.com/cryptpad" } }, - "../drawio-npm": { - "version": "21.8.2+3" - }, "node_modules/@mcrowe/minibloom": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@mcrowe/minibloom/-/minibloom-0.2.0.tgz", @@ -123,9 +120,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.10.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.4.tgz", - "integrity": "sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==", + "version": "20.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", + "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", "dependencies": { "undici-types": "~5.26.4" } @@ -1318,8 +1315,8 @@ } }, "node_modules/drawio": { - "resolved": "../drawio-npm", - "link": true + "version": "21.8.2+4", + "resolved": "git+ssh://git@github.com/cryptpad/drawio-npm.git#5555df31ce3a1c6220cefa3aaa16b9a7880bf8b8" }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", diff --git a/package.json b/package.json index 19f583950..183033c13 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "requirejs-plugins": "^1.0.2", "scrypt-async": "1.2.0", "sortablejs": "^1.6.0", - "drawio": "file:../drawio-npm", + "drawio": "github:cryptpad/drawio-npm#npm-21.8.2+4", "pako": "^2.1.0", "x2js": "^3.4.4" }, From 31c509d598b8d0b3eb005a72456f44c66c6e0407 Mon Sep 17 00:00:00 2001 From: Wolfgang Ginolas Date: Thu, 18 Jan 2024 10:49:38 +0100 Subject: [PATCH 26/28] Prevent draw.io from embedding images. --- www/common/{ => inner}/image-dialog.js | 0 www/common/sframe-app-framework.js | 2 +- www/diagram/inner.js | 3 +++ 3 files changed, 4 insertions(+), 1 deletion(-) rename www/common/{ => inner}/image-dialog.js (100%) diff --git a/www/common/image-dialog.js b/www/common/inner/image-dialog.js similarity index 100% rename from www/common/image-dialog.js rename to www/common/inner/image-dialog.js diff --git a/www/common/sframe-app-framework.js b/www/common/sframe-app-framework.js index bb1f4d834..bc082da91 100644 --- a/www/common/sframe-app-framework.js +++ b/www/common/sframe-app-framework.js @@ -1126,7 +1126,7 @@ define([ // Call this, when the user wants to add an image from drive. insertImage: function(data, cb) { - require(['/common/image-dialog.js'], function(imageDialog) { + require(['/common/inner/image-dialog.js'], function(imageDialog) { imageDialog.openImageDialog(common, integrationChannel, data, cb); }); }, diff --git a/www/diagram/inner.js b/www/diagram/inner.js index ce2842587..266123df8 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -209,6 +209,9 @@ define([ noExitBtn: 1, browser: 0, + noDevice: 1, + filesupport: 0, + modified: 'unsavedChanges', proto: 'json', From ebcbf4570e5bcd2d92f40adb8d7e04f5a03b2819 Mon Sep 17 00:00:00 2001 From: yflory Date: Mon, 29 Jan 2024 16:15:56 +0100 Subject: [PATCH 27/28] Remove custom HTTP headers for diagrams --- lib/defaults.js | 4 ---- lib/http-worker.js | 4 ---- 2 files changed, 8 deletions(-) diff --git a/lib/defaults.js b/lib/defaults.js index b149acabc..3d342a659 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -52,10 +52,6 @@ Default.padContentSecurity = function (Env) { return (Default.commonCSP(Env).join('; ') + "script-src 'self' 'unsafe-eval' 'unsafe-inline' resource: " + Env.httpUnsafeOrigin).replace(/\s+/g, ' '); }; -Default.diagramContentSecurity = function (Env) { - return (Default.commonCSP(Env).join('; ') + "script-src 'self' resource: " + Env.httpUnsafeOrigin).replace('img-src ', 'img-src http: https: ').replace(/\s+/g, ' '); -}; - Default.httpHeaders = function (Env) { return { "X-XSS-Protection": "1; mode=block", diff --git a/lib/http-worker.js b/lib/http-worker.js index be59617e5..fbcacbeb4 100644 --- a/lib/http-worker.js +++ b/lib/http-worker.js @@ -127,8 +127,6 @@ var getHeaders = function (Env, type) { var csp; if (type === 'office') { csp = Default.padContentSecurity(Env); - } else if (type === 'diagram') { - csp = Default.diagramContentSecurity(Env); } else { csp = Default.contentSecurity(Env); } @@ -151,8 +149,6 @@ var setHeaders = function (req, res) { type = 'office'; } else if (/^\/api\/(broadcast|config)/.test(req.url)) { type = 'api'; - } else if (/^\/components\/drawio\/src\/main\/webapp\/index.html.*$/.test(req.url)) { - type = 'diagram'; } else { type = 'standard'; } From d2252049c33115ae4174c985198c912fdc7c96bc Mon Sep 17 00:00:00 2001 From: yflory Date: Mon, 29 Jan 2024 17:26:24 +0100 Subject: [PATCH 28/28] Update example nginx --- docs/example-advanced.nginx.conf | 5 ----- 1 file changed, 5 deletions(-) diff --git a/docs/example-advanced.nginx.conf b/docs/example-advanced.nginx.conf index a7c01cd70..c59cf2273 100644 --- a/docs/example-advanced.nginx.conf +++ b/docs/example-advanced.nginx.conf @@ -166,11 +166,6 @@ server { # We've applied other sandboxing techniques to mitigate the risk of running WebAssembly in this privileged scope if ($uri ~ ^\/unsafeiframe\/inner\.html.*$) { set $unsafe 1; } - # draw.io uses inline script tags in it's index.html. The hashes are added here. - if ($uri ~ ^\/components\/drawio\/src\/main\/webapp\/index.html.*$) { - set $scriptSrc "'self' resource: https://${main_domain}"; - } - # privileged contexts allow a few more rights than unprivileged contexts, though limits are still applied if ($unsafe) { set $scriptSrc "'self' 'unsafe-eval' 'unsafe-inline' resource: https://${main_domain}";