Merge branch 'staging' of github.com:xwiki-labs/cryptpad into staging
This commit is contained in:
commit
bef5aa0b2b
@ -32,6 +32,7 @@ define(function () {
|
|||||||
out.error = "Erreur";
|
out.error = "Erreur";
|
||||||
out.saved = "Enregistré";
|
out.saved = "Enregistré";
|
||||||
out.synced = "Tout est enregistré";
|
out.synced = "Tout est enregistré";
|
||||||
|
out.deleted = "Pad supprimé de votre CryptDrive";
|
||||||
|
|
||||||
out.disconnected = 'Déconnecté';
|
out.disconnected = 'Déconnecté';
|
||||||
out.synchronizing = 'Synchronisation';
|
out.synchronizing = 'Synchronisation';
|
||||||
|
|||||||
@ -34,6 +34,7 @@ define(function () {
|
|||||||
out.error = "Error";
|
out.error = "Error";
|
||||||
out.saved = "Saved";
|
out.saved = "Saved";
|
||||||
out.synced = "Everything is saved";
|
out.synced = "Everything is saved";
|
||||||
|
out.deleted = "Pad deleted from your CryptDrive";
|
||||||
|
|
||||||
out.disconnected = 'Disconnected';
|
out.disconnected = 'Disconnected';
|
||||||
out.synchronizing = 'Synchronizing';
|
out.synchronizing = 'Synchronizing';
|
||||||
|
|||||||
@ -149,9 +149,7 @@ define([
|
|||||||
left: true, // Open to the left of the button
|
left: true, // Open to the left of the button
|
||||||
isSelect: true,
|
isSelect: true,
|
||||||
};
|
};
|
||||||
console.log('here');
|
|
||||||
var $block = exp.$language = Cryptpad.createDropdown(dropdownConfig);
|
var $block = exp.$language = Cryptpad.createDropdown(dropdownConfig);
|
||||||
console.log(exp);
|
|
||||||
$block.find('a').click(function () {
|
$block.find('a').click(function () {
|
||||||
setMode($(this).attr('data-value'), $block);
|
setMode($(this).attr('data-value'), $block);
|
||||||
onLocal();
|
onLocal();
|
||||||
|
|||||||
@ -32,9 +32,65 @@ define([
|
|||||||
return '/1/view/' + hexToBase64(chanKey) + '/'+Crypto.b64RemoveSlashes(keys.viewKeyStr)+'/';
|
return '/1/view/' + hexToBase64(chanKey) + '/'+Crypto.b64RemoveSlashes(keys.viewKeyStr)+'/';
|
||||||
};
|
};
|
||||||
var getFileHashFromKeys = Hash.getFileHashFromKeys = function (fileKey, cryptKey) {
|
var getFileHashFromKeys = Hash.getFileHashFromKeys = function (fileKey, cryptKey) {
|
||||||
return '/2/' + hexToBase64(fileKey) + '/' + Crypto.b64RemoveSlashes(cryptKey) + '/';
|
return '/1/' + hexToBase64(fileKey) + '/' + Crypto.b64RemoveSlashes(cryptKey) + '/';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var fixDuplicateSlashes = function (s) {
|
||||||
|
return s.replace(/\/+/g, '/');
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Version 0
|
||||||
|
/pad/#67b8385b07352be53e40746d2be6ccd7XAYSuJYYqa9NfmInyHci7LNy
|
||||||
|
Version 1
|
||||||
|
/code/#/1/edit/3Ujt4F2Sjnjbis6CoYWpoQ/usn4+9CqVja8Q7RZOGTfRgqI
|
||||||
|
*/
|
||||||
|
|
||||||
|
var parseTypeHash = Hash.parseTypeHash = function (type, hash) {
|
||||||
|
if (!hash) { return; }
|
||||||
|
var parsed = {};
|
||||||
|
var hashArr = fixDuplicateSlashes(hash).split('/');
|
||||||
|
if (['media', 'file', 'user'].indexOf(type) === -1) {
|
||||||
|
parsed.type = 'pad';
|
||||||
|
if (hash.slice(0,1) !== '/' && hash.length >= 56) {
|
||||||
|
// Old hash
|
||||||
|
parsed.channel = hash.slice(0, 32);
|
||||||
|
parsed.key = hash.slice(32);
|
||||||
|
parsed.version = 0;
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
if (hashArr[1] && hashArr[1] === '1') {
|
||||||
|
parsed.version = 1;
|
||||||
|
parsed.mode = hashArr[2];
|
||||||
|
parsed.channel = hashArr[3];
|
||||||
|
parsed.key = hashArr[4].replace(/-/g, '/');
|
||||||
|
parsed.present = typeof(hashArr[5]) === "string" && hashArr[5] === 'present';
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
if (['media', 'file'].indexOf(type) !== -1) {
|
||||||
|
parsed.type = 'file';
|
||||||
|
if (hashArr[1] && hashArr[1] === '1') {
|
||||||
|
parsed.version = 1;
|
||||||
|
parsed.channel = hashArr[2].replace(/-/g, '/');
|
||||||
|
parsed.key = hashArr[3].replace(/-/g, '/');
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
if (['user'].indexOf(type) !== -1) {
|
||||||
|
parsed.type = 'user';
|
||||||
|
if (hashArr[1] && hashArr[1] === '1') {
|
||||||
|
parsed.version = 1;
|
||||||
|
parsed.user = hashArr[2];
|
||||||
|
parsed.pubkey = hashArr[3].replace(/-/g, '/');
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
};
|
||||||
var parsePadUrl = Hash.parsePadUrl = function (href) {
|
var parsePadUrl = Hash.parsePadUrl = function (href) {
|
||||||
var patt = /^https*:\/\/([^\/]*)\/(.*?)\//i;
|
var patt = /^https*:\/\/([^\/]*)\/(.*?)\//i;
|
||||||
|
|
||||||
@ -43,10 +99,13 @@ define([
|
|||||||
if (!href) { return ret; }
|
if (!href) { return ret; }
|
||||||
if (href.slice(-1) !== '/') { href += '/'; }
|
if (href.slice(-1) !== '/') { href += '/'; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!/^https*:\/\//.test(href)) {
|
if (!/^https*:\/\//.test(href)) {
|
||||||
var idx = href.indexOf('/#');
|
var idx = href.indexOf('/#');
|
||||||
ret.type = href.slice(1, idx);
|
ret.type = href.slice(1, idx);
|
||||||
ret.hash = href.slice(idx + 2);
|
ret.hash = href.slice(idx + 2);
|
||||||
|
ret.hashData = parseTypeHash(ret.type, ret.hash);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +115,7 @@ define([
|
|||||||
return '';
|
return '';
|
||||||
});
|
});
|
||||||
ret.hash = hash.replace(/#/g, '');
|
ret.hash = hash.replace(/#/g, '');
|
||||||
|
ret.hashData = parseTypeHash(ret.type, ret.hash);
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -66,16 +126,12 @@ define([
|
|||||||
return '/' + parsed.type + '/#' + parsed.hash;
|
return '/' + parsed.type + '/#' + parsed.hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
var fixDuplicateSlashes = function (s) {
|
|
||||||
return s.replace(/\/+/g, '/');
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns all needed keys for a realtime channel
|
* Returns all needed keys for a realtime channel
|
||||||
* - no argument: use the URL hash or create one if it doesn't exist
|
* - no argument: use the URL hash or create one if it doesn't exist
|
||||||
* - secretHash provided: use secretHash to find the keys
|
* - secretHash provided: use secretHash to find the keys
|
||||||
*/
|
*/
|
||||||
Hash.getSecrets = function (secretHash) {
|
Hash.getSecrets = function (type, secretHash) {
|
||||||
var secret = {};
|
var secret = {};
|
||||||
var generate = function () {
|
var generate = function () {
|
||||||
secret.keys = Crypto.createEditCryptor();
|
secret.keys = Crypto.createEditCryptor();
|
||||||
@ -85,50 +141,53 @@ define([
|
|||||||
generate();
|
generate();
|
||||||
return secret;
|
return secret;
|
||||||
} else {
|
} else {
|
||||||
var hash = secretHash || window.location.hash.slice(1);
|
var parsed;
|
||||||
|
var hash;
|
||||||
|
if (secretHash) {
|
||||||
|
if (!type) { throw new Error("getSecrets with a hash requires a type parameter"); }
|
||||||
|
parsed = parseTypeHash(type, secretHash);
|
||||||
|
hash = secretHash;
|
||||||
|
} else {
|
||||||
|
var pHref = parsePadUrl(window.location.href);
|
||||||
|
parsed = pHref.hashData;
|
||||||
|
hash = pHref.hash;
|
||||||
|
}
|
||||||
|
//var parsed = parsePadUrl(window.location.href);
|
||||||
|
//var hash = secretHash || window.location.hash.slice(1);
|
||||||
if (hash.length === 0) {
|
if (hash.length === 0) {
|
||||||
generate();
|
generate();
|
||||||
return secret;
|
return secret;
|
||||||
}
|
}
|
||||||
// old hash system : #{hexChanKey}{cryptKey}
|
// old hash system : #{hexChanKey}{cryptKey}
|
||||||
// new hash system : #/{hashVersion}/{b64ChanKey}/{cryptKey}
|
// new hash system : #/{hashVersion}/{b64ChanKey}/{cryptKey}
|
||||||
if (hash.slice(0,1) !== '/' && hash.length >= 56) {
|
if (parsed.version === 0) {
|
||||||
// Old hash
|
// Old hash
|
||||||
secret.channel = hash.slice(0, 32);
|
secret.channel = hash.slice(0, 32);
|
||||||
secret.key = hash.slice(32);
|
secret.key = hash.slice(32);
|
||||||
}
|
}
|
||||||
else {
|
else if (parsed.version === 1) {
|
||||||
// New hash
|
// New hash
|
||||||
var hashArray = fixDuplicateSlashes(hash).split('/');
|
if (parsed.type === "pad") {
|
||||||
if (hashArray.length < 4) {
|
secret.channel = base64ToHex(parsed.channel);
|
||||||
Hash.alert("Unable to parse the key");
|
if (parsed.mode === 'edit') {
|
||||||
throw new Error("Unable to parse the key");
|
secret.keys = Crypto.createEditCryptor(parsed.key);
|
||||||
}
|
secret.key = secret.keys.editKeyStr;
|
||||||
var version = hashArray[1];
|
|
||||||
if (version === "1") {
|
|
||||||
var mode = hashArray[2];
|
|
||||||
if (mode === 'edit') {
|
|
||||||
secret.channel = base64ToHex(hashArray[3]);
|
|
||||||
var keys = Crypto.createEditCryptor(hashArray[4].replace(/-/g, '/'));
|
|
||||||
secret.keys = keys;
|
|
||||||
secret.key = keys.editKeyStr;
|
|
||||||
if (secret.channel.length !== 32 || secret.key.length !== 24) {
|
if (secret.channel.length !== 32 || secret.key.length !== 24) {
|
||||||
Hash.alert("The channel key and/or the encryption key is invalid");
|
Hash.alert("The channel key and/or the encryption key is invalid");
|
||||||
throw new Error("The channel key and/or the encryption key is invalid");
|
throw new Error("The channel key and/or the encryption key is invalid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mode === 'view') {
|
else if (parsed.mode === 'view') {
|
||||||
secret.channel = base64ToHex(hashArray[3]);
|
secret.keys = Crypto.createViewCryptor(parsed.key);
|
||||||
secret.keys = Crypto.createViewCryptor(hashArray[4].replace(/-/g, '/'));
|
|
||||||
if (secret.channel.length !== 32) {
|
if (secret.channel.length !== 32) {
|
||||||
Hash.alert("The channel key is invalid");
|
Hash.alert("The channel key is invalid");
|
||||||
throw new Error("The channel key is invalid");
|
throw new Error("The channel key is invalid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (version === "2") {
|
} else if (parsed.type === "file") {
|
||||||
// version 2 hashes are to be used for encrypted blobs
|
// version 2 hashes are to be used for encrypted blobs
|
||||||
secret.channel = hashArray[2].replace(/-/g, '/');
|
secret.channel = parsed.channel;
|
||||||
secret.keys = { fileKeyStr: hashArray[3].replace(/-/g, '/') };
|
secret.keys = { fileKeyStr: parsed.key };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,42 +224,6 @@ define([
|
|||||||
return '/1/edit/' + [channelId, key].join('/') + '/';
|
return '/1/edit/' + [channelId, key].join('/') + '/';
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Version 0
|
|
||||||
/pad/#67b8385b07352be53e40746d2be6ccd7XAYSuJYYqa9NfmInyHci7LNy
|
|
||||||
Version 1
|
|
||||||
/code/#/1/edit/3Ujt4F2Sjnjbis6CoYWpoQ/usn4+9CqVja8Q7RZOGTfRgqI
|
|
||||||
Version 2
|
|
||||||
/file/#/2/<fileId>/<cryptKey>/<contentType>
|
|
||||||
/file/#/2/K6xWU-LT9BJHCQcDCT-DcQ/ajExFODrFH4lVBwxxsrOKw/image-png
|
|
||||||
*/
|
|
||||||
var parseHash = Hash.parseHash = function (hash) {
|
|
||||||
var parsed = {};
|
|
||||||
if (hash.slice(0,1) !== '/' && hash.length >= 56) {
|
|
||||||
// Old hash
|
|
||||||
parsed.channel = hash.slice(0, 32);
|
|
||||||
parsed.key = hash.slice(32);
|
|
||||||
parsed.version = 0;
|
|
||||||
return parsed;
|
|
||||||
}
|
|
||||||
var hashArr = fixDuplicateSlashes(hash).split('/');
|
|
||||||
if (hashArr[1] && hashArr[1] === '1') {
|
|
||||||
parsed.version = 1;
|
|
||||||
parsed.mode = hashArr[2];
|
|
||||||
parsed.channel = hashArr[3];
|
|
||||||
parsed.key = hashArr[4];
|
|
||||||
parsed.present = typeof(hashArr[5]) === "string" && hashArr[5] === 'present';
|
|
||||||
return parsed;
|
|
||||||
}
|
|
||||||
if (hashArr[1] && hashArr[1] === '2') {
|
|
||||||
parsed.version = 2;
|
|
||||||
parsed.channel = hashArr[2].replace(/-/g, '/');
|
|
||||||
parsed.key = hashArr[3].replace(/-/g, '/');
|
|
||||||
return parsed;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
// STORAGE
|
// STORAGE
|
||||||
Hash.findWeaker = function (href, recents) {
|
Hash.findWeaker = function (href, recents) {
|
||||||
var rHref = href || getRelativeHref(window.location.href);
|
var rHref = href || getRelativeHref(window.location.href);
|
||||||
@ -211,9 +234,13 @@ Version 2
|
|||||||
var p = parsePadUrl(pad.href);
|
var p = parsePadUrl(pad.href);
|
||||||
if (p.type !== parsed.type) { return; } // Not the same type
|
if (p.type !== parsed.type) { return; } // Not the same type
|
||||||
if (p.hash === parsed.hash) { return; } // Same hash, not stronger
|
if (p.hash === parsed.hash) { return; } // Same hash, not stronger
|
||||||
var pHash = parseHash(p.hash);
|
var pHash = p.hashData;
|
||||||
var parsedHash = parseHash(parsed.hash);
|
var parsedHash = parsed.hashData;
|
||||||
if (!parsedHash || !pHash) { return; }
|
if (!parsedHash || !pHash) { return; }
|
||||||
|
|
||||||
|
// We don't have stronger/weaker versions of files or users
|
||||||
|
if (pHash.type !== 'pad' && parsedHash.type !== 'pad') { return; }
|
||||||
|
|
||||||
if (pHash.version !== parsedHash.version) { return; }
|
if (pHash.version !== parsedHash.version) { return; }
|
||||||
if (pHash.channel !== parsedHash.channel) { return; }
|
if (pHash.channel !== parsedHash.channel) { return; }
|
||||||
if (pHash.mode === 'view' && parsedHash.mode === 'edit') {
|
if (pHash.mode === 'view' && parsedHash.mode === 'edit') {
|
||||||
@ -233,9 +260,13 @@ Version 2
|
|||||||
var p = parsePadUrl(pad.href);
|
var p = parsePadUrl(pad.href);
|
||||||
if (p.type !== parsed.type) { return; } // Not the same type
|
if (p.type !== parsed.type) { return; } // Not the same type
|
||||||
if (p.hash === parsed.hash) { return; } // Same hash, not stronger
|
if (p.hash === parsed.hash) { return; } // Same hash, not stronger
|
||||||
var pHash = parseHash(p.hash);
|
var pHash = p.hashData;
|
||||||
var parsedHash = parseHash(parsed.hash);
|
var parsedHash = parsed.hashData;
|
||||||
if (!parsedHash || !pHash) { return; }
|
if (!parsedHash || !pHash) { return; }
|
||||||
|
|
||||||
|
// We don't have stronger/weaker versions of files or users
|
||||||
|
if (pHash.type !== 'pad' && parsedHash.type !== 'pad') { return; }
|
||||||
|
|
||||||
if (pHash.version !== parsedHash.version) { return; }
|
if (pHash.version !== parsedHash.version) { return; }
|
||||||
if (pHash.channel !== parsedHash.channel) { return; }
|
if (pHash.channel !== parsedHash.channel) { return; }
|
||||||
if (pHash.mode === 'edit' && parsedHash.mode === 'view') {
|
if (pHash.mode === 'edit' && parsedHash.mode === 'view') {
|
||||||
@ -254,8 +285,7 @@ Version 2
|
|||||||
var parsed = Hash.parsePadUrl(href);
|
var parsed = Hash.parsePadUrl(href);
|
||||||
if (!parsed || !parsed.hash) { return; }
|
if (!parsed || !parsed.hash) { return; }
|
||||||
|
|
||||||
parsed = Hash.parseHash(parsed.hash);
|
parsed = parsed.hashData;
|
||||||
|
|
||||||
if (parsed.version === 0) {
|
if (parsed.version === 0) {
|
||||||
return parsed.channel;
|
return parsed.channel;
|
||||||
} else if (parsed.version !== 1 && parsed.version !== 2) {
|
} else if (parsed.version !== 1 && parsed.version !== 2) {
|
||||||
|
|||||||
@ -35,8 +35,8 @@ define([
|
|||||||
};
|
};
|
||||||
var realtime = createRealtime();
|
var realtime = createRealtime();
|
||||||
|
|
||||||
var hash = config.href ? common.parsePadUrl(config.href).hash : undefined;
|
var parsed = config.href ? common.parsePadUrl(config.href) : {};
|
||||||
var secret = common.getSecrets(hash);
|
var secret = common.getSecrets(parsed.type, parsed.hash);
|
||||||
var crypto = Crypto.createEncryptor(secret.keys);
|
var crypto = Crypto.createEncryptor(secret.keys);
|
||||||
|
|
||||||
var to = window.setTimeout(function () {
|
var to = window.setTimeout(function () {
|
||||||
|
|||||||
@ -22,7 +22,8 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
var makeConfig = function (hash) {
|
var makeConfig = function (hash) {
|
||||||
var secret = Cryptpad.getSecrets(hash);
|
// We can't use cryptget with a file or a user so we can use 'pad' as hash type
|
||||||
|
var secret = Cryptpad.getSecrets('pad', hash);
|
||||||
if (!secret.keys) { secret.keys = secret.key; } // support old hashses
|
if (!secret.keys) { secret.keys = secret.key; } // support old hashses
|
||||||
var config = {
|
var config = {
|
||||||
websocketURL: Cryptpad.getWebsocketURL(),
|
websocketURL: Cryptpad.getWebsocketURL(),
|
||||||
|
|||||||
@ -75,10 +75,10 @@ define([
|
|||||||
|
|
||||||
// import hash utilities for export
|
// import hash utilities for export
|
||||||
var createRandomHash = common.createRandomHash = Hash.createRandomHash;
|
var createRandomHash = common.createRandomHash = Hash.createRandomHash;
|
||||||
|
common.parseTypeHash = Hash.parseTypeHash;
|
||||||
var parsePadUrl = common.parsePadUrl = Hash.parsePadUrl;
|
var parsePadUrl = common.parsePadUrl = Hash.parsePadUrl;
|
||||||
var isNotStrongestStored = common.isNotStrongestStored = Hash.isNotStrongestStored;
|
var isNotStrongestStored = common.isNotStrongestStored = Hash.isNotStrongestStored;
|
||||||
var hrefToHexChannelId = common.hrefToHexChannelId = Hash.hrefToHexChannelId;
|
var hrefToHexChannelId = common.hrefToHexChannelId = Hash.hrefToHexChannelId;
|
||||||
var parseHash = common.parseHash = Hash.parseHash;
|
|
||||||
var getRelativeHref = common.getRelativeHref = Hash.getRelativeHref;
|
var getRelativeHref = common.getRelativeHref = Hash.getRelativeHref;
|
||||||
common.getBlobPathFromHex = Hash.getBlobPathFromHex;
|
common.getBlobPathFromHex = Hash.getBlobPathFromHex;
|
||||||
|
|
||||||
@ -286,27 +286,22 @@ define([
|
|||||||
if (!pad.title) {
|
if (!pad.title) {
|
||||||
pad.title = common.getDefaultname(parsed);
|
pad.title = common.getDefaultname(parsed);
|
||||||
}
|
}
|
||||||
return parsed.hash;
|
return parsed.hashData;
|
||||||
};
|
};
|
||||||
// Migrate from legacy store (localStorage)
|
// Migrate from legacy store (localStorage)
|
||||||
var migrateRecentPads = common.migrateRecentPads = function (pads) {
|
var migrateRecentPads = common.migrateRecentPads = function (pads) {
|
||||||
return pads.map(function (pad) {
|
return pads.map(function (pad) {
|
||||||
var hash;
|
var parsedHash;
|
||||||
if (Array.isArray(pad)) { // TODO DEPRECATE_F
|
if (Array.isArray(pad)) { // TODO DEPRECATE_F
|
||||||
var href = pad[0];
|
|
||||||
href.replace(/\#(.*)$/, function (a, h) {
|
|
||||||
hash = h;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
href: pad[0],
|
href: pad[0],
|
||||||
atime: pad[1],
|
atime: pad[1],
|
||||||
title: pad[2] || hash && hash.slice(0,8),
|
title: pad[2] || '',
|
||||||
ctime: pad[1],
|
ctime: pad[1],
|
||||||
};
|
};
|
||||||
} else if (pad && typeof(pad) === 'object') {
|
} else if (pad && typeof(pad) === 'object') {
|
||||||
hash = checkObjectData(pad);
|
parsedHash = checkObjectData(pad);
|
||||||
if (!hash || !common.parseHash(hash)) { return; }
|
if (!parsedHash || !parsedHash.type) { return; }
|
||||||
return pad;
|
return pad;
|
||||||
} else {
|
} else {
|
||||||
console.error("[Cryptpad.migrateRecentPads] pad had unexpected value");
|
console.error("[Cryptpad.migrateRecentPads] pad had unexpected value");
|
||||||
@ -319,8 +314,8 @@ define([
|
|||||||
var checkRecentPads = common.checkRecentPads = function (pads) {
|
var checkRecentPads = common.checkRecentPads = function (pads) {
|
||||||
pads.forEach(function (pad, i) {
|
pads.forEach(function (pad, i) {
|
||||||
if (pad && typeof(pad) === 'object') {
|
if (pad && typeof(pad) === 'object') {
|
||||||
var hash = checkObjectData(pad);
|
var parsedHash = checkObjectData(pad);
|
||||||
if (!hash || !common.parseHash(hash)) {
|
if (!parsedHash || !parsedHash.type) {
|
||||||
console.error("[Cryptpad.checkRecentPads] pad had unexpected value", pad);
|
console.error("[Cryptpad.checkRecentPads] pad had unexpected value", pad);
|
||||||
getStore().removeData(i);
|
getStore().removeData(i);
|
||||||
return;
|
return;
|
||||||
@ -538,6 +533,7 @@ define([
|
|||||||
common.setPadTitle = function (name, cb) {
|
common.setPadTitle = function (name, cb) {
|
||||||
var href = window.location.href;
|
var href = window.location.href;
|
||||||
var parsed = parsePadUrl(href);
|
var parsed = parsePadUrl(href);
|
||||||
|
if (!parsed.hash) { return; }
|
||||||
href = getRelativeHref(href);
|
href = getRelativeHref(href);
|
||||||
// getRecentPads return the array from the drive, not a copy
|
// getRecentPads return the array from the drive, not a copy
|
||||||
// We don't have to call "set..." at the end, everything is stored with listmap
|
// We don't have to call "set..." at the end, everything is stored with listmap
|
||||||
@ -558,8 +554,8 @@ define([
|
|||||||
|
|
||||||
// Version 1 : we have up to 4 differents hash for 1 pad, keep the strongest :
|
// Version 1 : we have up to 4 differents hash for 1 pad, keep the strongest :
|
||||||
// Edit > Edit (present) > View > View (present)
|
// Edit > Edit (present) > View > View (present)
|
||||||
var pHash = parseHash(p.hash);
|
var pHash = p.hashData;
|
||||||
var parsedHash = parseHash(parsed.hash);
|
var parsedHash = parsed.hashData;
|
||||||
|
|
||||||
if (!pHash) { return; } // We may have a corrupted pad in our storage, abort here in that case
|
if (!pHash) { return; } // We may have a corrupted pad in our storage, abort here in that case
|
||||||
|
|
||||||
@ -661,7 +657,8 @@ define([
|
|||||||
var userHash = localStorage && localStorage.User_hash;
|
var userHash = localStorage && localStorage.User_hash;
|
||||||
if (!userHash) { return null; }
|
if (!userHash) { return null; }
|
||||||
|
|
||||||
var userChannel = common.parseHash(userHash).channel;
|
var userParsedHash = common.parseTypeHash('drive', userHash);
|
||||||
|
var userChannel = userParsedHash && userParsedHash.channel;
|
||||||
if (!userChannel) { return null; }
|
if (!userChannel) { return null; }
|
||||||
|
|
||||||
var list = fo.getFiles([fo.FILES_DATA]).map(hrefToHexChannelId)
|
var list = fo.getFiles([fo.FILES_DATA]).map(hrefToHexChannelId)
|
||||||
@ -746,13 +743,13 @@ define([
|
|||||||
|
|
||||||
common.updatePinLimit = function (cb) {
|
common.updatePinLimit = function (cb) {
|
||||||
if (!pinsReady()) { return void cb('[RPC_NOT_READY]'); }
|
if (!pinsReady()) { return void cb('[RPC_NOT_READY]'); }
|
||||||
rpc.getFileListSize(cb);
|
rpc.updatePinLimits(cb);
|
||||||
};
|
};
|
||||||
|
|
||||||
common.getPinLimit = function (cb) {
|
common.getPinLimit = function (cb) {
|
||||||
if (!pinsReady()) { return void cb('[RPC_NOT_READY]'); }
|
if (!pinsReady()) { return void cb('[RPC_NOT_READY]'); }
|
||||||
rpc.getFileListSize(cb);
|
cb(void 0, typeof(AppConfig.pinLimit) === 'number'? AppConfig.pinLimit: 1000);
|
||||||
//cb(void 0, typeof(AppConfig.pinLimit) === 'number'? AppConfig.pinLimit: 1000);
|
//rpc.getLimit(cb); TODO
|
||||||
};
|
};
|
||||||
|
|
||||||
common.isOverPinLimit = function (cb) {
|
common.isOverPinLimit = function (cb) {
|
||||||
@ -861,7 +858,8 @@ define([
|
|||||||
if (callback) {
|
if (callback) {
|
||||||
button.click(function() {
|
button.click(function() {
|
||||||
var href = window.location.href;
|
var href = window.location.href;
|
||||||
common.confirm(Messages.forgetPrompt, function (yes) {
|
var msg = isLoggedIn() ? Messages.forgetPrompt : Messages.fm_removePermanentlyDialog;
|
||||||
|
common.confirm(msg, function (yes) {
|
||||||
if (!yes) { return; }
|
if (!yes) { return; }
|
||||||
common.forgetPad(href, function (err) {
|
common.forgetPad(href, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -880,7 +878,8 @@ define([
|
|||||||
} else {
|
} else {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
common.alert(Messages.movedToTrash, undefined, true);
|
var cMsg = isLoggedIn() ? Messages.movedToTrash : Messages.deleted;
|
||||||
|
common.alert(cMsg, undefined, true);
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1280,20 +1279,21 @@ define([
|
|||||||
UI.Alertify.reset();
|
UI.Alertify.reset();
|
||||||
|
|
||||||
// Load the new pad when the hash has changed
|
// Load the new pad when the hash has changed
|
||||||
var oldHash = document.location.hash.slice(1);
|
var oldHref = document.location.href;
|
||||||
window.onhashchange = function () {
|
window.onhashchange = function () {
|
||||||
var newHash = document.location.hash.slice(1);
|
var newHref = document.location.href;
|
||||||
var parsedOld = parseHash(oldHash);
|
var parsedOld = parsePadUrl(oldHref).hashData;
|
||||||
var parsedNew = parseHash(newHash);
|
var parsedNew = parsePadUrl(newHref).hashData;
|
||||||
if (parsedOld && parsedNew && (
|
if (parsedOld && parsedNew && (
|
||||||
parsedOld.channel !== parsedNew.channel
|
parsedOld.type !== parsedNew.type
|
||||||
|
|| parsedOld.channel !== parsedNew.channel
|
||||||
|| parsedOld.mode !== parsedNew.mode
|
|| parsedOld.mode !== parsedNew.mode
|
||||||
|| parsedOld.key !== parsedNew.key)) {
|
|| parsedOld.key !== parsedNew.key)) {
|
||||||
document.location.reload();
|
document.location.reload();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (parsedNew) {
|
if (parsedNew) {
|
||||||
oldHash = newHash;
|
oldHref = newHref;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -222,7 +222,7 @@ define([
|
|||||||
if (!hash) {
|
if (!hash) {
|
||||||
throw new Error('[Store.init] Unable to find or create a drive hash. Aborting...');
|
throw new Error('[Store.init] Unable to find or create a drive hash. Aborting...');
|
||||||
}
|
}
|
||||||
var secret = Cryptpad.getSecrets(hash);
|
var secret = Cryptpad.getSecrets('drive', hash);
|
||||||
var listmapConfig = {
|
var listmapConfig = {
|
||||||
data: {},
|
data: {},
|
||||||
websocketURL: Cryptpad.getWebsocketURL(),
|
websocketURL: Cryptpad.getWebsocketURL(),
|
||||||
|
|||||||
@ -61,9 +61,7 @@ define([
|
|||||||
if (!isFile(element)) { return false; }
|
if (!isFile(element)) { return false; }
|
||||||
var parsed = Cryptpad.parsePadUrl(element);
|
var parsed = Cryptpad.parsePadUrl(element);
|
||||||
if (!parsed) { return false; }
|
if (!parsed) { return false; }
|
||||||
var hash = parsed.hash;
|
var pHash = parsed.hashData;
|
||||||
var pHash = Cryptpad.parseHash(hash);
|
|
||||||
if (pHash && !pHash.mode) { return; }
|
|
||||||
return pHash && pHash.mode === 'view';
|
return pHash && pHash.mode === 'view';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -541,6 +539,7 @@ define([
|
|||||||
|
|
||||||
// ADD
|
// ADD
|
||||||
var add = exp.add = function (data, path) {
|
var add = exp.add = function (data, path) {
|
||||||
|
if (!Cryptpad.isLoggedIn()) { return; }
|
||||||
if (!data || typeof(data) !== "object") { return; }
|
if (!data || typeof(data) !== "object") { return; }
|
||||||
var href = data.href;
|
var href = data.href;
|
||||||
var name = data.title;
|
var name = data.title;
|
||||||
@ -598,6 +597,18 @@ define([
|
|||||||
|
|
||||||
// FORGET (move with href not path)
|
// FORGET (move with href not path)
|
||||||
exp.forget = function (href) {
|
exp.forget = function (href) {
|
||||||
|
if (!Cryptpad.isLoggedIn()) {
|
||||||
|
// delete permanently
|
||||||
|
var data = getFileData(href);
|
||||||
|
if (data) {
|
||||||
|
var i = find([FILES_DATA]).indexOf(data);
|
||||||
|
if (i !== -1) {
|
||||||
|
exp.removePadAttribute(href);
|
||||||
|
spliceFileData(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
var paths = findFile(href);
|
var paths = findFile(href);
|
||||||
move(paths, [TRASH]);
|
move(paths, [TRASH]);
|
||||||
};
|
};
|
||||||
@ -605,7 +616,7 @@ define([
|
|||||||
// DELETE
|
// DELETE
|
||||||
// Permanently delete multiple files at once using a list of paths
|
// Permanently delete multiple files at once using a list of paths
|
||||||
// NOTE: We have to be careful when removing elements from arrays (trash root, unsorted or template)
|
// NOTE: We have to be careful when removing elements from arrays (trash root, unsorted or template)
|
||||||
var removePadAttribute = function (f) {
|
var removePadAttribute = exp.removePadAttribute = function (f) {
|
||||||
if (typeof(f) !== 'string') {
|
if (typeof(f) !== 'string') {
|
||||||
console.error("Can't find pad attribute for an undefined pad");
|
console.error("Can't find pad attribute for an undefined pad");
|
||||||
return;
|
return;
|
||||||
@ -621,7 +632,7 @@ define([
|
|||||||
};
|
};
|
||||||
var checkDeletedFiles = function () {
|
var checkDeletedFiles = function () {
|
||||||
// Nothing in FILES_DATA for workgroups
|
// Nothing in FILES_DATA for workgroups
|
||||||
if (workgroup) { return; }
|
if (workgroup || !Cryptpad.isLoggedIn()) { return; }
|
||||||
|
|
||||||
var filesList = getFiles([ROOT, 'hrefArray', TRASH]);
|
var filesList = getFiles([ROOT, 'hrefArray', TRASH]);
|
||||||
var toRemove = [];
|
var toRemove = [];
|
||||||
@ -656,6 +667,23 @@ define([
|
|||||||
var hrefPaths = paths.filter(function(x) { return isPathIn(x, ['hrefArray']); });
|
var hrefPaths = paths.filter(function(x) { return isPathIn(x, ['hrefArray']); });
|
||||||
var rootPaths = paths.filter(function(x) { return isPathIn(x, [ROOT]); });
|
var rootPaths = paths.filter(function(x) { return isPathIn(x, [ROOT]); });
|
||||||
var trashPaths = paths.filter(function(x) { return isPathIn(x, [TRASH]); });
|
var trashPaths = paths.filter(function(x) { return isPathIn(x, [TRASH]); });
|
||||||
|
var allFilesPaths = paths.filter(function(x) { return isPathIn(x, [FILES_DATA]); });
|
||||||
|
|
||||||
|
if (!Cryptpad.isLoggedIn()) {
|
||||||
|
var toSplice = [];
|
||||||
|
allFilesPaths.forEach(function (path) {
|
||||||
|
var el = find(path);
|
||||||
|
toSplice.push(el);
|
||||||
|
});
|
||||||
|
toSplice.forEach(function (el) {
|
||||||
|
var i = find([FILES_DATA]).indexOf(el);
|
||||||
|
if (i === -1) { return; }
|
||||||
|
removePadAttribute(el.href);
|
||||||
|
console.log(el.href);
|
||||||
|
spliceFileData(i);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var hrefs = [];
|
var hrefs = [];
|
||||||
hrefPaths.forEach(function (path) {
|
hrefPaths.forEach(function (path) {
|
||||||
@ -884,7 +912,7 @@ define([
|
|||||||
toClean.push(el);
|
toClean.push(el);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (rootFiles.indexOf(el.href) === -1) {
|
if (Cryptpad.isLoggedIn() && rootFiles.indexOf(el.href) === -1) {
|
||||||
debug("An element in filesData was not in ROOT, TEMPLATE or TRASH.", el);
|
debug("An element in filesData was not in ROOT, TEMPLATE or TRASH.", el);
|
||||||
var name = el.title || NEW_FILE_NAME;
|
var name = el.title || NEW_FILE_NAME;
|
||||||
var newName = getAvailableName(root, name);
|
var newName = getAvailableName(root, name);
|
||||||
|
|||||||
@ -154,6 +154,9 @@ span.fa-folder-open {
|
|||||||
min-width: 30px;
|
min-width: 30px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
#tree #allfilesTree {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
#tree #searchContainer {
|
#tree #searchContainer {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 5px 0;
|
padding: 5px 0;
|
||||||
|
|||||||
@ -194,6 +194,9 @@ span {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#allfilesTree {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
#searchContainer {
|
#searchContainer {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 5px 0;
|
padding: 5px 0;
|
||||||
|
|||||||
@ -205,7 +205,6 @@ define([
|
|||||||
var $trashTreeContextMenu = $iframe.find("#trashTreeContextMenu");
|
var $trashTreeContextMenu = $iframe.find("#trashTreeContextMenu");
|
||||||
var $trashContextMenu = $iframe.find("#trashContextMenu");
|
var $trashContextMenu = $iframe.find("#trashContextMenu");
|
||||||
|
|
||||||
|
|
||||||
// TOOLBAR
|
// TOOLBAR
|
||||||
|
|
||||||
/* add a "change username" button */
|
/* add a "change username" button */
|
||||||
@ -227,10 +226,14 @@ define([
|
|||||||
if (AppConfig.enableTemplates) { displayedCategories.push(TEMPLATE); }
|
if (AppConfig.enableTemplates) { displayedCategories.push(TEMPLATE); }
|
||||||
if (isWorkgroup()) { displayedCategories = [ROOT, TRASH, SEARCH]; }
|
if (isWorkgroup()) { displayedCategories = [ROOT, TRASH, SEARCH]; }
|
||||||
|
|
||||||
|
if (!Cryptpad.isLoggedIn()) {
|
||||||
|
displayedCategories = [FILES_DATA];
|
||||||
|
currentPath = [FILES_DATA];
|
||||||
|
}
|
||||||
|
|
||||||
if (!APP.readOnly) {
|
if (!APP.readOnly) {
|
||||||
setEditable(true);
|
setEditable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
var appStatus = {
|
var appStatus = {
|
||||||
isReady: true,
|
isReady: true,
|
||||||
_onReady: [],
|
_onReady: [],
|
||||||
@ -1103,7 +1106,7 @@ define([
|
|||||||
var type = Messages.type[hrefData.type] || hrefData.type;
|
var type = Messages.type[hrefData.type] || hrefData.type;
|
||||||
var $title = $('<span>', {'class': 'title listElement', title: data.title}).text(data.title);
|
var $title = $('<span>', {'class': 'title listElement', title: data.title}).text(data.title);
|
||||||
var $type = $('<span>', {'class': 'type listElement', title: type}).text(type);
|
var $type = $('<span>', {'class': 'type listElement', title: type}).text(type);
|
||||||
if (hrefData.hash && Cryptpad.parseHash(hrefData.hash) && Cryptpad.parseHash(hrefData.hash).mode === 'view') {
|
if (hrefData.hashData && hrefData.hashData.mode === 'view') {
|
||||||
$type.append(' (' + Messages.readonly+ ')');
|
$type.append(' (' + Messages.readonly+ ')');
|
||||||
}
|
}
|
||||||
var $adate = $('<span>', {'class': 'atime listElement', title: getDate(data.atime)}).text(getDate(data.atime));
|
var $adate = $('<span>', {'class': 'atime listElement', title: getDate(data.atime)}).text(getDate(data.atime));
|
||||||
@ -1811,6 +1814,7 @@ define([
|
|||||||
|
|
||||||
module.resetTree();
|
module.resetTree();
|
||||||
|
|
||||||
|
if (displayedCategories.indexOf(SEARCH) !== -1) {
|
||||||
// in history mode we want to focus the version number input
|
// in history mode we want to focus the version number input
|
||||||
if (!history.isHistoryMode && !APP.mobile()) {
|
if (!history.isHistoryMode && !APP.mobile()) {
|
||||||
var st = $tree.scrollTop() || 0;
|
var st = $tree.scrollTop() || 0;
|
||||||
@ -1819,6 +1823,7 @@ define([
|
|||||||
}
|
}
|
||||||
$tree.find('#searchInput')[0].selectionStart = getSearchCursor();
|
$tree.find('#searchInput')[0].selectionStart = getSearchCursor();
|
||||||
$tree.find('#searchInput')[0].selectionEnd = getSearchCursor();
|
$tree.find('#searchInput')[0].selectionEnd = getSearchCursor();
|
||||||
|
}
|
||||||
|
|
||||||
if (!isWorkgroup()) {
|
if (!isWorkgroup()) {
|
||||||
setLastOpenedFolder(path);
|
setLastOpenedFolder(path);
|
||||||
@ -2155,9 +2160,9 @@ define([
|
|||||||
var getReadOnlyUrl = APP.getRO = function (href) {
|
var getReadOnlyUrl = APP.getRO = function (href) {
|
||||||
if (!filesOp.isFile(href)) { return; }
|
if (!filesOp.isFile(href)) { return; }
|
||||||
var i = href.indexOf('#') + 1;
|
var i = href.indexOf('#') + 1;
|
||||||
var hash = href.slice(i);
|
var parsed = Cryptpad.parsePadUrl(href);
|
||||||
var base = href.slice(0, i);
|
var base = href.slice(0, i);
|
||||||
var hrefsecret = Cryptpad.getSecrets(hash);
|
var hrefsecret = Cryptpad.getSecrets(parsed.type, parsed.hash);
|
||||||
if (!hrefsecret.keys) { return; }
|
if (!hrefsecret.keys) { return; }
|
||||||
var viewHash = Cryptpad.getViewHashFromKeys(hrefsecret.channel, hrefsecret.keys);
|
var viewHash = Cryptpad.getViewHashFromKeys(hrefsecret.channel, hrefsecret.keys);
|
||||||
return base + viewHash;
|
return base + viewHash;
|
||||||
@ -2310,6 +2315,19 @@ define([
|
|||||||
else if ($(this).hasClass('delete')) {
|
else if ($(this).hasClass('delete')) {
|
||||||
var pathsList = [];
|
var pathsList = [];
|
||||||
paths.forEach(function (p) { pathsList.push(p.path); });
|
paths.forEach(function (p) { pathsList.push(p.path); });
|
||||||
|
if (!Cryptpad.isLoggedIn()) {
|
||||||
|
console.log(paths);
|
||||||
|
var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [paths.length]);
|
||||||
|
if (paths.length === 1) {
|
||||||
|
msg = Messages.fm_removePermanentlyDialog;
|
||||||
|
}
|
||||||
|
Cryptpad.confirm(msg, function(res) {
|
||||||
|
$(ifrw).focus();
|
||||||
|
if (!res) { return; }
|
||||||
|
filesOp.delete(pathsList, refresh);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
moveElements(pathsList, [TRASH], false, refresh);
|
moveElements(pathsList, [TRASH], false, refresh);
|
||||||
}
|
}
|
||||||
else if ($(this).hasClass("properties")) {
|
else if ($(this).hasClass("properties")) {
|
||||||
@ -2432,7 +2450,9 @@ define([
|
|||||||
$appContainer.on('keydown', function (e) {
|
$appContainer.on('keydown', function (e) {
|
||||||
// "Del"
|
// "Del"
|
||||||
if (e.which === 46) {
|
if (e.which === 46) {
|
||||||
if (filesOp.isPathIn(currentPath, [FILES_DATA])) { return; } // We can't remove elements directly from filesData
|
if (filesOp.isPathIn(currentPath, [FILES_DATA]) && Cryptpad.isLoggedIn()) {
|
||||||
|
return; // We can't remove elements directly from filesData
|
||||||
|
}
|
||||||
var $selected = $iframe.find('.selected');
|
var $selected = $iframe.find('.selected');
|
||||||
if (!$selected.length) { return; }
|
if (!$selected.length) { return; }
|
||||||
var paths = [];
|
var paths = [];
|
||||||
@ -2442,7 +2462,7 @@ define([
|
|||||||
paths.push($(elmt).data('path'));
|
paths.push($(elmt).data('path'));
|
||||||
});
|
});
|
||||||
// If we are in the trash or anon pad or if we are holding the "shift" key, delete permanently,
|
// If we are in the trash or anon pad or if we are holding the "shift" key, delete permanently,
|
||||||
if (isTrash || e.shiftKey) {
|
if (!Cryptpad.isLoggedIn() || isTrash || e.shiftKey) {
|
||||||
var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [paths.length]);
|
var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [paths.length]);
|
||||||
if (paths.length === 1) {
|
if (paths.length === 1) {
|
||||||
msg = Messages.fm_removePermanentlyDialog;
|
msg = Messages.fm_removePermanentlyDialog;
|
||||||
@ -2608,7 +2628,7 @@ define([
|
|||||||
}
|
}
|
||||||
|
|
||||||
var hash = window.location.hash.slice(1) || Cryptpad.getUserHash() || localStorage.FS_hash;
|
var hash = window.location.hash.slice(1) || Cryptpad.getUserHash() || localStorage.FS_hash;
|
||||||
var secret = Cryptpad.getSecrets(hash);
|
var secret = Cryptpad.getSecrets('drive', hash);
|
||||||
var readOnly = APP.readOnly = secret.keys && !secret.keys.editKeyStr;
|
var readOnly = APP.readOnly = secret.keys && !secret.keys.editKeyStr;
|
||||||
|
|
||||||
var listmapConfig = module.config = {
|
var listmapConfig = module.config = {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user