Make thumbnails more secure

pull/1/head
yflory 7 years ago
parent 2ff66e1a7c
commit 6b9ffe8dd1

@ -4,9 +4,8 @@ define([
'/common/visible.js', '/common/visible.js',
'/common/common-hash.js', '/common/common-hash.js',
'/file/file-crypto.js', '/file/file-crypto.js',
'/bower_components/localforage/dist/localforage.min.js',
'/bower_components/tweetnacl/nacl-fast.min.js', '/bower_components/tweetnacl/nacl-fast.min.js',
], function ($, Util, Visible, Hash, FileCrypto, localForage) { ], function ($, Util, Visible, Hash, FileCrypto) {
var Nacl = window.nacl; var Nacl = window.nacl;
var Thumb = { var Thumb = {
dimension: 100, dimension: 100,
@ -196,7 +195,7 @@ define([
require(['/bower_components/html2canvas/build/html2canvas.min.js'], todo); require(['/bower_components/html2canvas/build/html2canvas.min.js'], todo);
}; };
Thumb.initPadThumbnails = function (opts) { Thumb.initPadThumbnails = function (common, opts) {
if (!opts.href || !opts.getContent) { if (!opts.href || !opts.getContent) {
throw new Error("href and getContent are needed for thumbnails"); throw new Error("href and getContent are needed for thumbnails");
} }
@ -206,7 +205,7 @@ define([
if (content === oldThumbnailState) { return; } if (content === oldThumbnailState) { return; }
Thumb.fromDOM(opts, function (err, b64) { Thumb.fromDOM(opts, function (err, b64) {
oldThumbnailState = content; oldThumbnailState = content;
Thumb.setPadThumbnail(opts.href, b64); Thumb.setPadThumbnail(common, opts.href, b64);
}); });
}; };
var nafa = Util.notAgainForAnother(mkThumbnail, Thumb.UPDATE_INTERVAL); var nafa = Util.notAgainForAnother(mkThumbnail, Thumb.UPDATE_INTERVAL);
@ -238,15 +237,19 @@ define([
$span.prepend(img); $span.prepend(img);
cb($(img)); cb($(img));
}; };
Thumb.setPadThumbnail = function (href, b64, cb) { var getKey = function (href) {
var parsed = Hash.parsePadUrl(href);
return 'thumbnail-' + parsed.type + '-' + parsed.hashData.channel;
};
Thumb.setPadThumbnail = function (common, href, b64, cb) {
cb = cb || function () {}; cb = cb || function () {};
var k ='thumbnail-' + href; var k = getKey(href);
localForage.setItem(k, b64, cb); common.setThumbnail(k, b64, cb);
}; };
Thumb.displayThumbnail = function (href, $container, cb) { Thumb.displayThumbnail = function (common, href, $container, cb) {
cb = cb || function () {}; cb = cb || function () {};
var parsed = Hash.parsePadUrl(href); var parsed = Hash.parsePadUrl(href);
var k ='thumbnail-' + href; var k = getKey(href);
var whenNewThumb = function () { var whenNewThumb = function () {
var secret = Hash.getSecrets('file', parsed.hash); var secret = Hash.getSecrets('file', parsed.hash);
var hexFileName = Util.base64ToHex(secret.channel); var hexFileName = Util.base64ToHex(secret.channel);
@ -254,15 +257,17 @@ define([
var cryptKey = secret.keys && secret.keys.fileKeyStr; var cryptKey = secret.keys && secret.keys.fileKeyStr;
var key = Nacl.util.decodeBase64(cryptKey); var key = Nacl.util.decodeBase64(cryptKey);
FileCrypto.fetchDecryptedMetadata(src, key, function (e, metadata) { FileCrypto.fetchDecryptedMetadata(src, key, function (e, metadata) {
if (!metadata.thumbnail) { var v = metadata.thumbnail;
return void localForage.setItem(k, 'EMPTY'); if (!v) {
v = 'EMPTY';
} }
localForage.setItem(k, metadata.thumbnail, function (err) { Thumb.setPadThumbnail(common, href, v, function (err) {
if (!metadata.thumbnail) { return; }
addThumbnail(err, metadata.thumbnail, $container, cb); addThumbnail(err, metadata.thumbnail, $container, cb);
}); });
}); });
}; };
localForage.getItem(k, function (err, v) { common.getThumbnail(k, function (err, v) {
if (!v && parsed.type === 'file') { if (!v && parsed.type === 'file') {
// We can only create thumbnails for files here since we can't easily decrypt pads // We can only create thumbnails for files here since we can't easily decrypt pads
return void whenNewThumb(); return void whenNewThumb();

@ -21,9 +21,10 @@ define([
'/customize/application_config.js', '/customize/application_config.js',
'/common/media-tag.js', '/common/media-tag.js',
'/bower_components/nthen/index.js', '/bower_components/nthen/index.js',
'/bower_components/localforage/dist/localforage.min.js',
], function ($, Config, Messages, Store, Util, Hash, UI, History, UserList, Title, Metadata, ], function ($, Config, Messages, Store, Util, Hash, UI, History, UserList, Title, Metadata,
Messaging, CodeMirror, Files, FileCrypto, Realtime, Clipboard, Messaging, CodeMirror, Files, FileCrypto, Realtime, Clipboard,
Pinpad, AppConfig, MediaTag, Nthen) { Pinpad, AppConfig, MediaTag, Nthen, localForage) {
// Configure MediaTags to use our local viewer // Configure MediaTags to use our local viewer
if (MediaTag && MediaTag.PdfPlugin) { if (MediaTag && MediaTag.PdfPlugin) {
@ -519,6 +520,13 @@ define([
}); });
}; };
common.setThumbnail = function (key, value, cb) {
localForage.setItem(key, value, cb);
};
common.getThumbnail = function (key, cb) {
localForage.getItem(key, cb);
};
/* this returns a reference to your proxy. changing it will change your drive. /* this returns a reference to your proxy. changing it will change your drive.
*/ */
var getFileEntry = common.getFileEntry = function (href, cb) { var getFileEntry = common.getFileEntry = function (href, cb) {

@ -276,7 +276,7 @@ define([
if (!cpNfInner.chainpad) { return; } if (!cpNfInner.chainpad) { return; }
return cpNfInner.chainpad.getUserDoc(); return cpNfInner.chainpad.getUserDoc();
}; };
Thumb.initPadThumbnails(options.thumbnail); Thumb.initPadThumbnails(common, options.thumbnail);
} }
} }

@ -309,6 +309,20 @@ define([
}); });
}); });
sframeChan.on('Q_THUMBNAIL_GET', function (data, cb) {
Cryptpad.getThumbnail(data.key, function (e, data) {
cb({
error: e,
data: data
});
});
});
sframeChan.on('Q_THUMBNAIL_SET', function (data, cb) {
Cryptpad.setThumbnail(data.key, data.value, function (e) {
cb({error:e});
});
});
sframeChan.on('Q_SESSIONSTORAGE_PUT', function (data, cb) { sframeChan.on('Q_SESSIONSTORAGE_PUT', function (data, cb) {
sessionStorage[data.key] = data.value; sessionStorage[data.key] = data.value;
cb(); cb();

@ -15,7 +15,8 @@ define([
'/common/cryptpad-common.js', '/common/cryptpad-common.js',
'/common/common-realtime.js', '/common/common-realtime.js',
'/common/common-util.js', '/common/common-util.js',
'/common/common-thumbnail.js' '/common/common-thumbnail.js',
'/bower_components/localforage/dist/localforage.min.js'
], function ( ], function (
$, $,
nThen, nThen,
@ -32,9 +33,9 @@ define([
Cryptpad, Cryptpad,
CommonRealtime, CommonRealtime,
Util, Util,
Thumb Thumb,
localForage
) { ) {
// Chainpad Netflux Inner // Chainpad Netflux Inner
var funcs = {}; var funcs = {};
var ctx = {}; var ctx = {};
@ -84,7 +85,7 @@ define([
funcs.updateTags = callWithCommon(UI.updateTags); funcs.updateTags = callWithCommon(UI.updateTags);
// Thumb // Thumb
funcs.displayThumbnail = Thumb.displayThumbnail; funcs.displayThumbnail = callWithCommon(Thumb.displayThumbnail);
// History // History
funcs.getHistory = callWithCommon(History.create); funcs.getHistory = callWithCommon(History.create);
@ -218,6 +219,22 @@ define([
}, cb); }, cb);
}; };
// Thumbnails
funcs.setThumbnail = function (key, value, cb) {
cb = cb || $.noop;
ctx.sframeChan.query('Q_THUMBNAIL_SET', {
key: key,
value: value
}, cb);
};
funcs.getThumbnail = function (key, cb) {
ctx.sframeChan.query('Q_THUMBNAIL_GET', {
key: key
}, function (err, res) {
cb (err || res.error, res.data);
});
};
funcs.sessionStorage = { funcs.sessionStorage = {
put: function (key, value, cb) { put: function (key, value, cb) {
ctx.sframeChan.query('Q_SESSIONSTORAGE_PUT', { ctx.sframeChan.query('Q_SESSIONSTORAGE_PUT', {
@ -310,6 +327,8 @@ define([
SFrameChannel.create(window.parent, waitFor(function (sfc) { ctx.sframeChan = sfc; }), true); SFrameChannel.create(window.parent, waitFor(function (sfc) { ctx.sframeChan = sfc; }), true);
// CpNfInner.start() should be here.... // CpNfInner.start() should be here....
}).nThen(function () { }).nThen(function () {
localForage.clear();
ctx.metadataMgr = MetadataMgr.create(ctx.sframeChan); ctx.metadataMgr = MetadataMgr.create(ctx.sframeChan);
ctx.sframeChan.whenReg('EV_CACHE_PUT', function () { ctx.sframeChan.whenReg('EV_CACHE_PUT', function () {

@ -171,5 +171,9 @@ define({
// Add or remove the avatar from the profile. // Add or remove the avatar from the profile.
// We have to pin/unpin the avatar and store/remove the value from the user object // We have to pin/unpin the avatar and store/remove the value from the user object
'Q_PROFILE_AVATAR_ADD': true, 'Q_PROFILE_AVATAR_ADD': true,
'Q_PROFILE_AVATAR_REMOVE': true 'Q_PROFILE_AVATAR_REMOVE': true,
// Store outside and get thumbnails inside (stored with localForage (indexedDB) outside)
'Q_THUMBNAIL_SET': true,
'Q_THUMBNAIL_GET': true,
}); });

@ -837,7 +837,7 @@ define([
href: href, href: href,
getContent: function () { return JSON.stringify(APP.proxy.content); } getContent: function () { return JSON.stringify(APP.proxy.content); }
}; };
Thumb.initPadThumbnails(options); Thumb.initPadThumbnails(common, options);
}; };
var checkDeletedCells = function () { var checkDeletedCells = function () {

@ -390,7 +390,7 @@ define([
var D = Thumb.getResizedDimensions($canvas[0], 'pad'); var D = Thumb.getResizedDimensions($canvas[0], 'pad');
Thumb.fromCanvas($canvas[0], D, function (err, b64) { Thumb.fromCanvas($canvas[0], D, function (err, b64) {
oldThumbnailState = content; oldThumbnailState = content;
Thumb.setPadThumbnail(href, b64); Thumb.setPadThumbnail(common, href, b64);
}); });
}; };
window.setInterval(mkThumbnail, Thumb.UPDATE_INTERVAL); window.setInterval(mkThumbnail, Thumb.UPDATE_INTERVAL);

Loading…
Cancel
Save