Encrypted href
This commit is contained in:
parent
cf0d0e8e4b
commit
5ab3f39fb8
@ -52,7 +52,8 @@ define([
|
||||
var cancel = function () {
|
||||
cancelled = true;
|
||||
};
|
||||
var parsed = Hash.parsePadUrl(fData.href || fData.roHref);
|
||||
var href = (fData.href && fData.href.indexOf('#') !== -1) ? fData.href : fData.roHref;
|
||||
var parsed = Hash.parsePadUrl(href);
|
||||
var hash = parsed.hash;
|
||||
var name = fData.filename || fData.title;
|
||||
var secret = Hash.getSecrets('file', hash, fData.password);
|
||||
@ -88,7 +89,8 @@ define([
|
||||
cancelled = true;
|
||||
};
|
||||
|
||||
var parsed = Hash.parsePadUrl(pData.href || pData.roHref);
|
||||
var href = (pData.href && pData.href.indexOf('#') !== -1) ? pData.href : pData.roHref;
|
||||
var parsed = Hash.parsePadUrl(href);
|
||||
var name = pData.filename || pData.title;
|
||||
var opts = {
|
||||
password: pData.password
|
||||
@ -137,7 +139,8 @@ define([
|
||||
});
|
||||
}
|
||||
|
||||
var parsed = Hash.parsePadUrl(fData.href || fData.roHref);
|
||||
var href = (fData.href && fData.href.indexOf('#') !== -1) ? fData.href : fData.roHref;
|
||||
var parsed = Hash.parsePadUrl(href);
|
||||
if (['pad', 'file'].indexOf(parsed.hashData.type) === -1) { return; }
|
||||
|
||||
// waitFor is used to make sure all the pads and files are process before downloading the zip.
|
||||
|
||||
@ -38,8 +38,7 @@ define([
|
||||
var data = oldFo.getFileData(id);
|
||||
var channel = data.channel;
|
||||
|
||||
// XXX encrypted href: we need to be able to change the value here
|
||||
var datas = manager.findChannel(channel, true);
|
||||
var datas = manager.findChannel(channel);
|
||||
// Do not migrate a pad if we already have it, it would create a duplicate
|
||||
// in the drive
|
||||
if (datas.length !== 0) {
|
||||
@ -50,7 +49,9 @@ define([
|
||||
// We want to merge an edit pad: check if we have the same channel
|
||||
// but read-only and upgrade it in that case
|
||||
datas.forEach(function (pad) {
|
||||
if (pad.data && !pad.data.href) { pad.data.href = data.href; }
|
||||
if (pad.data && !pad.data.href) {
|
||||
pad.userObject.setHref(channel, null, data.href);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@ -145,10 +145,14 @@ define([
|
||||
n = n.nThen(function (w) {
|
||||
setTimeout(w(function () {
|
||||
el = data[k];
|
||||
if (!el.href || (el.roHref && false)) {
|
||||
if (!el.href) {
|
||||
// Already migrated
|
||||
return void progress(7, Math.round(100*i/padsLength));
|
||||
}
|
||||
if (el.href.indexOf('#') === -1) {
|
||||
// Encrypted href: already migrated
|
||||
return void progress(7, Math.round(100*i/padsLength));
|
||||
}
|
||||
parsed = Hash.parsePadUrl(el.href);
|
||||
if (parsed.hashData.type !== "pad") {
|
||||
// No read-only mode for files
|
||||
|
||||
@ -1045,7 +1045,7 @@ define([
|
||||
if (data.teamId && s.id !== data.teamId) { return; }
|
||||
if (storeLocally && s.id) { return; }
|
||||
|
||||
var res = s.manager.findChannel(channel);
|
||||
var res = s.manager.findChannel(channel, true);
|
||||
if (res.length) {
|
||||
sendTo.push(s.id);
|
||||
}
|
||||
@ -1081,7 +1081,7 @@ define([
|
||||
// If all of the weaker ones were in the trash, add the stronger to ROOT
|
||||
obj.userObject.restoreHref(href);
|
||||
}
|
||||
pad.href = href;
|
||||
obj.userObject.setHref(channel, null, href);
|
||||
});
|
||||
|
||||
// Pads owned by us ("us" can be a user or a team) that are not in our "main" drive
|
||||
@ -1474,7 +1474,7 @@ define([
|
||||
onMetadataUpdate: function (metadata) {
|
||||
channel.data = metadata || {};
|
||||
getAllStores().forEach(function (s) {
|
||||
var allData = s.manager.findChannel(data.channel);
|
||||
var allData = s.manager.findChannel(data.channel, true);
|
||||
allData.forEach(function (obj) {
|
||||
obj.data.owners = metadata.owners;
|
||||
obj.data.atime = +new Date();
|
||||
@ -1640,7 +1640,7 @@ define([
|
||||
|
||||
// Update owners and expire time in the drive
|
||||
getAllStores().forEach(function (s) {
|
||||
var allData = s.manager.findChannel(data.channel);
|
||||
var allData = s.manager.findChannel(data.channel, true);
|
||||
var changed = false;
|
||||
allData.forEach(function (obj) {
|
||||
if (Sortify(obj.data.owners) !== Sortify(metadata.owners)) {
|
||||
|
||||
@ -249,14 +249,13 @@ define([
|
||||
if (msg.author !== content.user.curvePublic) { return void cb(true); }
|
||||
|
||||
var channel = content.channel;
|
||||
// XXX encrypted href
|
||||
var res = ctx.store.manager.findChannel(channel);
|
||||
var res = ctx.store.manager.findChannel(channel, true);
|
||||
|
||||
var title;
|
||||
res.forEach(function (obj) {
|
||||
if (obj.data && !obj.data.href) {
|
||||
if (!title) { title = obj.data.filename || obj.data.title; }
|
||||
obj.data.href = content.href;
|
||||
obj.userObject.setHref(channel, null, content.href);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -25,7 +25,9 @@ define([
|
||||
var teamId = store.id || -1;
|
||||
var handler = store.handleSharedFolder;
|
||||
|
||||
var parsed = Hash.parsePadUrl(data.href);
|
||||
var href = store.manager.user.userObject.getHref(data);
|
||||
|
||||
var parsed = Hash.parsePadUrl(href);
|
||||
var secret = Hash.getSecrets('drive', parsed.hash, data.password);
|
||||
var secondaryKey = secret.keys.secondaryKey;
|
||||
|
||||
|
||||
@ -31,13 +31,26 @@ define([
|
||||
|
||||
var debug = exp.debug;
|
||||
|
||||
exp.setHref = function (channel, id, href) {
|
||||
if (!id && !channel) { return; }
|
||||
var ids = id ? [id] : exp.findChannels([channel]);
|
||||
ids.forEach(function (i) {
|
||||
var data = exp.getFileData(i, true);
|
||||
data.href = exp.cryptor.encrypt(href);
|
||||
});
|
||||
};
|
||||
|
||||
exp.setPadAttribute = function (href, attr, value, cb) {
|
||||
cb = cb || function () {};
|
||||
var id = exp.getIdFromHref(href);
|
||||
if (!id) { return void cb("E_INVAL_HREF"); }
|
||||
if (!attr || !attr.trim()) { return void cb("E_INVAL_ATTR"); }
|
||||
var data = exp.getFileData(id, true);
|
||||
data[attr] = clone(value);
|
||||
if (attr === "href") {
|
||||
exp.setHref(null, id, value);
|
||||
} else {
|
||||
data[attr] = clone(value);
|
||||
}
|
||||
cb(null);
|
||||
};
|
||||
exp.getPadAttribute = function (href, attr, cb) {
|
||||
@ -51,6 +64,8 @@ define([
|
||||
exp.pushData = function (data, cb) {
|
||||
if (typeof cb !== "function") { cb = function () {}; }
|
||||
var id = Util.createRandomInteger();
|
||||
// If we were given an edit link, encrypt its value if needed
|
||||
if (data.href) { data.href = exp.cryptor.encrypt(data.href); }
|
||||
files[FILES_DATA][id] = data;
|
||||
cb(null, id);
|
||||
};
|
||||
@ -70,6 +85,7 @@ define([
|
||||
return void cb("EAUTH");
|
||||
}
|
||||
var id = Util.createRandomInteger();
|
||||
if (data.href) { data.href = exp.cryptor.encrypt(data.href); }
|
||||
files[SHARED_FOLDERS][id] = data;
|
||||
cb(null, id);
|
||||
};
|
||||
@ -209,11 +225,15 @@ define([
|
||||
id = Number(id);
|
||||
// Find and maybe update existing pads with the same channel id
|
||||
var d = data[id];
|
||||
// If we were given an edit link, encrypt its value if needed
|
||||
if (d.href) { d.href = exp.cryptor.encrypt(d.href); }
|
||||
var found = false;
|
||||
for (var i in files[FILES_DATA]) {
|
||||
if (files[FILES_DATA][i].channel === d.channel) {
|
||||
// Update href?
|
||||
if (!files[FILES_DATA][i].href) { files[FILES_DATA][i].href = d.href; }
|
||||
if (!files[FILES_DATA][i].href) {
|
||||
files[FILES_DATA][i].href = d.href;
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@ -222,7 +242,7 @@ define([
|
||||
toRemove.push(id);
|
||||
return;
|
||||
}
|
||||
files[FILES_DATA][id] = data[id];
|
||||
files[FILES_DATA][id] = d;
|
||||
});
|
||||
|
||||
// Remove existing pads from the "element" variable
|
||||
@ -500,6 +520,7 @@ define([
|
||||
|
||||
if (silent) { debug = function () {}; }
|
||||
|
||||
var t0 = +new Date();
|
||||
debug("Cleaning file system...");
|
||||
|
||||
var before = JSON.stringify(files);
|
||||
@ -536,7 +557,10 @@ define([
|
||||
// We have an old file (href) which is not in filesData: add it
|
||||
var id = Util.createRandomInteger();
|
||||
var key = Hash.createChannelId();
|
||||
files[FILES_DATA][id] = {href: element[el], filename: el};
|
||||
files[FILES_DATA][id] = {
|
||||
href: exp.cryptor.encrypt(element[el]),
|
||||
filename: el
|
||||
};
|
||||
element[key] = id;
|
||||
delete element[el];
|
||||
}
|
||||
@ -562,7 +586,10 @@ define([
|
||||
if (typeof obj.element === "string") {
|
||||
// We have an old file (href) which is not in filesData: add it
|
||||
var id = Util.createRandomInteger();
|
||||
files[FILES_DATA][id] = {href: obj.element, filename: el};
|
||||
files[FILES_DATA][id] = {
|
||||
href: exp.cryptor.encrypt(obj.element),
|
||||
filename: el
|
||||
};
|
||||
obj.element = id;
|
||||
}
|
||||
if (exp.isFolder(obj.element)) { fixRoot(obj.element); }
|
||||
@ -607,7 +634,9 @@ define([
|
||||
if (typeof el === "string") {
|
||||
// We have an old file (href) which is not in filesData: add it
|
||||
var id = Util.createRandomInteger();
|
||||
files[FILES_DATA][id] = {href: el};
|
||||
files[FILES_DATA][id] = {
|
||||
href: exp.cryptor.encrypt(el)
|
||||
};
|
||||
us[idx] = id;
|
||||
}
|
||||
if (typeof el === "number") {
|
||||
@ -653,7 +682,12 @@ define([
|
||||
continue;
|
||||
}
|
||||
|
||||
var parsed = Hash.parsePadUrl(el.href || el.roHref);
|
||||
var href;
|
||||
try {
|
||||
href = el.href && ((el.href.indexOf('#') !== -1) ? el.href : exp.cryptor.decrypt(el.href));
|
||||
} catch (e) {}
|
||||
|
||||
var parsed = Hash.parsePadUrl(href || el.roHref);
|
||||
var secret;
|
||||
|
||||
// Clean invalid hash
|
||||
@ -670,9 +704,9 @@ define([
|
||||
}
|
||||
|
||||
// If we have an edit link, check the view link
|
||||
if (el.href && parsed.hashData.type === "pad" && parsed.hashData.version) {
|
||||
if (href && parsed.hashData.type === "pad" && parsed.hashData.version) {
|
||||
if (parsed.hashData.mode === "view") {
|
||||
el.roHref = el.href;
|
||||
el.roHref = href;
|
||||
delete el.href;
|
||||
} else if (!el.roHref) {
|
||||
secret = Hash.getSecrets(parsed.type, parsed.hash, el.password);
|
||||
@ -691,7 +725,7 @@ define([
|
||||
}
|
||||
|
||||
// Fix href
|
||||
if (el.href && /^https*:\/\//.test(el.href)) { el.href = Hash.getRelativeHref(el.href); }
|
||||
if (href && href.slice(0,1) !== '/') { el.href = exp.cryptor.encrypt(Hash.getRelativeHref(el.href)); }
|
||||
// Fix creation time
|
||||
if (!el.ctime) { el.ctime = el.atime; }
|
||||
// Fix title
|
||||
@ -732,8 +766,13 @@ define([
|
||||
el = sf[id];
|
||||
id = Number(id);
|
||||
|
||||
var href;
|
||||
try {
|
||||
href = el.href && ((el.href.indexOf('#') !== -1) ? el.href : exp.cryptor.decrypt(el.href));
|
||||
} catch (e) {}
|
||||
|
||||
// Fix undefined hash
|
||||
parsed = Hash.parsePadUrl(el.href || el.roHref);
|
||||
parsed = Hash.parsePadUrl(href || el.roHref);
|
||||
secret = Hash.getSecrets('drive', parsed.hash, el.password);
|
||||
if (!secret.keys) {
|
||||
delete sf[id];
|
||||
@ -762,11 +801,12 @@ define([
|
||||
fixDrive();
|
||||
fixSharedFolders();
|
||||
|
||||
var ms = (+new Date() - t0) + 'ms';
|
||||
if (JSON.stringify(files) !== before) {
|
||||
debug("Your file system was corrupted. It has been cleaned so that the pads you visit can be stored safely");
|
||||
debug("Your file system was corrupted. It has been cleaned so that the pads you visit can be stored safely.", ms);
|
||||
return;
|
||||
}
|
||||
debug("File system was clean");
|
||||
debug("File system was clean.", ms);
|
||||
};
|
||||
|
||||
return exp;
|
||||
|
||||
@ -81,11 +81,13 @@ define([
|
||||
|
||||
// Return files data objects associated to a channel for setPadTitle
|
||||
// All occurences are returned, in drive or shared folders
|
||||
var findChannel = function (Env, channel) {
|
||||
// If "editable" is true, the data returned is a proxy, otherwise
|
||||
// it's a cloned object (NOTE: href should never be edited directly)
|
||||
var findChannel = function (Env, channel, editable) {
|
||||
var ret = [];
|
||||
Env.user.userObject.findChannels([channel]).forEach(function (id) {
|
||||
ret.push({
|
||||
data: Env.user.userObject.getFileData(id),
|
||||
data: Env.user.userObject.getFileData(id, editable),
|
||||
userObject: Env.user.userObject
|
||||
});
|
||||
});
|
||||
@ -93,7 +95,7 @@ define([
|
||||
Env.folders[fId].userObject.findChannels([channel]).forEach(function (id) {
|
||||
ret.push({
|
||||
fId: fId,
|
||||
data: Env.folders[fId].userObject.getFileData(id),
|
||||
data: Env.folders[fId].userObject.getFileData(id, editable),
|
||||
userObject: Env.folders[fId].userObject
|
||||
});
|
||||
});
|
||||
@ -101,6 +103,8 @@ define([
|
||||
return ret;
|
||||
};
|
||||
// Return files data objects associated to a given href for setPadAttribute...
|
||||
// If "editable" is true, the data returned is a proxy, otherwise
|
||||
// it's a cloned object (NOTE: href should never be edited directly)
|
||||
var findHref = function (Env, href) {
|
||||
var ret = [];
|
||||
var id = Env.user.userObject.getIdFromHref(href);
|
||||
@ -155,11 +159,11 @@ define([
|
||||
return ret;
|
||||
};
|
||||
|
||||
var _getFileData = function (Env, id) {
|
||||
var _getFileData = function (Env, id, editable) {
|
||||
var userObjects = _getUserObjects(Env);
|
||||
var data = {};
|
||||
userObjects.some(function (uo) {
|
||||
data = uo.getFileData(id);
|
||||
data = uo.getFileData(id, editable);
|
||||
if (Object.keys(data).length) { return true; }
|
||||
});
|
||||
return data;
|
||||
@ -278,11 +282,6 @@ define([
|
||||
filesData[f] = userObject.getFileData(f);
|
||||
});
|
||||
|
||||
// TODO RO
|
||||
// Encrypt or decrypt edit link here
|
||||
// filesData.forEach(function (d) { d.href = encrypt(d.href); });
|
||||
|
||||
|
||||
data.push({
|
||||
el: el,
|
||||
data: filesData,
|
||||
@ -435,6 +434,7 @@ define([
|
||||
Env.pinPads([folderData.channel], waitFor());
|
||||
}).nThen(function (waitFor) {
|
||||
// 1. add the shared folder to our list of shared folders
|
||||
// NOTE: pushSharedFolder will encrypt the href directly in the object if needed
|
||||
Env.user.userObject.pushSharedFolder(folderData, waitFor(function (err, folderId) {
|
||||
if (err) {
|
||||
waitFor.abort();
|
||||
@ -1128,7 +1128,13 @@ define([
|
||||
if (!Env.folders[id]) { return {}; }
|
||||
var obj = Env.folders[id].proxy.metadata || {};
|
||||
for (var k in Env.user.proxy[UserObject.SHARED_FOLDERS][id] || {}) {
|
||||
obj[k] = Env.user.proxy[UserObject.SHARED_FOLDERS][id][k];
|
||||
var data = JSON.parse(JSON.stringify(Env.user.proxy[UserObject.SHARED_FOLDERS][id][k]));
|
||||
if (data.href && data.href.indexOf('#') === -1) {
|
||||
try {
|
||||
data.href = Env.user.userObject.cryptor.decrypt(data.href);
|
||||
} catch (e) {}
|
||||
}
|
||||
obj[k] = data;
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
@ -39,7 +39,13 @@ define([
|
||||
};
|
||||
if (config.editKey) {
|
||||
try {
|
||||
exp.cryptor = Crypto.createEncryptor(config.editKey);
|
||||
var c = Crypto.createEncryptor(config.editKey);
|
||||
exp.cryptor.encrypt = function (href) {
|
||||
// Never encrypt blob href, they are always read-only
|
||||
if (href.slice(0,7) === '/file/#') { return href; }
|
||||
return c.encrypt(href);
|
||||
};
|
||||
exp.cryptor.decrypt = c.decrypt;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
@ -106,6 +112,16 @@ define([
|
||||
return a;
|
||||
};
|
||||
|
||||
var getHref = exp.getHref = function (pad) {
|
||||
if (pad.href && pad.href.indexOf('#') !== -1) {
|
||||
return pad.href;
|
||||
}
|
||||
if (pad.href) {
|
||||
return exp.cryptor.decrypt(pad.href);
|
||||
}
|
||||
return pad.roHref;
|
||||
};
|
||||
|
||||
var type = function (dat) {
|
||||
return dat === null? 'null': Array.isArray(dat)?'array': typeof(dat);
|
||||
};
|
||||
@ -219,12 +235,23 @@ define([
|
||||
};
|
||||
|
||||
// Get data from AllFiles (Cryptpad_RECENTPADS)
|
||||
var getFileData = exp.getFileData = function (file, noCopy) {
|
||||
var getFileData = exp.getFileData = function (file, editable) {
|
||||
if (!file) { return; }
|
||||
var data = files[FILES_DATA][file] || {};
|
||||
if (!noCopy) {
|
||||
// XXX encrypted href: decrypt or remove "href"
|
||||
if (!editable) {
|
||||
data = JSON.parse(JSON.stringify(data));
|
||||
if (data.href && data.href.indexOf('#') === -1) {
|
||||
// Encrypted href: decrypt it if we can, otherwise remove it
|
||||
if (config.editKey) {
|
||||
try {
|
||||
data.href = exp.cryptor.decrypt(data.href);
|
||||
} catch (e) {
|
||||
delete data.href;
|
||||
}
|
||||
} else {
|
||||
delete data.href;
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
};
|
||||
@ -401,7 +428,7 @@ define([
|
||||
var getIdFromHref = exp.getIdFromHref = function (href) {
|
||||
var result;
|
||||
getFiles([FILES_DATA]).some(function (id) {
|
||||
if (files[FILES_DATA][id].href === href ||
|
||||
if (getHref(files[FILES_DATA][id]) === href ||
|
||||
files[FILES_DATA][id].roHref === href) {
|
||||
result = id;
|
||||
return true;
|
||||
@ -413,7 +440,7 @@ define([
|
||||
exp.getSFIdFromHref = function (href) {
|
||||
var result;
|
||||
getFiles([SHARED_FOLDERS]).some(function (id) {
|
||||
if (files[SHARED_FOLDERS][id].href === href ||
|
||||
if (getHref(files[SHARED_FOLDERS][id]) === href ||
|
||||
files[SHARED_FOLDERS][id].roHref === href) {
|
||||
result = id;
|
||||
return true;
|
||||
|
||||
@ -97,7 +97,7 @@ define([
|
||||
for (var i = 0; i<old.length; i++) {
|
||||
try {
|
||||
pad = old[i];
|
||||
href = pad.href || pad.roHref;
|
||||
href = (pad.href && pad.href.indexOf('#') !== -1) ? pad.href : pad.roHref;
|
||||
chan = channelByHref[href];
|
||||
if (!chan && href) {
|
||||
parsed = Hash.parsePadUrl(href);
|
||||
@ -121,7 +121,7 @@ define([
|
||||
for (var id in ids) {
|
||||
try {
|
||||
pad = ids[id];
|
||||
href = pad.href || pad.roHref;
|
||||
href = (pad.href && pad.href.indexOf('#') !== -1) ? pad.href : pad.roHref;
|
||||
chan = pad.channel || channelByHref[href];
|
||||
if (!chan) {
|
||||
if (href) {
|
||||
|
||||
@ -43,7 +43,7 @@ define([
|
||||
var oldIds = Object.keys(folders);
|
||||
nThen(function (waitFor) {
|
||||
Object.keys(drive.sharedFolders).forEach(function (fId) {
|
||||
var sfData = drive.sharedFolders[id] || {};
|
||||
var sfData = drive.sharedFolders[fId] || {};
|
||||
var parsed = Hash.parsePadUrl(sfData.href);
|
||||
var secret = Hash.getSecrets('drive', parsed.hash, sfData.password);
|
||||
sframeChan.query('Q_DRIVE_GETOBJECT', {
|
||||
|
||||
@ -958,12 +958,12 @@ define([
|
||||
$(list).appendTo(errors);
|
||||
errs.forEach(function (err) {
|
||||
if (!err.data) { return; }
|
||||
var href = err.data.href || err.data.roHref;
|
||||
var href = (err.data.href && err.data.href.indexOf('#') !== -1) ? err.data.href : err.data.roHref;
|
||||
$(h('div', [
|
||||
h('div.title', err.data.filename || err.data.title),
|
||||
h('div.link', [
|
||||
h('a', {
|
||||
href: err.data.href || err.data.roHref,
|
||||
href: href,
|
||||
target: '_blank'
|
||||
}, privateData.origin + href)
|
||||
]),
|
||||
|
||||
@ -52,7 +52,7 @@ define([
|
||||
var oldIds = Object.keys(folders);
|
||||
nThen(function (waitFor) {
|
||||
Object.keys(drive.sharedFolders).forEach(function (fId) {
|
||||
var sfData = drive.sharedFolders[id] || {};
|
||||
var sfData = drive.sharedFolders[fId] || {};
|
||||
var parsed = Hash.parsePadUrl(sfData.href);
|
||||
var secret = Hash.getSecrets('drive', parsed.hash, sfData.password);
|
||||
sframeChan.query('Q_DRIVE_GETOBJECT', {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user