From 96de4dffe9cc2037d956ba1e6555f8f12f75a7ce Mon Sep 17 00:00:00 2001 From: ansuz Date: Wed, 11 Jan 2023 13:03:10 +0530 Subject: [PATCH 01/10] fix an inverted not in a non-functional telemetry attribute --- lib/stats.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/stats.js b/lib/stats.js index 16c0058e8..2a8e32ca2 100644 --- a/lib/stats.js +++ b/lib/stats.js @@ -74,7 +74,7 @@ Stats.instanceData = function (Env) { } // Admins can opt-in to providing more detailed information about the extent of the instance's usage - if (!Env.provideAggregateStatistics) { + if (Env.provideAggregateStatistics) { // check how many instances provide stats before we put more work into it data.providesAggregateStatistics = true; } From 38861e5b999677b8f32c56b8f2808955a46b4be4 Mon Sep 17 00:00:00 2001 From: ansuz Date: Wed, 11 Jan 2023 13:19:15 +0530 Subject: [PATCH 02/10] properly omit thumbnails from upload metadata in cases where they would cause the metadata to be too large --- www/file/file-crypto.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/file/file-crypto.js b/www/file/file-crypto.js index 6a0c08816..e5f1c12b2 100644 --- a/www/file/file-crypto.js +++ b/www/file/file-crypto.js @@ -148,7 +148,7 @@ define([ // if metadata is too large, drop the thumbnail. if (plaintext.length > 65535) { var temp = JSON.parse(JSON.stringify(metadata)); - delete metadata.thumbnail; + delete temp.thumbnail; plaintext = Nacl.util.decodeUTF8(JSON.stringify(temp)); } From f079f23fa389c406c747fcb2df35f391468d934f Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 11 Jan 2023 12:44:43 +0100 Subject: [PATCH 03/10] Fix invisible calendar in form closing date --- www/form/app-form.less | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/www/form/app-form.less b/www/form/app-form.less index 78d0f7665..cde12d66d 100644 --- a/www/form/app-form.less +++ b/www/form/app-form.less @@ -25,6 +25,10 @@ } } + .flatpickr-calendar.open { + z-index: 100001 !important; // Alertify is 100000 + } + @palette0: @cp_kanban-color0; // Default bg color for header @form-colors: @cp_form-palette; .form-colors(@form-colors; @index) when (@index > 0){ From a0714b9cc83cdcd3cb94e9f24c273ca9ec7f98f5 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 12 Jan 2023 15:54:16 +0100 Subject: [PATCH 04/10] Prevent type error with the new admin script --- lib/commands/admin-rpc.js | 4 +++- lib/env.js | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/commands/admin-rpc.js b/lib/commands/admin-rpc.js index a05b177a2..7200ce49b 100644 --- a/lib/commands/admin-rpc.js +++ b/lib/commands/admin-rpc.js @@ -779,12 +779,14 @@ var commands = { // addFirstAdmin is an anon_rpc command Admin.addFirstAdmin = function (Env, data, cb) { + if (!Env.installToken) { return void cb('EINVAL'); } var token = data.token; + if (!token || !data.edPublic) { return void cb('MISSING_ARGS'); } + if (token.length !== 64 || data.edPublic.length !== 44) { return void cb('INVALID_ARGS'); } if (token !== Env.installToken) { return void cb('FORBIDDEN'); } if (Array.isArray(Env.admins) && Env.admins.length) { return void cb('EEXISTS'); } var key = data.edPublic; - if (token.length !== 64 || data.edPublic.length !== 44) { return void cb('INVALID_ARGS'); } adminDecree(Env, null, function (err) { if (err) { return void cb(err); } diff --git a/lib/env.js b/lib/env.js index 8824c347f..f61d48f9c 100644 --- a/lib/env.js +++ b/lib/env.js @@ -167,6 +167,7 @@ module.exports.create = function (config) { limits: {}, admins: [], + installToken: undefined, WARN: function (e, output) { // TODO deprecate this if (!Env.Log) { return; } if (e && output) { From 74a9357b502d8102d02531a37a43dd9b6a7be965 Mon Sep 17 00:00:00 2001 From: yflory Date: Mon, 16 Jan 2023 14:29:08 +0100 Subject: [PATCH 05/10] lint compliance --- scripts/clear.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/scripts/clear.js b/scripts/clear.js index f9ca46533..8bfadd964 100644 --- a/scripts/clear.js +++ b/scripts/clear.js @@ -1,18 +1,12 @@ var prompt = require('prompt-confirm'); const p = new prompt('Are you sure? This will permanently delete all existing data on your instance.'); -const nThen = require("nthen"); const Fs = require("fs"); -const Path = require("path"); var config = require("../lib/load-config"); -var Hash = require('../www/common/common-hash'); var Env = require("../lib/env").create(config); Env.Log = { error: console.log }; -var keyOrDefaultString = function (key, def) { - return Path.resolve(typeof(config[key]) === 'string'? config[key]: def); -}; var paths = Env.paths; p.ask(function (answer) { if (!answer) { @@ -20,7 +14,6 @@ p.ask(function (answer) { return; } console.log('Deleting all data...'); - var n = nThen; Object.values(paths).forEach(function (path) { console.log(`Deleting ${path}`); Fs.rmSync(path, { recursive: true, force: true }); From 5ec89c9a28315161bd55f91e3010aad713200c42 Mon Sep 17 00:00:00 2001 From: yflory Date: Mon, 16 Jan 2023 15:17:50 +0100 Subject: [PATCH 06/10] Fix feedback not initialized on new tabs with SharedWorker --- www/common/cryptpad-common.js | 2 +- www/common/outer/sharedworker.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index 018503259..f417a4507 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -2320,7 +2320,6 @@ define([ localStorage.setItem(Constants.tokenKey, data[Constants.tokenKey]); } } - initFeedback(data.feedback); }; @@ -2729,6 +2728,7 @@ define([ if (data.error) { throw new Error(data.error); } if (data.state === 'ALREADY_INIT') { data = data.returned; + initFeedback(data.feedback); } if (data.loggedIn) { diff --git a/www/common/outer/sharedworker.js b/www/common/outer/sharedworker.js index 825deb383..e256f065f 100644 --- a/www/common/outer/sharedworker.js +++ b/www/common/outer/sharedworker.js @@ -111,7 +111,7 @@ var init = function (client, cb) { if (data && data.state === "ALREADY_INIT") { debug('Store already exists!'); self.store = data.returned; - return void cb(data.returned); + return void cb(data); } self.store = data; cb(data); From 949a304989b359807d4be5d4888f735d04da6ff5 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 18 Jan 2023 12:59:28 +0100 Subject: [PATCH 07/10] Fix missing secure-fabric.js dependency --- www/whiteboard/export.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/whiteboard/export.js b/www/whiteboard/export.js index 4cdca58f8..1a96cf799 100644 --- a/www/whiteboard/export.js +++ b/www/whiteboard/export.js @@ -1,7 +1,7 @@ // This file is used when a user tries to export the entire CryptDrive. // Pads from the code app will be exported using this format instead of plain text. define([ - '/bower_components/secure-fabric.js/dist/fabric.min.js', + '/lib/fabric.min.js', ], function () { var module = {}; From 911c15df257a0cd64113f3535714cdf7c0720489 Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 19 Jan 2023 08:56:32 +0530 Subject: [PATCH 08/10] fix incorrectly constructed archival path for blobs --- lib/storage/blob.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/storage/blob.js b/lib/storage/blob.js index a2d9930f3..7d55676d7 100644 --- a/lib/storage/blob.js +++ b/lib/storage/blob.js @@ -19,7 +19,11 @@ var isValidId = function (id) { // helpers var prependArchive = function (Env, path) { - return Path.join(Env.archivePath, path); + // Env has an absolute path to the blob storage + // we want the path to the blob relative to that + var relativePathToBlob = Path.relative(Env.blobPath, path); + // the new path structure is the same, but relative to the blob archive root + return Path.join(Env.archivePath, 'blob', relativePathToBlob); }; // /blob//// @@ -492,7 +496,7 @@ BlobStore.create = function (config, _cb) { if (e) { CB(e); } })); - Fse.mkdirp(Path.join(Env.archivePath, Env.blobPath), w(function (e) { + Fse.mkdirp(Path.join(Env.archivePath, './blob'), w(function (e) { if (e) { CB(e); } })); }).nThen(function (w) { From 15272a660421bb05d7edd221f059615dc77a38d2 Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 19 Jan 2023 08:57:39 +0530 Subject: [PATCH 09/10] relocate blobs that have been archived to the wrong location --- lib/eviction.js | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/lib/eviction.js b/lib/eviction.js index 673c7313f..32e1bdd56 100644 --- a/lib/eviction.js +++ b/lib/eviction.js @@ -3,6 +3,10 @@ var Bloom = require("@mcrowe/minibloom"); var Util = require("../lib/common-util"); var Pins = require("../lib/pins"); var Keys = require("./keys"); +var Path = require('node:path'); +var config = require("./load-config"); +var Fs = require("node:fs"); +var Fse = require("fs-extra"); var getNewestTime = function (stats) { return stats[['atime', 'ctime', 'mtime'].reduce(function (a, b) { @@ -70,6 +74,103 @@ var evictArchived = function (Env, cb) { blobs = Env.blobStore; }; + var migrateBlobRoot = function (from, to) { + // only migrate subpaths, leave everything else alone + if (!Path.dirname(from).startsWith(Path.dirname(to))) { return; } + + // expects a directory + var recurse = function (relativePath) { + var src = Path.join(from, relativePath); + var children; + try { + children = Fs.readdirSync(src); + } catch (err) { + if (err.code === 'ENOENT') { return; } + // if you can't read a directory's contents + // then nothing else will work, so just abort + Log.verbose("EVICT_ARCHIVED_NOT_DIRECTORY", { + error: err, + }); + return; + } + + var dest; + if (children.length === 0) { + try { + Fse.removeSync(src); + } catch (err2) { + Log.error('EVICT_ARCHIVED_EMPTY_DIR_REMOVAL', { + error: err2, + }); + // removal is non-essential, so we can continue + } + } else { + // make an equivalent path in the target directory + dest = Path.join(to, relativePath); + + try { + Fse.mkdirpSync(dest); + } catch (err3) { + Log.error("EVICT_ARCHIVED_BLOB_MIGRATION", { + error: err3, + }); + + // failure to create the host directory + // will cause problems when we try to move + // so bail out here + return; + } + } + + children.forEach(function (child) { + var childSrcPath = Path.join(src, child); + var stat = Fs.statSync(childSrcPath); + if (stat.isDirectory()) { + return void recurse(Path.join(relativePath, child)); + } + + var childDestPath = Path.join(dest, child); + + try { + Log.verbose("EVICT_ARCHIVED_MOVE_FROM_DEPRECATED_PATH", { + from: childSrcPath, + to: childDestPath, + }); + Fse.moveSync(childSrcPath, childDestPath, { + overwrite: false, + }); + } catch (err4) { + Log.error('EVICT_ARCHIVED_MOVE_FAILURE', { + error: err4, + }); + } + }); + }; + recurse(''); + }; + +/* In CryptPad 5.2.0 we merged a patch which converted + all of CryptPad's root filepaths to their absolute form, + rather than the relative paths we'd been using until then. + Unfortunately, we overlooked a case where two absolute + paths were concatenated together, resulting in blobs being + archived to an incorrect path. + + This migration detects evidence of incorrect archivals + and moves such archived files to their intended location + before continuing with the normal eviction procedure. +*/ + var migrateIncorrectBlobs = function () { + var incorrectPaths = [ + Path.join(Env.paths.archive, config.blobPath), + Path.join(Env.paths.archive, Path.resolve(config.blobPath)) + ]; + var correctPath = Path.join(Env.paths.archive, 'blob'); + incorrectPaths.forEach(root => { + migrateBlobRoot(root, correctPath); + }); + }; + var removeArchivedChannels = function (w) { // this block will iterate over archived channels and removes them // if they've been in cold storage for longer than your configured archive time @@ -186,6 +287,7 @@ var evictArchived = function (Env, cb) { }; nThen(loadStorage) + .nThen(migrateIncorrectBlobs) .nThen(removeArchivedChannels) .nThen(removeArchivedBlobProofs) .nThen(removeArchivedBlobs) From 35867df36c36113f4e4f6914c2945c699cdea65e Mon Sep 17 00:00:00 2001 From: ansuz Date: Thu, 19 Jan 2023 08:58:51 +0530 Subject: [PATCH 10/10] lint compliance --- scripts/clear.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/clear.js b/scripts/clear.js index f9ca46533..4f33aa4c2 100644 --- a/scripts/clear.js +++ b/scripts/clear.js @@ -1,18 +1,19 @@ var prompt = require('prompt-confirm'); const p = new prompt('Are you sure? This will permanently delete all existing data on your instance.'); -const nThen = require("nthen"); +//const nThen = require("nthen"); const Fs = require("fs"); -const Path = require("path"); +//const Path = require("path"); var config = require("../lib/load-config"); -var Hash = require('../www/common/common-hash'); +//var Hash = require('../www/common/common-hash'); var Env = require("../lib/env").create(config); Env.Log = { error: console.log }; +/* var keyOrDefaultString = function (key, def) { return Path.resolve(typeof(config[key]) === 'string'? config[key]: def); -}; +}; */ var paths = Env.paths; p.ask(function (answer) { if (!answer) { @@ -20,7 +21,7 @@ p.ask(function (answer) { return; } console.log('Deleting all data...'); - var n = nThen; + //var n = nThen; Object.values(paths).forEach(function (path) { console.log(`Deleting ${path}`); Fs.rmSync(path, { recursive: true, force: true });