Merge branch 'q' into staging
This commit is contained in:
@@ -196,6 +196,7 @@ define([
|
||||
]);
|
||||
var $frame = $(frame);
|
||||
frame.closeModal = function (cb) {
|
||||
frame.closeModal = function () {}; // Prevent further calls
|
||||
$frame.fadeOut(150, function () {
|
||||
$frame.detach();
|
||||
if (typeof(cb) === "function") { cb(); }
|
||||
@@ -464,16 +465,23 @@ define([
|
||||
|
||||
UI.createModal = function (cfg) {
|
||||
var $body = cfg.$body || $('body');
|
||||
var $blockContainer = $body.find('#'+cfg.id);
|
||||
if (!$blockContainer.length) {
|
||||
$blockContainer = $(h('div.cp-modal-container#'+cfg.id, {
|
||||
var $blockContainer = cfg.id && $body.find('#'+cfg.id);
|
||||
if (!$blockContainer || !$blockContainer.length) {
|
||||
var id = '';
|
||||
if (cfg.id) { id = '#'+cfg.id; }
|
||||
$blockContainer = $(h('div.cp-modal-container'+id, {
|
||||
tabindex: 1
|
||||
}));
|
||||
}
|
||||
var deleted = false;
|
||||
var hide = function () {
|
||||
if (cfg.onClose) { return void cfg.onClose(); }
|
||||
if (deleted) { return; }
|
||||
$blockContainer.hide();
|
||||
if (cfg.onClosed) { cfg.onClosed(); }
|
||||
if (!cfg.id) {
|
||||
deleted = true;
|
||||
$blockContainer.remove();
|
||||
}
|
||||
if (cfg.onClose) { cfg.onClose(); }
|
||||
};
|
||||
$blockContainer.html('').appendTo($body);
|
||||
var $block = $(h('div.cp-modal')).appendTo($blockContainer);
|
||||
|
||||
@@ -1606,11 +1606,7 @@ define([
|
||||
.text(Messages.accessButton))
|
||||
.click(common.prepareFeedback(type))
|
||||
.click(function () {
|
||||
require(['/common/inner/access.js'], function (Access) {
|
||||
Access.getAccessModal(common, {}, function (e) {
|
||||
if (e) { console.error(e); }
|
||||
});
|
||||
});
|
||||
sframeChan.event('EV_ACCESS_OPEN');
|
||||
});
|
||||
break;
|
||||
case 'properties':
|
||||
@@ -1625,11 +1621,7 @@ define([
|
||||
if (!data) {
|
||||
return void UI.alert(Messages.autostore_notAvailable);
|
||||
}
|
||||
require(['/common/inner/properties.js'], function (Properties) {
|
||||
Properties.getPropertiesModal(common, {}, function (e) {
|
||||
if (e) { console.error(e); }
|
||||
});
|
||||
});
|
||||
sframeChan.event('EV_PROPERTIES_OPEN');
|
||||
});
|
||||
});
|
||||
break;
|
||||
@@ -2642,17 +2634,13 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
UIElements.initFilePicker = function (common, cfg) {
|
||||
var onSelect = cfg.onSelect || $.noop;
|
||||
UIElements.openFilePicker = function (common, types, cb) {
|
||||
var sframeChan = common.getSframeChannel();
|
||||
sframeChan.on("EV_FILE_PICKED", function (data) {
|
||||
onSelect(data);
|
||||
sframeChan.query("Q_FILE_PICKER_OPEN", types, function (err, data) {
|
||||
if (err) { return; }
|
||||
cb(data);
|
||||
});
|
||||
};
|
||||
UIElements.openFilePicker = function (common, types) {
|
||||
var sframeChan = common.getSframeChannel();
|
||||
sframeChan.event("EV_FILE_PICKER_OPEN", types);
|
||||
};
|
||||
|
||||
UIElements.openTemplatePicker = function (common, force) {
|
||||
var metadataMgr = common.getMetadataMgr();
|
||||
@@ -2675,29 +2663,25 @@ define([
|
||||
return;
|
||||
}
|
||||
delete pickerCfg.hidden;
|
||||
common.openFilePicker(pickerCfg);
|
||||
var first = true; // We can only pick a template once (for a new document)
|
||||
var fileDialogCfg = {
|
||||
onSelect: function (data) {
|
||||
if (data.type === type && first) {
|
||||
UI.addLoadingScreen({hideTips: true});
|
||||
var chatChan = common.getPadChat();
|
||||
var cursorChan = common.getCursorChannel();
|
||||
sframeChan.query('Q_TEMPLATE_USE', {
|
||||
href: data.href,
|
||||
chat: chatChan,
|
||||
cursor: cursorChan
|
||||
}, function () {
|
||||
first = false;
|
||||
UI.removeLoadingScreen();
|
||||
Feedback.send('TEMPLATE_USED');
|
||||
});
|
||||
if (focus) { focus.focus(); }
|
||||
return;
|
||||
}
|
||||
common.openFilePicker(pickerCfg, function (data) {
|
||||
if (data.type === type && first) {
|
||||
UI.addLoadingScreen({hideTips: true});
|
||||
var chatChan = common.getPadChat();
|
||||
var cursorChan = common.getCursorChannel();
|
||||
sframeChan.query('Q_TEMPLATE_USE', {
|
||||
href: data.href,
|
||||
chat: chatChan,
|
||||
cursor: cursorChan
|
||||
}, function () {
|
||||
first = false;
|
||||
UI.removeLoadingScreen();
|
||||
Feedback.send('TEMPLATE_USED');
|
||||
});
|
||||
if (focus) { focus.focus(); }
|
||||
return;
|
||||
}
|
||||
};
|
||||
common.initFilePicker(fileDialogCfg);
|
||||
});
|
||||
};
|
||||
|
||||
sframeChan.query("Q_TEMPLATE_EXIST", type, function (err, data) {
|
||||
|
||||
@@ -59,7 +59,7 @@ define([
|
||||
}), opts.href);
|
||||
|
||||
// If this is a file, don't try to look for metadata
|
||||
if (opts.channel && opts.channel.length > 34) { return; }
|
||||
if (opts.channel && opts.channel.length > 32) { return; }
|
||||
if (opts.channel) { data.channel = opts.channel; }
|
||||
Modal.loadMetadata(Env, data, waitFor);
|
||||
}).nThen(function () {
|
||||
@@ -129,7 +129,10 @@ define([
|
||||
tabs[i] = {
|
||||
content: c && UI.dialog.customModal(node, {
|
||||
buttons: obj.buttons || button,
|
||||
onClose: function () { blocked = false; }
|
||||
onClose: function () {
|
||||
blocked = false;
|
||||
if (typeof(opts.onClose) === "function") { opts.onClose(); }
|
||||
}
|
||||
}),
|
||||
disabled: !c,
|
||||
title: obj.title,
|
||||
|
||||
@@ -132,6 +132,12 @@ define([
|
||||
APP.onLocal();
|
||||
};
|
||||
|
||||
var isRegisteredUserOnline = function () {
|
||||
var users = metadataMgr.getMetadata().users || {};
|
||||
return Object.keys(users).some(function (id) {
|
||||
return users[id] && users[id].curvePublic;
|
||||
});
|
||||
};
|
||||
var isUserOnline = function (ooid) {
|
||||
// Remove ids for users that have left the channel
|
||||
deleteOffline();
|
||||
@@ -348,16 +354,44 @@ define([
|
||||
fixSheets();
|
||||
APP.FM.handleFile(blob, data);
|
||||
};
|
||||
|
||||
Messages.oo_login = 'Log in...'; // XXX
|
||||
var noLogin = false;
|
||||
|
||||
var makeCheckpoint = function (force) {
|
||||
if (!common.isLoggedIn()) { return; }
|
||||
var locked = content.saveLock;
|
||||
var lastCp = getLastCp();
|
||||
|
||||
var needCp = force || ooChannel.cpIndex % CHECKPOINT_INTERVAL === 0 ||
|
||||
(ooChannel.cpIndex - lastCp.index) > CHECKPOINT_INTERVAL;
|
||||
(ooChannel.cpIndex - (lastCp.index || 0)) > CHECKPOINT_INTERVAL;
|
||||
if (!needCp) { return; }
|
||||
|
||||
if (!locked || !isUserOnline(locked) || force) {
|
||||
if (!common.isLoggedIn() && !isRegisteredUserOnline() && !noLogin) {
|
||||
var login = h('button.cp-corner-primary', Messages.login_login);
|
||||
var register = h('button.cp-corner-primary', Messages.login_register);
|
||||
var cancel = h('button.cp-corner-cancel', Messages.cancel);
|
||||
var actions = h('div', [cancel, register, login]);
|
||||
var modal = UI.cornerPopup(Messages.oo_login, actions, '', {alt: true});
|
||||
$(register).click(function () {
|
||||
common.setLoginRedirect(function () {
|
||||
common.gotoURL('/register/');
|
||||
});
|
||||
modal.delete();
|
||||
});
|
||||
$(login).click(function () {
|
||||
common.setLoginRedirect(function () {
|
||||
common.gotoURL('/login/');
|
||||
});
|
||||
modal.delete();
|
||||
});
|
||||
$(cancel).click(function () {
|
||||
modal.delete();
|
||||
noLogin = true;
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!common.isLoggedIn()) { return; }
|
||||
content.saveLock = myOOId;
|
||||
APP.onLocal();
|
||||
APP.realtime.onSettle(function () {
|
||||
@@ -907,8 +941,16 @@ define([
|
||||
if (ifr) { ifr.remove(); }
|
||||
};
|
||||
|
||||
common.initFilePicker({
|
||||
onSelect: function (data) {
|
||||
APP.AddImage = function(cb1, cb2) {
|
||||
APP.AddImageSuccessCallback = cb1;
|
||||
APP.AddImageErrorCallback = cb2;
|
||||
common.openFilePicker({
|
||||
types: ['file'],
|
||||
where: ['root'],
|
||||
filter: {
|
||||
fileType: ['image/']
|
||||
}
|
||||
}, function (data) {
|
||||
if (data.type !== 'file') {
|
||||
debug("Unexpected data type picked " + data.type);
|
||||
return;
|
||||
@@ -929,19 +971,6 @@ define([
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
APP.AddImage = function(cb1, cb2) {
|
||||
APP.AddImageSuccessCallback = cb1;
|
||||
APP.AddImageErrorCallback = cb2;
|
||||
common.openFilePicker({
|
||||
types: ['file'],
|
||||
where: ['root'],
|
||||
filter: {
|
||||
fileType: ['image/']
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -675,6 +675,8 @@ define([
|
||||
sem.take(function (give) {
|
||||
var otherOwners = false;
|
||||
nThen(function (_w) {
|
||||
// Don't check server metadata for blobs
|
||||
if (c.length !== 32) { return; }
|
||||
Store.anonRpcMsg(null, {
|
||||
msg: 'GET_METADATA',
|
||||
data: c
|
||||
@@ -1807,6 +1809,7 @@ define([
|
||||
var cb = Util.once(Util.mkAsync(_cb));
|
||||
|
||||
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
|
||||
if (data.channel.length !== 32) { return void cb({ error: 'EINVAL'}); }
|
||||
store.anon_rpc.send('GET_METADATA', data.channel, function (err, obj) {
|
||||
if (err) { return void cb({error: err}); }
|
||||
var metadata = (obj && obj[0]) || {};
|
||||
|
||||
@@ -678,6 +678,8 @@ define([
|
||||
sem.take(function (give) {
|
||||
var otherOwners = false;
|
||||
nThen(function (_w) {
|
||||
// Don't check server metadata for blobs
|
||||
if (c.length !== 32) { return; }
|
||||
ctx.Store.anonRpcMsg(null, {
|
||||
msg: 'GET_METADATA',
|
||||
data: c
|
||||
|
||||
@@ -503,8 +503,13 @@ define([
|
||||
|
||||
var createFilePicker = function () {
|
||||
if (!common.isLoggedIn()) { return; }
|
||||
common.initFilePicker({
|
||||
onSelect: function (data) {
|
||||
$embedButton = common.createButton('mediatag', true).click(function () {
|
||||
var cfg = {
|
||||
types: ['file'],
|
||||
where: ['root']
|
||||
};
|
||||
if ($embedButton.data('filter')) { cfg.filter = $embedButton.data('filter'); }
|
||||
common.openFilePicker(cfg, function (data) {
|
||||
if (data.type !== 'file') {
|
||||
console.log("Unexpected data type picked " + data.type);
|
||||
return;
|
||||
@@ -516,17 +521,7 @@ define([
|
||||
var src = data.src = data.src.slice(0,1) === '/' ? origin + data.src : data.src;
|
||||
mediaTagEmbedder($('<media-tag src="' + src +
|
||||
'" data-crypto-key="cryptpad:' + data.key + '"></media-tag>'), data);
|
||||
}
|
||||
});
|
||||
$embedButton = common.createButton('mediatag', true).click(function () {
|
||||
var cfg = {
|
||||
types: ['file'],
|
||||
where: ['root']
|
||||
};
|
||||
if ($embedButton.data('filter')) {
|
||||
cfg.filter = $embedButton.data('filter');
|
||||
}
|
||||
common.openFilePicker(cfg);
|
||||
});
|
||||
}).appendTo(toolbar.$rightside).hide();
|
||||
};
|
||||
var setMediaTagEmbedder = function (mte, filter) {
|
||||
|
||||
@@ -18,8 +18,7 @@ define([
|
||||
var Cryptget;
|
||||
var SFrameChannel;
|
||||
var sframeChan;
|
||||
var FilePicker;
|
||||
var Share;
|
||||
var SecureIframe;
|
||||
var Messaging;
|
||||
var Notifier;
|
||||
var Utils = {
|
||||
@@ -44,8 +43,7 @@ define([
|
||||
'/bower_components/chainpad-crypto/crypto.js',
|
||||
'/common/cryptget.js',
|
||||
'/common/outer/worker-channel.js',
|
||||
'/filepicker/main.js',
|
||||
'/share/main.js',
|
||||
'/secureiframe/main.js',
|
||||
'/common/common-messaging.js',
|
||||
'/common/common-notifier.js',
|
||||
'/common/common-hash.js',
|
||||
@@ -58,15 +56,14 @@ define([
|
||||
'/common/test.js',
|
||||
'/common/userObject.js',
|
||||
], waitFor(function (_CpNfOuter, _Cryptpad, _Crypto, _Cryptget, _SFrameChannel,
|
||||
_FilePicker, _Share, _Messaging, _Notifier, _Hash, _Util, _Realtime,
|
||||
_SecureIframe, _Messaging, _Notifier, _Hash, _Util, _Realtime,
|
||||
_Constants, _Feedback, _LocalStore, _AppConfig, _Test, _UserObject) {
|
||||
CpNfOuter = _CpNfOuter;
|
||||
Cryptpad = _Cryptpad;
|
||||
Crypto = Utils.Crypto = _Crypto;
|
||||
Cryptget = _Cryptget;
|
||||
SFrameChannel = _SFrameChannel;
|
||||
FilePicker = _FilePicker;
|
||||
Share = _Share;
|
||||
SecureIframe = _SecureIframe;
|
||||
Messaging = _Messaging;
|
||||
Notifier = _Notifier;
|
||||
Utils.Hash = _Hash;
|
||||
@@ -491,7 +488,7 @@ define([
|
||||
|
||||
|
||||
// Put in the following function the RPC queries that should also work in filepicker
|
||||
var addCommonRpc = function (sframeChan) {
|
||||
var addCommonRpc = function (sframeChan, safe) {
|
||||
sframeChan.on('Q_ANON_RPC_MESSAGE', function (data, cb) {
|
||||
Cryptpad.anonRpcMsg(data.msg, data.content, function (err, response) {
|
||||
cb({error: err, response: response});
|
||||
@@ -598,6 +595,12 @@ define([
|
||||
}
|
||||
if (data.href) { href = data.href; }
|
||||
Cryptpad.getPadAttribute(data.key, function (e, data) {
|
||||
if (!safe && data) {
|
||||
// Remove unsafe data for the unsafe iframe
|
||||
delete data.href;
|
||||
delete data.roHref;
|
||||
delete data.password;
|
||||
}
|
||||
cb({
|
||||
error: e,
|
||||
data: data
|
||||
@@ -976,81 +979,63 @@ define([
|
||||
onFileUpload(sframeChan, data, cb);
|
||||
});
|
||||
|
||||
// File picker
|
||||
var FP = {};
|
||||
var initFilePicker = function (cfg) {
|
||||
// cfg.hidden means pre-loading the filepicker while keeping it hidden.
|
||||
// Secure modal
|
||||
var SecureModal = {};
|
||||
// Create or display the iframe and modal
|
||||
var initSecureModal = function (type, cfg, cb) {
|
||||
cfg.modal = type;
|
||||
SecureModal.cb = cb;
|
||||
// cfg.hidden means pre-loading the iframe while keeping it hidden.
|
||||
// if cfg.hidden is true and the iframe already exists, do nothing
|
||||
if (!FP.$iframe) {
|
||||
if (!SecureModal.$iframe) {
|
||||
var config = {};
|
||||
config.onFilePicked = function (data) {
|
||||
sframeChan.event('EV_FILE_PICKED', data);
|
||||
config.onAction = function (data) {
|
||||
if (typeof(SecureModal.cb) !== "function") { return; }
|
||||
SecureModal.cb(data);
|
||||
SecureModal.$iframe.hide();
|
||||
};
|
||||
config.onClose = function () {
|
||||
FP.$iframe.hide();
|
||||
SecureModal.$iframe.hide();
|
||||
};
|
||||
config.data = {
|
||||
hashes: hashes,
|
||||
password: password,
|
||||
isTemplate: isTemplate
|
||||
};
|
||||
config.onFileUpload = onFileUpload;
|
||||
config.types = cfg;
|
||||
config.addCommonRpc = addCommonRpc;
|
||||
config.modules = {
|
||||
Cryptpad: Cryptpad,
|
||||
SFrameChannel: SFrameChannel,
|
||||
Utils: Utils
|
||||
};
|
||||
FP.$iframe = $('<iframe>', {id: 'sbox-filePicker-iframe'}).appendTo($('body'));
|
||||
FP.picker = FilePicker.create(config);
|
||||
SecureModal.$iframe = $('<iframe>', {id: 'sbox-secure-iframe'}).appendTo($('body'));
|
||||
SecureModal.modal = SecureIframe.create(config);
|
||||
} else if (!cfg.hidden) {
|
||||
FP.$iframe.show();
|
||||
FP.picker.refresh(cfg);
|
||||
}
|
||||
if (cfg.hidden) {
|
||||
FP.$iframe.hide();
|
||||
return;
|
||||
}
|
||||
FP.$iframe.focus();
|
||||
};
|
||||
sframeChan.on('EV_FILE_PICKER_OPEN', function (data) {
|
||||
initFilePicker(data);
|
||||
});
|
||||
|
||||
// Share modal
|
||||
var ShareModal = {};
|
||||
var initShareModal = function (cfg) {
|
||||
cfg.hashes = hashes;
|
||||
cfg.password = password;
|
||||
cfg.isTemplate = isTemplate;
|
||||
// cfg.hidden means pre-loading the filepicker while keeping it hidden.
|
||||
// if cfg.hidden is true and the iframe already exists, do nothing
|
||||
if (!ShareModal.$iframe) {
|
||||
var config = {};
|
||||
config.onShareAction = function (data) {
|
||||
sframeChan.event('EV_SHARE_ACTION', data);
|
||||
};
|
||||
config.onClose = function () {
|
||||
ShareModal.$iframe.hide();
|
||||
};
|
||||
config.data = cfg;
|
||||
config.addCommonRpc = addCommonRpc;
|
||||
config.modules = {
|
||||
Cryptpad: Cryptpad,
|
||||
SFrameChannel: SFrameChannel,
|
||||
Utils: Utils
|
||||
};
|
||||
ShareModal.$iframe = $('<iframe>', {id: 'sbox-share-iframe'}).appendTo($('body'));
|
||||
ShareModal.modal = Share.create(config);
|
||||
} else if (!cfg.hidden) {
|
||||
ShareModal.modal.refresh(cfg, function () {
|
||||
ShareModal.$iframe.show();
|
||||
SecureModal.modal.refresh(cfg, function () {
|
||||
SecureModal.$iframe.show();
|
||||
});
|
||||
}
|
||||
if (cfg.hidden) {
|
||||
ShareModal.$iframe.hide();
|
||||
SecureModal.$iframe.hide();
|
||||
return;
|
||||
}
|
||||
ShareModal.$iframe.focus();
|
||||
SecureModal.$iframe.focus();
|
||||
};
|
||||
|
||||
sframeChan.on('Q_FILE_PICKER_OPEN', function (data, cb) {
|
||||
initSecureModal('filepicker', data || {}, cb);
|
||||
});
|
||||
|
||||
sframeChan.on('EV_PROPERTIES_OPEN', function (data) {
|
||||
initSecureModal('properties', data || {}, null);
|
||||
});
|
||||
|
||||
sframeChan.on('EV_ACCESS_OPEN', function (data) {
|
||||
initSecureModal('access', data || {}, null);
|
||||
});
|
||||
|
||||
sframeChan.on('EV_SHARE_OPEN', function (data) {
|
||||
initShareModal(data || {});
|
||||
initSecureModal('share', data || {}, null);
|
||||
});
|
||||
|
||||
sframeChan.on('Q_TEMPLATE_USE', function (data, cb) {
|
||||
@@ -1266,6 +1251,9 @@ define([
|
||||
var _parsed = Utils.Hash.parsePadUrl(metadata.roHref);
|
||||
_secret = Utils.Hash.getSecrets(_parsed.type, _parsed.hash, metadata.password);
|
||||
}
|
||||
if (_secret.channel.length !== 32) {
|
||||
return void cb({error: 'EINVAL'});
|
||||
}
|
||||
var crypto = Crypto.createEncryptor(_secret.keys);
|
||||
nThen(function (waitFor) {
|
||||
// Try to get the owner's mailbox from the pad metadata first.
|
||||
@@ -1325,6 +1313,9 @@ define([
|
||||
var _parsed = Utils.Hash.parsePadUrl(metadata.href || metadata.roHref);
|
||||
_secret = Utils.Hash.getSecrets(_parsed.type, _parsed.hash, metadata.password);
|
||||
}
|
||||
if (_secret.channel.length !== 32) {
|
||||
return void cb({error: 'EINVAL'});
|
||||
}
|
||||
var crypto = Crypto.createEncryptor(_secret.keys);
|
||||
nThen(function (waitFor) {
|
||||
// If we already have metadata, use it, otherwise, try to get it
|
||||
|
||||
@@ -89,7 +89,6 @@ define([
|
||||
window.CryptPad_UIElements = UIElements;
|
||||
window.CryptPad_common = funcs;
|
||||
funcs.createUserAdminMenu = callWithCommon(UIElements.createUserAdminMenu);
|
||||
funcs.initFilePicker = callWithCommon(UIElements.initFilePicker);
|
||||
funcs.openFilePicker = callWithCommon(UIElements.openFilePicker);
|
||||
funcs.openTemplatePicker = callWithCommon(UIElements.openTemplatePicker);
|
||||
funcs.displayMediatagImage = callWithCommon(MT.displayMediatagImage);
|
||||
|
||||
Reference in New Issue
Block a user