diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 89ad52835..a195a1ba9 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -4001,6 +4001,8 @@ define([ msg += Messages.errorCopy; } } + var sframeChan = common.getSframeChannel(); + sframeChan.event('EV_SHARE_OPEN', {hidden: true}); if (toolbar && typeof toolbar.deleted === "function") { toolbar.deleted(); } UI.errorLoadingScreen(msg, true, true); (cb || function () {})(); diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index e39a2f980..681f1d575 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -1653,6 +1653,45 @@ define([ }; // Delete a pad received with a burn after reading URL + + var notifyOwnerPadRemoved = function (data, obj) { + var channel = data.channel; + var href = data.href; + var parsed = Hash.parsePadUrl(href); + var secret = Hash.getSecrets(parsed.type, parsed.hash, data.password); + if (obj && obj.error) { return; } + if (!obj.mailbox) { return; } + + // Decrypt the mailbox + var crypto = Crypto.createEncryptor(secret.keys); + var m = []; + try { + if (typeof (obj.mailbox) === "string") { + m.push(crypto.decrypt(obj.mailbox, true, true)); + } else { + Object.keys(obj.mailbox).forEach(function (k) { + m.push(crypto.decrypt(obj.mailbox[k], true, true)); + }); + } + } catch (e) { + console.error(e); + } + // Tell all the owners that the pad was deleted from the server + var curvePublic = store.proxy.curvePublic; + var myData = Messaging.createData(store.proxy, false); + m.forEach(function (obj) { + var mb = JSON.parse(obj); + if (mb.curvePublic === curvePublic) { return; } + store.mailbox.sendTo('OWNED_PAD_REMOVED', { + channel: channel, + user: myData + }, { + channel: mb.notifications, + curvePublic: mb.curvePublic + }, function () {}); + }); + }; + Store.burnPad = function (clientId, data) { var channel = data.channel; var ownerKey = Crypto.b64AddSlashes(data.ownerKey || ''); @@ -1665,8 +1704,14 @@ define([ edPrivate: Hash.encodeBase64(pair.secretKey) }, function (e, rpc) { if (e) { return void console.error(e); } - rpc.removeOwnedChannel(channel, function (err) { - if (err) { console.error(err); } + Store.getPadMetadata(null, { + channel: channel + }, function (md) { + rpc.removeOwnedChannel(channel, function (err) { + if (err) { return void console.error(err); } + // Notify owners that the pad was removed + notifyOwnerPadRemoved(data, md); + }); }); }); } catch (e) { @@ -2130,6 +2175,11 @@ define([ updateMetadata: function () { broadcast([], "UPDATE_METADATA"); }, + updateDrive: function () { + sendDriveEvent('DRIVE_CHANGE', { + path: ['drive', 'filesData'] + }); + }, pinPads: function (data, cb) { Store.pinPads(null, data, cb); }, }, waitFor, function (ev, data, clients, _cb) { var cb = Util.once(_cb || function () {}); diff --git a/www/common/outer/mailbox-handlers.js b/www/common/outer/mailbox-handlers.js index 6e10cd5a2..253157361 100644 --- a/www/common/outer/mailbox-handlers.js +++ b/www/common/outer/mailbox-handlers.js @@ -482,6 +482,31 @@ define([ cb(true); }; + handlers['OWNED_PAD_REMOVED'] = function (ctx, box, data, cb) { + var msg = data.msg; + var content = msg.content; + + if (msg.author !== content.user.curvePublic) { return void cb(true); } + if (!content.channel) { + console.log('Remove invalid notification'); + return void cb(true); + } + + var channel = content.channel; + var res = ctx.store.manager.findChannel(channel); + + res.forEach(function (obj) { + var paths = ctx.store.manager.findFile(obj.id); + ctx.store.manager.delete({ + paths: paths + }, function () { + ctx.updateDrive(); + }); + }); + + cb(true); + }; + return { diff --git a/www/common/outer/mailbox.js b/www/common/outer/mailbox.js index 1def668e1..b84e98dd7 100644 --- a/www/common/outer/mailbox.js +++ b/www/common/outer/mailbox.js @@ -422,6 +422,7 @@ proxy.mailboxes = { store: store, pinPads: cfg.pinPads, updateMetadata: cfg.updateMetadata, + updateDrive: cfg.updateDrive, emit: emit, clients: [], boxes: {}, diff --git a/www/common/proxy-manager.js b/www/common/proxy-manager.js index 1bd88e90b..796c52898 100644 --- a/www/common/proxy-manager.js +++ b/www/common/proxy-manager.js @@ -119,6 +119,7 @@ define([ // If it's not a shared folder, check the pads if (!data) { data = Env.user.userObject.getFileData(id, editable); } ret.push({ + id: id, data: data, userObject: Env.user.userObject }); @@ -126,6 +127,7 @@ define([ Object.keys(Env.folders).forEach(function (fId) { Env.folders[fId].userObject.findChannels([channel]).forEach(function (id) { ret.push({ + id: id, fId: fId, data: Env.folders[fId].userObject.getFileData(id, editable), userObject: Env.folders[fId].userObject @@ -1095,9 +1097,11 @@ define([ // Store getChannelsList: callWithEnv(getChannelsList), addPad: callWithEnv(addPad), + delete: callWithEnv(_delete), // Tools findChannel: callWithEnv(findChannel), findHref: callWithEnv(findHref), + findFile: callWithEnv(findFile), getEditHash: callWithEnv(getEditHash), user: Env.user, folders: Env.folders diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index c19e9e344..f53a6b496 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -81,8 +81,8 @@ define([ }); localStorage.CRYPTPAD_URLARGS = ApiConfig.requireConf.urlArgs; } - var cache = {}; - var localStore = {}; + var cache = window.cpCache = {}; + var localStore = window.localStore = {}; Object.keys(localStorage).forEach(function (k) { if (k.indexOf('CRYPTPAD_CACHE|') === 0) { cache[k.slice(('CRYPTPAD_CACHE|').length)] = localStorage[k]; @@ -1240,6 +1240,8 @@ define([ if (burnAfterReading) { Cryptpad.padRpc.onReadyEvent.reg(function () { Cryptpad.burnPad({ + password: password, + href: window.location.href, channel: secret.channel, ownerKey: burnAfterReading }); diff --git a/www/filepicker/main.js b/www/filepicker/main.js index d6017c2dd..cada394ba 100644 --- a/www/filepicker/main.js +++ b/www/filepicker/main.js @@ -58,7 +58,7 @@ define([ // Remove the listener once we've received the READY message window.removeEventListener('message', whenReady); // Answer with the requested data - postMsg(JSON.stringify({ txid: data.txid, language: Cryptpad.getLanguage() })); + postMsg(JSON.stringify({ txid: data.txid, language: Cryptpad.getLanguage(), localStore: window.localStore, cache: window.cpCache })); // Then start the channel window.addEventListener('message', function (msg) { diff --git a/www/share/main.js b/www/share/main.js index 43e514f58..28cc1a882 100644 --- a/www/share/main.js +++ b/www/share/main.js @@ -60,7 +60,7 @@ define([ // Remove the listener once we've received the READY message window.removeEventListener('message', whenReady); // Answer with the requested data - postMsg(JSON.stringify({ txid: data.txid, language: Cryptpad.getLanguage() })); + postMsg(JSON.stringify({ txid: data.txid, language: Cryptpad.getLanguage(), localStore: window.localStore, cache: window.cpCache })); // Then start the channel window.addEventListener('message', function (msg) { @@ -105,6 +105,21 @@ define([ config.addCommonRpc(sframeChan); + sframeChan.on('EV_CACHE_PUT', function (x) { + Object.keys(x).forEach(function (k) { + localStorage['CRYPTPAD_CACHE|' + k] = x[k]; + }); + }); + sframeChan.on('EV_LOCALSTORE_PUT', function (x) { + Object.keys(x).forEach(function (k) { + if (typeof(x[k]) === "undefined") { + delete localStorage['CRYPTPAD_STORE|' + k]; + return; + } + localStorage['CRYPTPAD_STORE|' + k] = x[k]; + }); + }); + sframeChan.on('Q_GET_FILES_LIST', function (types, cb) { Cryptpad.getSecureFilesList(types, function (err, data) { cb({