Migrate the file to a sandboxed iframe

This commit is contained in:
yflory
2017-09-12 18:40:11 +02:00
parent 5ac3e97dc8
commit 437f50fd4a
21 changed files with 1697 additions and 317 deletions

View File

@@ -2024,6 +2024,7 @@ define([
common.getRecentPads(function (err, recent) {
var parsed = parsePadUrl(window.location.href);
if (!parsed.type || !parsed.hashData) { return void cb('E_INVALID_HREF'); }
if (parsed.type === 'file') { secret.channel = Util.base64ToHex(secret.channel); }
var hashes = common.getHashes(secret.channel, secret);
if (!hashes.editHash && !hashes.viewHash && parsed.hashData && !parsed.hashData.mode) {

View File

@@ -6,7 +6,9 @@ define([
], function (nThen, ApiConfig, $) {
var common = {};
common.start = function () {
common.start = function (cfg) {
cfg = cfg || {};
var realtime = !cfg.noRealtime;
var secret;
var hashes;
var CpNfOuter;
@@ -60,7 +62,7 @@ define([
name = n;
}));
}).nThen(function (/*waitFor*/) {
sframeChan.event('EV_METADATA_UPDATE', {
var metaObj = {
doc: {
defaultTitle: defaultTitle,
type: parsed.type
@@ -77,6 +79,7 @@ define([
accountName: Cryptpad.getAccountName(),
origin: window.location.origin,
pathname: window.location.pathname,
fileHost: ApiConfig.fileHost,
readOnly: readOnly,
availableHashes: hashes,
isTemplate: Cryptpad.isTemplate(window.location.href),
@@ -86,7 +89,11 @@ define([
isPresent: parsed.hashData && parsed.hashData.present,
isEmbed: parsed.hashData && parsed.hashData.embed,
}
});
};
if (cfg.addData) {
cfg.addData(metaObj.priv, Cryptpad);
}
sframeChan.event('EV_METADATA_UPDATE', metaObj);
});
};
Cryptpad.onDisplayNameChanged(updateMeta);
@@ -341,8 +348,16 @@ define([
}
});
if (cfg.addRpc) {
cfg.addRpc(sframeChan, Cryptpad);
}
sframeChan.ready();
Cryptpad.reportAppUsage();
if (!realtime) { return; }
CpNfOuter.start({
sframeChan: sframeChan,
channel: secret.channel,
@@ -362,7 +377,6 @@ define([
Cryptpad.replaceHash(Cryptpad.getEditHashFromKeys(wc.id, secret.keys));
}
});
Cryptpad.reportAppUsage();
});
};

View File

@@ -16,7 +16,7 @@ define(['jquery'], function ($) {
var $title;
exp.setToolbar = function (toolbar) {
$title = toolbar && toolbar.title;
$title = toolbar && (toolbar.title || toolbar.pageTitle);
};
exp.getTitle = function () { return exp.title; };
@@ -41,8 +41,10 @@ define(['jquery'], function ($) {
metadataMgr.onChange(function () {
var md = metadataMgr.getMetadata();
$title.find('span.cp-toolbar-title-value').text(md.title || md.defaultTitle);
$title.find('input').val(md.title || md.defaultTitle);
if ($title) {
$title.find('span.cp-toolbar-title-value').text(md.title || md.defaultTitle);
$title.find('input').val(md.title || md.defaultTitle);
}
exp.title = md.title;
});
metadataMgr.onTitleChange(function (title) {

View File

@@ -57,8 +57,7 @@ define([
funcs.getAppConfig = function () { return AppConfig; };
funcs.isLoggedIn = function () {
if (!ctx.cpNfInner) { throw new Error("cpNfInner is not ready!"); }
return ctx.cpNfInner.metadataMgr.getPrivateData().accountName;
return ctx.metadataMgr.getPrivateData().accountName;
};
// MISC
@@ -78,6 +77,7 @@ define([
funcs.openTemplatePicker = callWithCommon(UI.openTemplatePicker);
funcs.displayAvatar = callWithCommon(UI.displayAvatar);
funcs.createButton = callWithCommon(UI.createButton);
funcs.getFileSize = callWithCommon(UI.getFileSize);
// History
funcs.getHistory = callWithCommon(History.create);
@@ -88,6 +88,24 @@ define([
// Files
funcs.uploadFile = callWithCommon(File.uploadFile);
funcs.createFileManager = callWithCommon(File.create);
funcs.getMediatagScript = function () {
var origin = ctx.metadataMgr.getPrivateData().origin;
return '<script src="' + origin + '/common/media-tag-nacl.min.js"></script>';
};
funcs.getMediatagFromHref = function (href) {
var parsed = Cryptpad.parsePadUrl(href);
var secret = Cryptpad.getSecrets('file', parsed.hash);
var data = ctx.metadataMgr.getPrivateData();
if (secret.keys && secret.channel) {
var cryptKey = secret.keys && secret.keys.fileKeyStr;
var hexFileName = Cryptpad.base64ToHex(secret.channel);
var origin = data.fileHost || data.origin;
var src = origin + Cryptpad.getBlobPathFromHex(hexFileName);
return '<media-tag src="' + src + '" data-crypto-key="cryptpad:' + cryptKey + '">' +
'</media-tag>';
}
return;
};
// CodeMirror
funcs.initCodeMirrorApp = callWithCommon(CodeMirror.create);
@@ -171,6 +189,7 @@ define([
funcs.isStrongestStored = function () {
var data = ctx.metadataMgr.getPrivateData();
if (data.availableHashes.fileHash) { return true; }
return !data.readOnly || !data.availableHashes.editHash;
};

View File

@@ -345,6 +345,7 @@ define([
show();
});
initUserList(toolbar, config);
return $container;
};
@@ -473,22 +474,59 @@ define([
return "Loading share button";
};
var createFileShare = function (toolbar) {
if (true) { throw new Error('TODO: Update createFileShare to add "embed" and work in secure iframes'); }
if (!window.location.hash) {
throw new Error("Unable to display the share button: hash required in the URL");
var createFileShare = function (toolbar, config) {
if (!config.metadataMgr) {
throw new Error("You must provide a `metadataMgr` to display the userlist");
}
var metadataMgr = config.metadataMgr;
var origin = config.metadataMgr.getPrivateData().origin;
var pathname = config.metadataMgr.getPrivateData().pathname;
var hashes = metadataMgr.getPrivateData().availableHashes;
var url = origin + pathname + '#' + hashes.fileHash;
var $shareIcon = $('<span>', {'class': 'fa fa-share-alt'});
var $button = $('<button>', {'title': Messages.shareButton}).append($shareIcon);
$button.addClass('cp-toolbar-share-button');
$button.click(function () {
var url = window.location.href;
var options = [];
options.push({
tag: 'a',
attributes: {title: Messages.editShareTitle, 'class': 'cp-toolbar-share-file-copy'},
content: '<span class="fa fa-file"></span> ' + Messages.fileShare
});
options.push({
tag: 'a',
attributes: {title: Messages.fileEmbedTitle, 'class': 'cp-toolbar-share-file-embed'},
content: '<span class="fa fa-file"></span> ' + Messages.getEmbedCode
});
var dropdownConfigShare = {
text: $('<div>').append($shareIcon).html(),
options: options,
feedback: 'FILESHARE_MENU',
};
var $shareBlock = Cryptpad.createDropdown(dropdownConfigShare);
$shareBlock.find('.cp-dropdown-content').addClass(SHARE_CLS);
$shareBlock.addClass('cp-toolbar-share-button');
$shareBlock.find('button').attr('title', Messages.shareButton);
// Add handlers
$shareBlock.find('a.cp-toolbar-share-file-copy').click(function () {
var success = Cryptpad.Clipboard.copy(url);
if (success) { Cryptpad.log(Messages.shareSuccess); }
});
$shareBlock.find('a.cp-toolbar-share-file-embed').click(function () {
var $content = $('<div>');
$('<input>', {'style':'display:none;'}).appendTo($content);
$('<h3>').text(Messages.fileEmbedTitle).appendTo($content);
var $script = $('<p>').text(Messages.fileEmbedScript).appendTo($content);
$('<br>').appendTo($script);
$script.append(Cryptpad.dialog.selectable(Common.getMediatagScript()));
var $tag = $('<p>').text(Messages.fileEmbedTag).appendTo($content);
$('<br>').appendTo($tag);
$tag.append(Cryptpad.dialog.selectable(Common.getMediatagFromHref(url)));
Cryptpad.alert($content[0], null, true);
});
toolbar.$leftside.append($button);
return $button;
toolbar.$leftside.append($shareBlock);
return $shareBlock;
};
var createTitle = function (toolbar, config) {
@@ -820,13 +858,13 @@ define([
$title.find('input').trigger(ev);
};
// Click in the main window
var w = config.ifrw || window;
var w = window;
$(w).on('click', removeDropdowns);
$(w).on('click', cancelEditTitle);
// Click in iframes
try {
if (w.$ && w.$('iframe').length) {
config.ifrw.$('iframe').each(function (i, el) {
w.$('iframe').each(function (i, el) {
$(el.contentWindow).on('click', removeDropdowns);
$(el.contentWindow).on('click', cancelEditTitle);
});
@@ -956,9 +994,9 @@ define([
var tb = {};
tb['userlist'] = createUserList;
tb['share'] = createShare;
tb['fileshare'] = createFileShare;//TODO
tb['fileshare'] = createFileShare;
tb['title'] = createTitle;
tb['pageTitle'] = createPageTitle;//TODO
tb['pageTitle'] = createPageTitle;
tb['lag'] = $.noop;
tb['spinner'] = createSpinner;
tb['state'] = $.noop;
@@ -980,7 +1018,6 @@ define([
};
addElement(config.displayed, {}, true);
initUserList(toolbar, config);
toolbar['linkToMain'] = createLinkToMain(toolbar, config);