diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less
index 3274f1c63..c73c27c78 100644
--- a/customize.dist/src/less2/include/alertify.less
+++ b/customize.dist/src/less2/include/alertify.less
@@ -427,7 +427,7 @@
display: flex;
flex-flow: row;
- .cp-share-column {
+ & > .cp-share-column {
width: 50%;
padding: 0 10px;
}
diff --git a/historyKeeper.js b/historyKeeper.js
index 6027fc3fe..10137dd06 100644
--- a/historyKeeper.js
+++ b/historyKeeper.js
@@ -717,6 +717,9 @@ module.exports.create = function (cfg) {
if (channel && metadata_cache[channel] && typeof (metadata) === "object") {
Log.silly('SET_METADATA_CACHE', 'Channel '+ channel +', metadata: '+ JSON.stringify(metadata));
metadata_cache[channel] = metadata;
+ if (ctx.channels[channel] && ctx.channels[channel].index) {
+ ctx.channels[channel].index.metadata = metadata;
+ }
historyKeeperBroadcast(ctx, channel, metadata);
}
};
diff --git a/lib/metadata.js b/lib/metadata.js
index 11214931b..037024b57 100644
--- a/lib/metadata.js
+++ b/lib/metadata.js
@@ -54,6 +54,51 @@ commands.RM_OWNERS = function (meta, args) {
});
};
+// ["ADD_PENDING_OWNERS", ["7eEqelGso3EBr5jHlei6av4r9w2B9XZiGGwA1EgZ-5I="], 1561623438989]
+commands.ADD_PENDING_OWNERS = function (meta, args) {
+ // bail out if args isn't an array
+ if (!Array.isArray(args)) {
+ throw new Error('METADATA_INVALID_PENDING_OWNERS');
+ }
+
+ // you shouldn't be able to get here if there are no owners
+ // because only an owner should be able to change the owners
+ if (meta.pending_owners && !Array.isArray(meta.pending_owners)) {
+ throw new Error("METADATA_NONSENSE_PENDING_OWNERS");
+ }
+
+ // Add pending_owners array if it doesn't exist
+ if (!meta.pending_owners) {
+ meta.pending_owners = deduplicate(args);
+ return;
+ }
+ // or fill it
+ args.forEach(function (owner) {
+ if (meta.pending_owners.indexOf(owner) >= 0) { return; }
+ meta.pending_owners.push(owner);
+ });
+};
+
+// ["RM_PENDING_OWNERS", ["CrufexqXcY-z+eKJlEbNELVy5Sb7E-EAAEFI8GnEtZ0="], 1561623439989]
+commands.RM_PENDING_OWNERS = function (meta, args) {
+ // what are you doing if you don't have owners to remove?
+ if (!Array.isArray(args)) {
+ throw new Error('METADATA_INVALID_PENDING_OWNERS');
+ }
+ // if there aren't any owners to start, this is also pointless
+ if (!Array.isArray(meta.pending_owners)) {
+ throw new Error("METADATA_NONSENSE_PENDING_OWNERS");
+ }
+
+ // remove owners one by one
+ // we assume there are no duplicates
+ args.forEach(function (owner) {
+ var index = meta.pending_owners.indexOf(owner);
+ if (index < 0) { return; }
+ meta.pending_owners.splice(index, 1);
+ });
+};
+
// ["RESET_OWNERS", ["7eEqelGso3EBr5jHlei6av4r9w2B9XZiGGwA1EgZ-5I="], 1561623439989]
commands.RESET_OWNERS = function (meta, args) {
// expect a new array, even if it's empty
@@ -73,7 +118,7 @@ commands.UPDATE_EXPIRATION = function () {
throw new Error("E_NOT_IMPLEMENTED");
};
-var handleCommand = function (meta, line) {
+var handleCommand = Meta.handleCommand = function (meta, line) {
var command = line[0];
var args = line[1];
//var time = line[2];
@@ -84,6 +129,7 @@ var handleCommand = function (meta, line) {
commands[command](meta, args);
};
+Meta.commands = Object.keys(commands);
Meta.createLineHandler = function (ref, errorHandler) {
ref.meta = {};
@@ -125,4 +171,3 @@ Meta.createLineHandler = function (ref, errorHandler) {
};
};
-Meta.commands = Object.keys(commands);
diff --git a/rpc.js b/rpc.js
index 514d5e7d7..6ab004865 100644
--- a/rpc.js
+++ b/rpc.js
@@ -340,6 +340,7 @@ var getMetadata = function (Env, channel, cb) {
value: value
}
*/
+var metadataSem = Saferphore.create(1);
var setMetadata = function (Env, data, unsafeKey, cb) {
var channel = data.channel;
var command = data.command;
@@ -347,25 +348,52 @@ var setMetadata = function (Env, data, unsafeKey, cb) {
if (!command || typeof (command) !== 'string') { return void cb ('INVALID_COMMAND'); }
if (Meta.commands.indexOf(command) === -1) { return void('UNSUPPORTED_COMMAND'); }
- // XXX should we add checks to "metadata.js" to make sure data.value is
- // valid for the selected command?
+ metadataSem.take(function (give) {
+ var g = give();
+ getMetadata(Env, channel, function (err, metadata) {
+ if (err) {
+ g();
+ return void cb(err);
+ }
+ if (!(metadata && Array.isArray(metadata.owners))) {
+ g();
+ return void cb('E_NO_OWNERS');
+ }
- getMetadata(Env, channel, function (err, metadata) {
- if (err) { return void cb(err); }
- if (!(metadata && Array.isArray(metadata.owners))) { return void cb('E_NO_OWNERS'); }
- // Confirm that the channel is owned by the user in question
- if (metadata.owners.indexOf(unsafeKey) === -1) {
- return void cb('INSUFFICIENT_PERMISSIONS');
- }
+ // Confirm that the channel is owned by the user in question
+ // or the user is accepting a pending ownerhsip offer
+ if (metadata.pending_owners && Array.isArray(metadata.pending_owners) &&
+ metadata.pending_owners.indexOf(unsafeKey) !== -1 &&
+ metadata.owners.indexOf(unsafeKey) === -1) {
- // Add the new metadata line
- var line = JSON.stringify([command, data.value]);
- return void Env.msgStore.writeMetadata(channel, line, function (e) {
- if (e) {
+ // If you are a pending owner, make sure you can only add yourelf as an owner
+ if ((command !== 'ADD_OWNERS' && command !== 'RM_PENDING_OWNERS')
+ || !Array.isArray(data.value)
+ || data.value.length !== 1
+ || data.value[0] !== unsafeKey) {
+ g();
+ return void cb('INSUFFICIENT_PERMISSIONS');
+ }
+
+ } else if (metadata.owners.indexOf(unsafeKey) === -1) {
+ g();
+ return void cb('INSUFFICIENT_PERMISSIONS');
+ }
+
+ // Add the new metadata line
+ var line = [command, data.value, +new Date()];
+ try {
+ Meta.handleCommand(metadata, line);
+ } catch (e) {
+ g();
return void cb(e);
}
- getMetadata(Env, channel, function (err, metadata) {
- // XXX handle error here?
+
+ Env.msgStore.writeMetadata(channel, JSON.stringify(line), function (e) {
+ g();
+ if (e) {
+ return void cb(e);
+ }
cb(void 0, metadata);
});
});
diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js
index 650d0bf1f..b37d71355 100644
--- a/www/common/common-ui-elements.js
+++ b/www/common/common-ui-elements.js
@@ -76,6 +76,8 @@ define([
}));
}).nThen(function (waitFor) {
var base = common.getMetadataMgr().getPrivateData().origin;
+ // XXX getFileData?
+ // XXX getPadMetadata
common.getPadAttribute('href', waitFor(function (err, val) {
if (!val) { return; }
data.href = base + val;
@@ -99,29 +101,52 @@ define([
common.getPadAttribute('ctime', waitFor(function (err, val) {
data.ctime = val;
}));
+ common.getPadAttribute('title', waitFor(function (err, val) {
+ data.title = val;
+ }));
common.getPadAttribute('tags', waitFor(function (err, val) {
data.tags = val;
}));
+ common.getPadMetadata(null, waitFor(function (obj) {
+ console.log(obj);
+ if (obj && obj.error) { return; }
+ data.owners = obj.owners;
+ data.expire = obj.expire;
+ data.pending_owners = obj.pending_owners;
+ }));
+ /*
common.getPadAttribute('owners', waitFor(function (err, val) {
data.owners = val;
}));
common.getPadAttribute('expire', waitFor(function (err, val) {
data.expire = val;
- }));
+ }));*/
}).nThen(function () {
cb(void 0, data);
});
};
- var createOwnerModal = function (common, channel, owners) {
+ var createOwnerModal = function (common, data) {
var friends = common.getFriends(true);
var sframeChan = common.getSframeChannel();
var priv = common.getMetadataMgr().getPrivateData();
+ var user = common.getMetadataMgr().getUserData();
var edPublic = priv.edPublic;
+ var channel = data.channel;
+ var owners = data.owners;
+ var pending_owners = data.pending_owners;
+
+ var redrawAll = function () {};
+
+ var div1 = h('div.cp-share-friends.cp-share-column');
+ var div2 = h('div.cp-share-friends.cp-share-column');
+ var $div1 = $(div1);
+ var $div2 = $(div2);
// Remove owner column
- var drawRemove = function () {
+ var drawRemove = function (pending) {
var _owners = {};
- owners.forEach(function (ed) {
+ var o = pending ? pending_owners : owners;
+ o.forEach(function (ed) {
var f;
Object.keys(friends).some(function (c) {
if (friends[c].edPublic === ed) {
@@ -135,17 +160,19 @@ define([
edPublic: ed,
};
});
- var removeCol = UIElements.getFriendsList('Remove an existing owner instantly', {
+ var msg = pending ? 'Remove a pending owner:'
+ : 'Remove an existing owner:'; // XXX
+ var removeCol = UIElements.getFriendsList(msg, {
common: common,
friends: _owners,
noFilter: true
}, function () {
console.log(arguments);
});
- var $div1 = $(removeCol.div);
+ var $div = $(removeCol.div);
var others1 = removeCol.others;
- $div1.append(h('div.cp-share-grid', others1));
- $div1.find('.cp-share-friend').click(function () {
+ $div.append(h('div.cp-share-grid', others1));
+ $div.find('.cp-share-friend').click(function () {
var sel = $(this).hasClass('cp-selected');
if (!sel) {
$(this).addClass('cp-selected');
@@ -157,10 +184,11 @@ define([
});
// When clicking on the remove button, we check the selected users.
// If you try to remove yourself, we'll display an additional warning message
- var removeButton = h('button.no-margin', 'Remove owners'); // XXX
+ var btnMsg = pending ? 'Remove pending owners' : 'Remove owners'; // XXX
+ var removeButton = h('button.no-margin', btnMsg);
$(removeButton).click(function () {
// Check selection
- var $sel = $div1.find('.cp-share-friend.cp-selected');
+ var $sel = $div.find('.cp-share-friend.cp-selected');
var sel = $sel.toArray();
var me = false;
var toRemove = sel.map(function (el) {
@@ -173,14 +201,12 @@ define([
var send = function () {
sframeChan.query('Q_SET_PAD_METADATA', {
channel: channel,
- command: 'RM_OWNERS',
+ command: pending ? 'RM_PENDING_OWNERS' : 'RM_OWNERS',
value: toRemove
}, function (err, res) {
err = err || (res && res.error);
if (err) { return void UI.warn('ERROR' + err); } // XXX
- owners = res.owners;
- drawRemove().insertBefore($div1);
- $div1.remove();
+ redrawAll();
UI.log('DONE'); // XXX
});
};
@@ -192,20 +218,26 @@ define([
send();
});
});
- $div1.append(h('p', removeButton));
- return $div1;
+ $div.append(h('p', removeButton));
+ return $div;
};
// Add owners column
var drawAdd = function () {
+ var _friends = JSON.parse(JSON.stringify(friends));
+ Object.keys(_friends).forEach(function (curve) {
+ if (owners.indexOf(_friends[curve].edPublic) !== -1) {
+ delete _friends[curve];
+ }
+ });
var addCol = UIElements.getFriendsList('Ask a friend to be an owner.', {
common: common,
- friends: friends
+ friends: _friends
}, function () {
// XXX onSelect...
console.log(arguments);
});
- var $div2 = $(addCol.div);
+ $div2 = $(addCol.div);
var others2 = addCol.others;
$div2.append(h('div.cp-share-grid', others2));
$div2.find('.cp-share-friend').click(function () {
@@ -226,38 +258,86 @@ define([
var $sel = $div2.find('.cp-share-friend.cp-selected');
var sel = $sel.toArray();
var toAdd = sel.map(function (el) {
- return $(el).attr('data-curve');
+ return friends[$(el).attr('data-curve')].edPublic;
}).filter(function (x) { return x; });
- // Send the command
- var send = function () {
- // XXX Pinning problem....
+
+ NThen(function (waitFor) {
+ var msg = "Are you sure?"; // XXX
+ UI.confirm(msg, waitFor(function (yes) {
+ if (!yes) {
+ waitFor.abort();
+ return;
+ }
+ }));
+ }).nThen(function (waitFor) {
+ console.log('koko');
+ // Send the command
sframeChan.query('Q_SET_PAD_METADATA', {
channel: channel,
- command: 'ADD_OWNERS',
+ command: 'ADD_PENDING_OWNERS',
value: toAdd
- }, function (err, res) {
+ }, waitFor(function (err, res) {
+ console.error(arguments);
err = err || (res && res.error);
- if (err) { return void UI.warn('ERROR' + err); } // XXX
- owners = res.owners;
- drawRemove().insertBefore($div2);
- $div2.remove();
- UI.log('DONE'); // XXX
+ if (err) {
+ waitFor.abort();
+ return void UI.warn('ERROR' + err);
+ } // XXX
+ }));
+ }).nThen(function (waitFor) {
+ console.log('okok');
+ // TODO send notifications
+ sel.forEach(function (el) {
+ var friend = friends[$(el).attr('data-curve')];
+ if (!friend) { return; }
+ common.mailbox.sendTo("ADD_OWNER", {
+ channel: channel,
+ href: data.href,
+ password: data.password,
+ title: data.title,
+ user: {
+ displayName: user.name,
+ avatar: user.avatar,
+ profile: user.profile,
+ notifications: user.notifications,
+ curvePublic: user.curvePublic,
+ edPublic: priv.edPublic
+ }
+ }, {
+ channel: friend.notifications,
+ curvePublic: friend.curvePublic
+ }, waitFor());
});
- };
- var msg = "Are you sure?"; // XXX
- UI.confirm(msg, function (yes) {
- if (!yes) { return; }
- send();
+ }).nThen(function () {
+ redrawAll();
+ UI.log('DONE'); // XXX
});
});
- //$div2.append(h('p', addButton));
+ $div2.append(h('p', addButton));
return $div2;
};
+ redrawAll = function () {
+ $div1.empty();
+ $div2.empty();
+ common.getPadMetadata(null, function (obj) {
+ if (obj && obj.error) { return; }
+ owners = obj.owners;
+ pending_owners = obj.pending_owners;
+ $div1.append(drawRemove(false)).append(drawRemove(true));
+ $div2.append(drawAdd());
+ });
+ };
+
+ $div1.append(drawRemove(false)).append(drawRemove(true));
+ $div2.append(drawAdd());
+
// Create modal
var link = h('div.cp-share-columns', [
- drawRemove()[0],
- drawAdd()[0]
+ div1,
+ div2
+ /*drawRemove()[0],
+ drawAdd()[0]*/
]);
var linkButtons = [{
className: 'cancel',
@@ -310,7 +390,7 @@ define([
if (owned) {
var manageOwners = h('button.no-margin', 'Manage owners'); // XXX
$(manageOwners).click(function () {
- var modal = createOwnerModal(common, data.channel, data.owners);
+ var modal = createOwnerModal(common, data);
UI.openCustomModal(modal, {
wide: true,
});
@@ -3152,7 +3232,7 @@ define([
UIElements.displayFriendRequestModal = function (common, data) {
var msg = data.content.msg;
- var text = Messages._getKey('contacts_request', [msg.content.displayName]);
+ var text = Messages._getKey('contacts_request', [Util.fixHTML(msg.content.displayName)]);
var todo = function (yes) {
common.getSframeChannel().query("Q_ANSWER_FRIEND_REQUEST", {
@@ -3197,5 +3277,132 @@ define([
UI.openCustomModal(modal);
};
+ UIElements.displayAddOwnerModal = function (common, data) {
+ var priv = common.getMetadataMgr().getPrivateData();
+ var user = common.getMetadataMgr().getUserData();
+ var sframeChan = common.getSframeChannel();
+ var msg = data.content.msg;
+
+ var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
+ var title = Util.fixHTML(msg.content.title);
+
+ Messages.owner_add = '{0} wants you to be an owner of the pad {1}. Do you accept?'; //XXX
+ var text = Messages._getKey('owner_add', [name, title]);
+
+ var link = h('a', {
+ href: '#'
+ }, Messages.requestEdit_viewPad);
+ $(link).click(function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ if (msg.content.password) {
+ common.sessionStorage.put('newPadPassword', msg.content.password, function () {
+ common.openURL(msg.content.href);
+ });
+ return;
+ }
+ common.openURL(msg.content.href);
+ });
+
+ var div = h('div', [
+ UI.setHTML(h('p'), text),
+ link
+ ]);
+
+ var answer = function (yes) {
+ common.mailbox.sendTo("ADD_OWNER_ANSWER", {
+ channel: msg.content.channel,
+ href: msg.content.href,
+ password: msg.content.password,
+ title: msg.content.title,
+ answer: yes,
+ user: {
+ displayName: user.name,
+ avatar: user.avatar,
+ profile: user.profile,
+ notifications: user.notifications,
+ curvePublic: user.curvePublic,
+ edPublic: priv.edPublic
+ }
+ }, {
+ channel: msg.content.user.notifications,
+ curvePublic: msg.content.user.curvePublic
+ });
+ common.mailbox.dismiss(data, function (err) {
+ console.log(err);
+ });
+ };
+
+ var todo = function (yes) {
+ if (yes) {
+ // ACCEPT
+ sframeChan.query('Q_SET_PAD_METADATA', {
+ channel: msg.content.channel,
+ command: 'ADD_OWNERS',
+ value: [priv.edPublic]
+ }, function (err, res) {
+ err = err || (res && res.error);
+ if (err) {
+ return void UI.warn('ERROR ' + err);
+ } // XXX
+ UI.log('DONE'); // XXX
+
+ // Send notification to the sender
+ answer(true);
+
+ // Remove yourself from the pending owners
+ sframeChan.query('Q_SET_PAD_METADATA', {
+ channel: msg.content.channel,
+ command: 'RM_PENDING_OWNERS',
+ value: [priv.edPublic]
+ }, function (err, res) {
+ err = err || (res && res.error);
+ if (err) {
+ console.error(err);
+ }
+ });
+ });
+ return;
+ }
+
+ // DECLINE
+ // Remove yourself from the pending owners
+ sframeChan.query('Q_SET_PAD_METADATA', {
+ channel: msg.content.channel,
+ command: 'RM_PENDING_OWNERS',
+ value: [priv.edPublic]
+ }, function (err, res) {
+ err = err || (res && res.error);
+ if (err) {
+ console.error(err);
+ }
+ // Send notification to the sender
+ answer(false);
+ });
+ };
+
+ var buttons = [{
+ name: Messages.friendRequest_later,
+ onClick: function () {},
+ keys: [27]
+ }, {
+ className: 'primary',
+ name: Messages.friendRequest_accept,
+ onClick: function () {
+ todo(true);
+ },
+ keys: [13]
+ }, {
+ className: 'primary',
+ name: Messages.friendRequest_decline,
+ onClick: function () {
+ todo(false);
+ },
+ keys: [[13, 'ctrl']]
+ }];
+ var modal = UI.dialog.customModal(div, {buttons: buttons});
+ UI.openCustomModal(modal);
+ };
+
return UIElements;
});
diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js
index 4ed0976ff..56e5edcae 100644
--- a/www/common/cryptpad-common.js
+++ b/www/common/cryptpad-common.js
@@ -758,6 +758,10 @@ define([
pad.onConnectEvent = Util.mkEvent();
pad.onErrorEvent = Util.mkEvent();
+ pad.getPadMetadata = function (data, cb) {
+ postMessage('GET_PAD_METADATA', data, cb);
+ };
+
pad.requestAccess = function (data, cb) {
postMessage("REQUEST_PAD_ACCESS", data, cb);
};
@@ -769,7 +773,10 @@ define([
postMessage('SET_PAD_METADATA', data, cb);
};
common.getPadMetadata = function (data, cb) {
- postMessage('GET_PAD_METADATA', data, cb);
+ common.anonRpcMsg('GET_METADATA', data.channel, function (err, obj) {
+ if (err) { return void cb({error: err}); }
+ cb(obj && obj[0]);
+ });
};
common.changePadPassword = function (Crypt, href, newPassword, edPublic, cb) {
diff --git a/www/common/notifications.js b/www/common/notifications.js
index 72b62b501..b06e8e3fc 100644
--- a/www/common/notifications.js
+++ b/www/common/notifications.js
@@ -210,6 +210,48 @@ define([
};
};
+
+ handlers['ADD_OWNER'] = function (common, data) {
+ var content = data.content;
+ var msg = content.msg;
+
+ // Display the notification
+ var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
+ var title = Util.fixHTML(msg.content.title);
+ Messages.owner_request = '{0} wants you to be an owner of {1}'; // XXX
+ content.getFormatText = function () {
+ return Messages._getKey('owner_request', [name, title]);
+ };
+
+ // Check authenticity
+ if (msg.author !== msg.content.user.curvePublic) { return; }
+
+ // if not archived, add handlers
+ if (!content.archived) {
+ content.handler = function () {
+ UIElements.displayAddOwnerModal(common, data);
+ };
+ }
+ };
+
+ handlers['ADD_OWNER_ANSWER'] = function (common, data) {
+ var content = data.content;
+ var msg = content.msg;
+
+ // Display the notification
+ var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
+ var title = Util.fixHTML(msg.content.title);
+ Messages.owner_request_accepted = '{0} has accepted your offer to be an owner of {1}'; // XXX
+ Messages.owner_request_declined = '{0} has declined your offer to be an owner of {1}'; // XXX
+ var key = 'owner_request_' + (msg.content.answer ? 'accepted' : 'declined');
+ content.getFormatText = function () {
+ return Messages._getKey(key, [name, title]);
+ };
+ if (!content.archived) {
+ content.dismissHandler = defaultDismiss(common, data);
+ }
+ };
+
// NOTE: don't forget to fixHTML everything returned by "getFormatText"
return {
diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js
index 619c4018f..83dcf5806 100644
--- a/www/common/outer/async-store.js
+++ b/www/common/outer/async-store.js
@@ -1374,6 +1374,7 @@ define([
};
Store.getPadMetadata = function (clientId, data, cb) {
+ console.log(data);
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
var channel = channels[data.channel];
if (!channel) { return void cb({ error: 'ENOTFOUND' }); }
@@ -1396,6 +1397,7 @@ define([
cb(channel.data || {});
};
Store.setPadMetadata = function (clientId, data, cb) {
+ console.log(data);
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
if (!data.command) { return void cb({ error: 'EINVAL' }); }
store.rpc.setMetadata(data, function (err, res) {
diff --git a/www/common/outer/mailbox-handlers.js b/www/common/outer/mailbox-handlers.js
index 9d383caa1..ed1d954b1 100644
--- a/www/common/outer/mailbox-handlers.js
+++ b/www/common/outer/mailbox-handlers.js
@@ -259,6 +259,33 @@ define([
cb(false);
};
+ // Hide duplicates when receiving an ADD_OWNER notification:
+ var addOwners = {};
+ handlers['ADD_OWNER'] = function (ctx, box, data, cb) {
+ var msg = data.msg;
+ var content = msg.content;
+console.log(msg);
+
+ if (msg.author !== content.user.curvePublic) { return void cb(true); }
+ if (!content.href || !content.title || !content.channel) {
+ console.log('Remove invalid notification');
+ return void cb(true);
+ }
+
+ var channel = content.channel;
+
+ if (addOwners[channel]) { return void cb(true); }
+ addOwners[channel] = true;
+
+ cb(false);
+ };
+ removeHandlers['ADD_OWNER'] = function (ctx, box, data) {
+ var channel = data.content.channel;
+ if (addOwners[channel]) {
+ delete addOwners[channel];
+ }
+ };
+
return {
add: function (ctx, box, data, cb) {
/**
diff --git a/www/common/sframe-common-mailbox.js b/www/common/sframe-common-mailbox.js
index 5aaaa5340..e468b29f1 100644
--- a/www/common/sframe-common-mailbox.js
+++ b/www/common/sframe-common-mailbox.js
@@ -32,13 +32,17 @@ define([
});
};
- mailbox.sendTo = function (type, content, user) {
+ mailbox.sendTo = function (type, content, user, cb) {
+ cb = cb || function () {};
execCommand('SENDTO', {
type: type,
msg: content,
user: user
}, function (err, obj) {
- if (err || (obj && obj.error)) { return void console.error(err || obj.error); }
+ cb(err || (obj && obj.error), obj);
+ if (err || (obj && obj.error)) {
+ return void console.error(err || obj.error);
+ }
});
};
diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js
index 38214752f..cc568553a 100644
--- a/www/common/sframe-common-outer.js
+++ b/www/common/sframe-common-outer.js
@@ -981,7 +981,7 @@ define([
// Try to get the owner's mailbox from the pad metadata first.
// If it's is an older owned pad, check if the owner is a friend
// or an acquaintance (from async-store directly in requestAccess)
- Cryptpad.getPadMetadata({
+ Cryptpad.pad.getPadMetadata({
channel: secret.channel
}, waitFor(function (obj) {
obj = obj || {};
@@ -1004,6 +1004,15 @@ define([
});
});
+ sframeChan.on('Q_GET_PAD_METADATA', function (data, cb) {
+ if (!data || !data.channel) {
+ data = {
+ channel: secret.channel
+ };
+ }
+ console.log(data);
+ Cryptpad.getPadMetadata(data, cb);
+ });
sframeChan.on('Q_SET_PAD_METADATA', function (data, cb) {
Cryptpad.setPadMetadata(data, cb);
});
diff --git a/www/common/sframe-common.js b/www/common/sframe-common.js
index 58e1ffcb0..6b4fc96aa 100644
--- a/www/common/sframe-common.js
+++ b/www/common/sframe-common.js
@@ -467,6 +467,13 @@ define([
}, { timeout: 60000 });
};
+ funcs.getPadMetadata = function (data, cb) {
+ ctx.sframeChan.query('Q_GET_PAD_METADATA', data, function (err, val) {
+ if (err || (val && val.error)) { return void cb({error: err || val.error}); }
+ cb(val);
+ });
+ };
+
funcs.gotoURL = function (url) { ctx.sframeChan.event('EV_GOTO_URL', url); };
funcs.openURL = function (url) { ctx.sframeChan.event('EV_OPEN_URL', url); };
funcs.openUnsafeURL = function (url) {
diff --git a/www/drive/inner.js b/www/drive/inner.js
index 08babf7e0..59fbaba2f 100644
--- a/www/drive/inner.js
+++ b/www/drive/inner.js
@@ -3716,6 +3716,20 @@ define([
data.sharedFolder = true;
}
+ if (manager.isFile(el) && data.roHref) { // Only for pads!
+ sframeChan.query('Q_GET_PAD_METADATA', {
+ channel: data.channel
+ }, function (err, val) {
+ console.log(arguments);
+ if (!err && !(val && val.error)) {
+ data.owners = val.owners;
+ data.expire = val.expire;
+ data.pending_owners = val.pending_owners;
+ }
+ UIElements.getProperties(common, data, cb);
+ });
+ return;
+ }
UIElements.getProperties(common, data, cb);
};