Merge branch 'password' into staging
This commit is contained in:
commit
10ce95087a
@ -81,6 +81,38 @@ define([], function () {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
#cp-loading-password-prompt {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
#cp-loading-password-prompt .cp-password-error {
|
||||||
|
color: white;
|
||||||
|
background: #9e0000;
|
||||||
|
padding: 5px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
#cp-loading-password-prompt .cp-password-info {
|
||||||
|
text-align: left;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
#cp-loading-password-prompt .cp-password-form {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
#cp-loading-password-prompt .cp-password-form * {
|
||||||
|
background-color: #4591c4;
|
||||||
|
color: white;
|
||||||
|
border: 1px solid #4591c4;
|
||||||
|
}
|
||||||
|
#cp-loading-password-prompt .cp-password-form input {
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 15px;
|
||||||
|
padding: 0 5px;
|
||||||
|
min-width: 0;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
#cp-loading-password-prompt .cp-password-form button:hover {
|
||||||
|
background-color: #326599;
|
||||||
|
}
|
||||||
#cp-loading .cp-loading-spinner-container {
|
#cp-loading .cp-loading-spinner-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
|
|||||||
@ -145,9 +145,7 @@
|
|||||||
max-height: 100px;
|
max-height: 100px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.cp-creation-expire {
|
|
||||||
.cp-creation-expire-picker {
|
|
||||||
text-align: center;
|
|
||||||
input, select {
|
input, select {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
border: 1px solid @colortheme_form-border;
|
border: 1px solid @colortheme_form-border;
|
||||||
@ -155,6 +153,10 @@
|
|||||||
background-color: @colortheme_form-bg;
|
background-color: @colortheme_form-bg;
|
||||||
color: @colortheme_form-color;
|
color: @colortheme_form-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cp-creation-expire {
|
||||||
|
.cp-creation-expire-picker {
|
||||||
|
text-align: center;
|
||||||
input {
|
input {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
margin: 0 5px;
|
margin: 0 5px;
|
||||||
@ -172,6 +174,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.cp-creation-password {
|
||||||
|
.cp-creation-password-picker {
|
||||||
|
text-align: center;
|
||||||
|
input {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.active {
|
||||||
|
label {
|
||||||
|
flex: unset;
|
||||||
|
}
|
||||||
|
.cp-creation-slider {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.cp-creation-settings {
|
.cp-creation-settings {
|
||||||
button {
|
button {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -317,7 +335,7 @@
|
|||||||
width: 95%;
|
width: 95%;
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
}
|
}
|
||||||
.cp-creation-expire {
|
.cp-creation-expire, .cp-creation-password {
|
||||||
&.active {
|
&.active {
|
||||||
label {
|
label {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|||||||
@ -1081,6 +1081,7 @@ define(function () {
|
|||||||
out.creation_expireMonths = "Mois";
|
out.creation_expireMonths = "Mois";
|
||||||
out.creation_expire1 = "Un pad <b>illimité</b> ne sera pas supprimé du serveur à moins que son propriétaire ne le décide.";
|
out.creation_expire1 = "Un pad <b>illimité</b> ne sera pas supprimé du serveur à moins que son propriétaire ne le décide.";
|
||||||
out.creation_expire2 = "Un pad <b>à durée de vie</b> sera supprimé automatiquement du serveur et du CryptDrive des utilisateurs lorsque cette durée sera dépassée.";
|
out.creation_expire2 = "Un pad <b>à durée de vie</b> sera supprimé automatiquement du serveur et du CryptDrive des utilisateurs lorsque cette durée sera dépassée.";
|
||||||
|
out.creation_password = "Ajouter un mot de passe";
|
||||||
out.creation_noTemplate = "Pas de modèle";
|
out.creation_noTemplate = "Pas de modèle";
|
||||||
out.creation_newTemplate = "Nouveau modèle";
|
out.creation_newTemplate = "Nouveau modèle";
|
||||||
out.creation_create = "Créer";
|
out.creation_create = "Créer";
|
||||||
@ -1098,6 +1099,12 @@ define(function () {
|
|||||||
out.creation_newPadModalDescriptionAdvanced = "Cochez la case si vous souhaitez voir l'écran de création de pads (pour les pads avec propriétaire ou à durée de vie). Vous pouvez appuyer sur <b>Espace</b> pour changer sa valeur.";
|
out.creation_newPadModalDescriptionAdvanced = "Cochez la case si vous souhaitez voir l'écran de création de pads (pour les pads avec propriétaire ou à durée de vie). Vous pouvez appuyer sur <b>Espace</b> pour changer sa valeur.";
|
||||||
out.creation_newPadModalAdvanced = "Afficher l'écran de création de pads";
|
out.creation_newPadModalAdvanced = "Afficher l'écran de création de pads";
|
||||||
|
|
||||||
|
// Password prompt on the loadind screen
|
||||||
|
out.password_info = "Le pad auquel vous essayez d'accéder est protégé par un mot de passe. Entrez le bon mot de passe pour accéder à son contenu.";
|
||||||
|
out.password_error = "Pad introuvable !<br>Cette erreur peut provenir de deux facteurs. Soit le mot de passe est faux, soit le pad a été supprimé du serveur.";
|
||||||
|
out.password_placeholder = "Tapez le mot de passe ici...";
|
||||||
|
out.password_submit = "Valider";
|
||||||
|
|
||||||
// New share modal
|
// New share modal
|
||||||
out.share_linkCategory = "Partage";
|
out.share_linkCategory = "Partage";
|
||||||
out.share_linkAccess = "Droits d'accès";
|
out.share_linkAccess = "Droits d'accès";
|
||||||
|
|||||||
@ -1127,6 +1127,7 @@ define(function () {
|
|||||||
out.creation_expireMonths = "Month(s)";
|
out.creation_expireMonths = "Month(s)";
|
||||||
out.creation_expire1 = "An <b>unlimited</b> pad will not be removed from the server until its owner deletes it.";
|
out.creation_expire1 = "An <b>unlimited</b> pad will not be removed from the server until its owner deletes it.";
|
||||||
out.creation_expire2 = "An <b>expiring</b> pad has a set lifetime, after which it will be automatically removed from the server and other users' CryptDrives.";
|
out.creation_expire2 = "An <b>expiring</b> pad has a set lifetime, after which it will be automatically removed from the server and other users' CryptDrives.";
|
||||||
|
out.creation_password = "Add a password";
|
||||||
out.creation_noTemplate = "No template";
|
out.creation_noTemplate = "No template";
|
||||||
out.creation_newTemplate = "New template";
|
out.creation_newTemplate = "New template";
|
||||||
out.creation_create = "Create";
|
out.creation_create = "Create";
|
||||||
@ -1144,6 +1145,12 @@ define(function () {
|
|||||||
out.creation_newPadModalDescriptionAdvanced = "You can check the box (or press <b>Space</b> to change its value) if you want to display the pad creation screen (for owned pads, expiring pads, etc.).";
|
out.creation_newPadModalDescriptionAdvanced = "You can check the box (or press <b>Space</b> to change its value) if you want to display the pad creation screen (for owned pads, expiring pads, etc.).";
|
||||||
out.creation_newPadModalAdvanced = "Display the pad creation screen";
|
out.creation_newPadModalAdvanced = "Display the pad creation screen";
|
||||||
|
|
||||||
|
// Password prompt on the loadind screen
|
||||||
|
out.password_info = "The pad you're tyring to open is protected with a password. Enter the correct password to access its content.";
|
||||||
|
out.password_error = "Pad not found!<br>This error can be caused by two factors: either the password in invalid, or the pad has been deleted from the server.";
|
||||||
|
out.password_placeholder = "Type the password here...";
|
||||||
|
out.password_submit = "Submit";
|
||||||
|
|
||||||
// New share modal
|
// New share modal
|
||||||
out.share_linkCategory = "Share link";
|
out.share_linkCategory = "Share link";
|
||||||
out.share_linkAccess = "Access rights";
|
out.share_linkAccess = "Access rights";
|
||||||
|
|||||||
@ -223,6 +223,33 @@ define([
|
|||||||
hd.type === 'invite');
|
hd.type === 'invite');
|
||||||
}, "test support for invite urls");
|
}, "test support for invite urls");
|
||||||
|
|
||||||
|
// test support for V2
|
||||||
|
assert(function (cb) {
|
||||||
|
var parsed = Hash.parsePadUrl('/pad/#/2/pad/edit/oRE0oLCtEXusRDyin7GyLGcS/');
|
||||||
|
var secret = Hash.getSecrets('pad', '/2/pad/edit/oRE0oLCtEXusRDyin7GyLGcS/');
|
||||||
|
return cb(parsed.hashData.version === 2 &&
|
||||||
|
parsed.hashData.mode === "edit" &&
|
||||||
|
parsed.hashData.type === "pad" &&
|
||||||
|
parsed.hashData.key === "oRE0oLCtEXusRDyin7GyLGcS" &&
|
||||||
|
secret.channel === "d8d51b4aea863f3f050f47f8ad261753" &&
|
||||||
|
window.nacl.util.encodeBase64(secret.keys.cryptKey) === "0Ts1M6VVEozErV2Nx/LTv6Im5SCD7io2LlhasyyBPQo=" &&
|
||||||
|
secret.keys.validateKey === "f5A1FM9Gp55tnOcM75RyHD1oxBG9ZPh9WDA7qe2Fvps=" &&
|
||||||
|
!parsed.hashData.present);
|
||||||
|
}, "test support for version 2 hash failed to parse");
|
||||||
|
assert(function (cb) {
|
||||||
|
var parsed = Hash.parsePadUrl('/pad/#/2/pad/edit/HGu0tK2od-2BBnwAz2ZNS-t4/p/embed');
|
||||||
|
var secret = Hash.getSecrets('pad', '/2/pad/edit/HGu0tK2od-2BBnwAz2ZNS-t4/p/embed', 'pewpew');
|
||||||
|
return cb(parsed.hashData.version === 2 &&
|
||||||
|
parsed.hashData.mode === "edit" &&
|
||||||
|
parsed.hashData.type === "pad" &&
|
||||||
|
parsed.hashData.key === "HGu0tK2od-2BBnwAz2ZNS-t4" &&
|
||||||
|
secret.channel === "3fb6dc93807d903aff390b5f798c92c9" &&
|
||||||
|
window.nacl.util.encodeBase64(secret.keys.cryptKey) === "EeCkGJra8eJgVu7v4Yl2Hc3yUjrgpKpxr0Lcc3bSWVs=" &&
|
||||||
|
secret.keys.validateKey === "WGkBczJf2V6vQZfAScz8V1KY6jKdoxUCckrD+E75gGE=" &&
|
||||||
|
parsed.hashData.embed &&
|
||||||
|
parsed.hashData.password);
|
||||||
|
}, "test support for password in version 2 hash failed to parse");
|
||||||
|
|
||||||
assert(function (cb) {
|
assert(function (cb) {
|
||||||
var url = '/pad/?utm_campaign=new_comment&utm_medium=email&utm_source=thread_mailer#/1/edit/3Ujt4F2Sjnjbis6CoYWpoQ/usn4+9CqVja8Q7RZOGTfRgqI/';
|
var url = '/pad/?utm_campaign=new_comment&utm_medium=email&utm_source=thread_mailer#/1/edit/3Ujt4F2Sjnjbis6CoYWpoQ/usn4+9CqVja8Q7RZOGTfRgqI/';
|
||||||
var secret = Hash.parsePadUrl(url);
|
var secret = Hash.parsePadUrl(url);
|
||||||
|
|||||||
@ -334,6 +334,7 @@ define([
|
|||||||
//var cursor = editor.getCursor();
|
//var cursor = editor.getCursor();
|
||||||
//var cleanName = data.name.replace(/[\[\]]/g, '');
|
//var cleanName = data.name.replace(/[\[\]]/g, '');
|
||||||
//var text = '';
|
//var text = '';
|
||||||
|
// PASSWORD_FILES
|
||||||
var parsed = Hash.parsePadUrl(data.url);
|
var parsed = Hash.parsePadUrl(data.url);
|
||||||
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
||||||
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
||||||
|
|||||||
@ -19,7 +19,50 @@ define([
|
|||||||
.decodeUTF8(JSON.stringify(list))));
|
.decodeUTF8(JSON.stringify(list))));
|
||||||
};
|
};
|
||||||
|
|
||||||
var getEditHashFromKeys = Hash.getEditHashFromKeys = function (chanKey, keys) {
|
var getEditHashFromKeys = Hash.getEditHashFromKeys = function (secret) {
|
||||||
|
var version = secret.version;
|
||||||
|
var data = secret.keys;
|
||||||
|
if (version === 0) {
|
||||||
|
return secret.channel + secret.key;
|
||||||
|
}
|
||||||
|
if (version === 1) {
|
||||||
|
if (!data.editKeyStr) { return; }
|
||||||
|
return '/1/edit/' + hexToBase64(secret.channel) +
|
||||||
|
'/' + Crypto.b64RemoveSlashes(data.editKeyStr) + '/';
|
||||||
|
}
|
||||||
|
if (version === 2) {
|
||||||
|
if (!data.editKeyStr) { return; }
|
||||||
|
var pass = secret.password ? 'p/' : '';
|
||||||
|
return '/2/' + secret.type + '/edit/' + Crypto.b64RemoveSlashes(data.editKeyStr) + '/' + pass;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var getViewHashFromKeys = Hash.getViewHashFromKeys = function (secret) {
|
||||||
|
var version = secret.version;
|
||||||
|
var data = secret.keys;
|
||||||
|
if (version === 0) { return; }
|
||||||
|
if (version === 1) {
|
||||||
|
if (!data.viewKeyStr) { return; }
|
||||||
|
return '/1/view/' + hexToBase64(secret.channel) +
|
||||||
|
'/'+Crypto.b64RemoveSlashes(data.viewKeyStr)+'/';
|
||||||
|
}
|
||||||
|
if (version === 2) {
|
||||||
|
if (!data.viewKeyStr) { return; }
|
||||||
|
var pass = secret.password ? 'p/' : '';
|
||||||
|
return '/2/' + secret.type + '/view/' + Crypto.b64RemoveSlashes(data.viewKeyStr) + '/' + pass;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var getFileHashFromKeys = Hash.getFileHashFromKeys = function (secret) {
|
||||||
|
var version = secret.version;
|
||||||
|
var data = secret.keys;
|
||||||
|
if (version === 0) { return; }
|
||||||
|
if (version === 1) {
|
||||||
|
return '/1/' + hexToBase64(secret.channel) + '/' +
|
||||||
|
Crypto.b64RemoveSlashes(data.fileKeyStr) + '/';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// V1
|
||||||
|
/*var getEditHashFromKeys = Hash.getEditHashFromKeys = function (chanKey, keys) {
|
||||||
if (typeof keys === 'string') {
|
if (typeof keys === 'string') {
|
||||||
return chanKey + keys;
|
return chanKey + keys;
|
||||||
}
|
}
|
||||||
@ -34,7 +77,7 @@ define([
|
|||||||
};
|
};
|
||||||
var getFileHashFromKeys = Hash.getFileHashFromKeys = function (fileKey, cryptKey) {
|
var getFileHashFromKeys = Hash.getFileHashFromKeys = function (fileKey, cryptKey) {
|
||||||
return '/1/' + hexToBase64(fileKey) + '/' + Crypto.b64RemoveSlashes(cryptKey) + '/';
|
return '/1/' + hexToBase64(fileKey) + '/' + Crypto.b64RemoveSlashes(cryptKey) + '/';
|
||||||
};
|
};*/
|
||||||
Hash.getUserHrefFromKeys = function (origin, username, pubkey) {
|
Hash.getUserHrefFromKeys = function (origin, username, pubkey) {
|
||||||
return origin + '/user/#/1/' + username + '/' + pubkey.replace(/\//g, '-');
|
return origin + '/user/#/1/' + username + '/' + pubkey.replace(/\//g, '-');
|
||||||
};
|
};
|
||||||
@ -43,6 +86,24 @@ define([
|
|||||||
return s.replace(/\/+/g, '/');
|
return s.replace(/\/+/g, '/');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Hash.createChannelId = function () {
|
||||||
|
var id = uint8ArrayToHex(Crypto.Nacl.randomBytes(16));
|
||||||
|
if (id.length !== 32 || /[^a-f0-9]/.test(id)) {
|
||||||
|
throw new Error('channel ids must consist of 32 hex characters');
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
|
||||||
|
Hash.createRandomHash = function (type, password) {
|
||||||
|
var cryptor = Crypto.createEditCryptor2(void 0, void 0, password);
|
||||||
|
return getEditHashFromKeys({
|
||||||
|
password: Boolean(password),
|
||||||
|
version: 2,
|
||||||
|
type: type,
|
||||||
|
keys: { editKeyStr: cryptor.editKeyStr }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Version 0
|
Version 0
|
||||||
/pad/#67b8385b07352be53e40746d2be6ccd7XAYSuJYYqa9NfmInyHci7LNy
|
/pad/#67b8385b07352be53e40746d2be6ccd7XAYSuJYYqa9NfmInyHci7LNy
|
||||||
@ -56,25 +117,56 @@ Version 1
|
|||||||
var hashArr = fixDuplicateSlashes(hash).split('/');
|
var hashArr = fixDuplicateSlashes(hash).split('/');
|
||||||
if (['media', 'file', 'user', 'invite'].indexOf(type) === -1) {
|
if (['media', 'file', 'user', 'invite'].indexOf(type) === -1) {
|
||||||
parsed.type = 'pad';
|
parsed.type = 'pad';
|
||||||
if (hash.slice(0,1) !== '/' && hash.length >= 56) {
|
if (hash.slice(0,1) !== '/' && hash.length >= 56) { // Version 0
|
||||||
// Old hash
|
// Old hash
|
||||||
parsed.channel = hash.slice(0, 32);
|
parsed.channel = hash.slice(0, 32);
|
||||||
parsed.key = hash.slice(32, 56);
|
parsed.key = hash.slice(32, 56);
|
||||||
parsed.version = 0;
|
parsed.version = 0;
|
||||||
|
parsed.getHash = function () { return hash; };
|
||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
if (hashArr[1] && hashArr[1] === '1') {
|
var options;
|
||||||
|
if (hashArr[1] && hashArr[1] === '1') { // Version 1
|
||||||
parsed.version = 1;
|
parsed.version = 1;
|
||||||
parsed.mode = hashArr[2];
|
parsed.mode = hashArr[2];
|
||||||
parsed.channel = hashArr[3];
|
parsed.channel = hashArr[3];
|
||||||
parsed.key = hashArr[4].replace(/-/g, '/');
|
parsed.key = Crypto.b64AddSlashes(hashArr[4]);
|
||||||
var options = hashArr.slice(5);
|
|
||||||
|
options = hashArr.slice(5);
|
||||||
parsed.present = options.indexOf('present') !== -1;
|
parsed.present = options.indexOf('present') !== -1;
|
||||||
parsed.embed = options.indexOf('embed') !== -1;
|
parsed.embed = options.indexOf('embed') !== -1;
|
||||||
|
|
||||||
|
parsed.getHash = function (opts) {
|
||||||
|
var hash = hashArr.slice(0, 5).join('/') + '/';
|
||||||
|
if (opts.embed) { hash += 'embed/'; }
|
||||||
|
if (opts.present) { hash += 'present/'; }
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
if (hashArr[1] && hashArr[1] === '2') { // Version 2
|
||||||
|
parsed.version = 2;
|
||||||
|
parsed.app = hashArr[2];
|
||||||
|
parsed.mode = hashArr[3];
|
||||||
|
parsed.key = hashArr[4];
|
||||||
|
|
||||||
|
options = hashArr.slice(5);
|
||||||
|
parsed.password = options.indexOf('p') !== -1;
|
||||||
|
parsed.present = options.indexOf('present') !== -1;
|
||||||
|
parsed.embed = options.indexOf('embed') !== -1;
|
||||||
|
|
||||||
|
parsed.getHash = function (opts) {
|
||||||
|
var hash = hashArr.slice(0, 5).join('/') + '/';
|
||||||
|
if (parsed.password) { hash += 'p/'; }
|
||||||
|
if (opts.embed) { hash += 'embed/'; }
|
||||||
|
if (opts.present) { hash += 'present/'; }
|
||||||
|
return hash;
|
||||||
|
};
|
||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
parsed.getHash = function () { return hashArr.join('/'); };
|
||||||
if (['media', 'file'].indexOf(type) !== -1) {
|
if (['media', 'file'].indexOf(type) !== -1) {
|
||||||
parsed.type = 'file';
|
parsed.type = 'file';
|
||||||
if (hashArr[1] && hashArr[1] === '1') {
|
if (hashArr[1] && hashArr[1] === '1') {
|
||||||
@ -125,17 +217,9 @@ Version 1
|
|||||||
url += ret.type + '/';
|
url += ret.type + '/';
|
||||||
if (!ret.hashData) { return url; }
|
if (!ret.hashData) { return url; }
|
||||||
if (ret.hashData.type !== 'pad') { return url + '#' + ret.hash; }
|
if (ret.hashData.type !== 'pad') { return url + '#' + ret.hash; }
|
||||||
if (ret.hashData.version !== 1) { return url + '#' + ret.hash; }
|
if (ret.hashData.version === 0) { return url + '#' + ret.hash; }
|
||||||
url += '#/' + ret.hashData.version +
|
var hash = ret.hashData.getHash(options);
|
||||||
'/' + ret.hashData.mode +
|
url += '#' + hash;
|
||||||
'/' + ret.hashData.channel.replace(/\//g, '-') +
|
|
||||||
'/' + ret.hashData.key.replace(/\//g, '-') +'/';
|
|
||||||
if (options.embed) {
|
|
||||||
url += 'embed/';
|
|
||||||
}
|
|
||||||
if (options.present) {
|
|
||||||
url += 'present/';
|
|
||||||
}
|
|
||||||
return url;
|
return url;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -153,12 +237,13 @@ Version 1
|
|||||||
return '';
|
return '';
|
||||||
});
|
});
|
||||||
idx = href.indexOf('/#');
|
idx = href.indexOf('/#');
|
||||||
|
if (idx === -1) { return ret; }
|
||||||
ret.hash = href.slice(idx + 2);
|
ret.hash = href.slice(idx + 2);
|
||||||
ret.hashData = parseTypeHash(ret.type, ret.hash);
|
ret.hashData = parseTypeHash(ret.type, ret.hash);
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
var getRelativeHref = Hash.getRelativeHref = function (href) {
|
Hash.getRelativeHref = function (href) {
|
||||||
if (!href) { return; }
|
if (!href) { return; }
|
||||||
if (href.indexOf('#') === -1) { return; }
|
if (href.indexOf('#') === -1) { return; }
|
||||||
var parsed = parsePadUrl(href);
|
var parsed = parsePadUrl(href);
|
||||||
@ -170,11 +255,13 @@ Version 1
|
|||||||
* - 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 (type, secretHash) {
|
Hash.getSecrets = function (type, secretHash, password) {
|
||||||
var secret = {};
|
var secret = {};
|
||||||
var generate = function () {
|
var generate = function () {
|
||||||
secret.keys = Crypto.createEditCryptor();
|
secret.keys = Crypto.createEditCryptor2(void 0, void 0, password);
|
||||||
secret.key = Crypto.createEditCryptor().editKeyStr;
|
secret.channel = base64ToHex(secret.keys.chanId);
|
||||||
|
secret.version = 2;
|
||||||
|
secret.type = type;
|
||||||
};
|
};
|
||||||
if (!secretHash && !window.location.hash) { //!/#/.test(window.location.href)) {
|
if (!secretHash && !window.location.hash) { //!/#/.test(window.location.href)) {
|
||||||
generate();
|
generate();
|
||||||
@ -191,7 +278,6 @@ Version 1
|
|||||||
parsed = pHref.hashData;
|
parsed = pHref.hashData;
|
||||||
hash = pHref.hash;
|
hash = pHref.hash;
|
||||||
}
|
}
|
||||||
//var parsed = parsePadUrl(window.location.href);
|
|
||||||
//var hash = secretHash || window.location.hash.slice(1);
|
//var hash = secretHash || window.location.hash.slice(1);
|
||||||
if (hash.length === 0) {
|
if (hash.length === 0) {
|
||||||
generate();
|
generate();
|
||||||
@ -203,9 +289,10 @@ Version 1
|
|||||||
// Old hash
|
// Old hash
|
||||||
secret.channel = parsed.channel;
|
secret.channel = parsed.channel;
|
||||||
secret.key = parsed.key;
|
secret.key = parsed.key;
|
||||||
}
|
secret.version = 0;
|
||||||
else if (parsed.version === 1) {
|
} else if (parsed.version === 1) {
|
||||||
// New hash
|
// New hash
|
||||||
|
secret.version = 1;
|
||||||
if (parsed.type === "pad") {
|
if (parsed.type === "pad") {
|
||||||
secret.channel = base64ToHex(parsed.channel);
|
secret.channel = base64ToHex(parsed.channel);
|
||||||
if (parsed.mode === 'edit') {
|
if (parsed.mode === 'edit') {
|
||||||
@ -229,49 +316,63 @@ Version 1
|
|||||||
// version 2 hashes are to be used for encrypted blobs
|
// version 2 hashes are to be used for encrypted blobs
|
||||||
throw new Error("User hashes can't be opened (yet)");
|
throw new Error("User hashes can't be opened (yet)");
|
||||||
}
|
}
|
||||||
|
} else if (parsed.version === 2) {
|
||||||
|
// New hash
|
||||||
|
secret.version = 2;
|
||||||
|
secret.type = type;
|
||||||
|
secret.password = password;
|
||||||
|
if (parsed.type === "pad") {
|
||||||
|
if (parsed.mode === 'edit') {
|
||||||
|
secret.keys = Crypto.createEditCryptor2(parsed.key, void 0, password);
|
||||||
|
secret.channel = base64ToHex(secret.keys.chanId);
|
||||||
|
secret.key = secret.keys.editKeyStr;
|
||||||
|
if (secret.channel.length !== 32 || secret.key.length !== 24) {
|
||||||
|
throw new Error("The channel key and/or the encryption key is invalid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (parsed.mode === 'view') {
|
||||||
|
secret.keys = Crypto.createViewCryptor2(parsed.key, password);
|
||||||
|
secret.channel = base64ToHex(secret.keys.chanId);
|
||||||
|
if (secret.channel.length !== 32) {
|
||||||
|
throw new Error("The channel key is invalid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (parsed.type === "file") {
|
||||||
|
throw new Error("File hashes should be version 1");
|
||||||
|
} else if (parsed.type === "user") {
|
||||||
|
throw new Error("User hashes can't be opened (yet)");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return secret;
|
return secret;
|
||||||
};
|
};
|
||||||
|
|
||||||
Hash.getHashes = function (channel, secret) {
|
Hash.getHashes = function (secret) {
|
||||||
var hashes = {};
|
var hashes = {};
|
||||||
if (!secret.keys) {
|
secret = JSON.parse(JSON.stringify(secret));
|
||||||
|
|
||||||
|
if (!secret.keys && !secret.key) {
|
||||||
console.error('e');
|
console.error('e');
|
||||||
return hashes;
|
return hashes;
|
||||||
|
} else if (!secret.keys) {
|
||||||
|
secret.keys = {};
|
||||||
}
|
}
|
||||||
if (secret.keys.editKeyStr) {
|
|
||||||
hashes.editHash = getEditHashFromKeys(channel, secret.keys);
|
if (secret.keys.editKeyStr || (secret.version === 0 && secret.key)) {
|
||||||
|
hashes.editHash = getEditHashFromKeys(secret);
|
||||||
}
|
}
|
||||||
if (secret.keys.viewKeyStr) {
|
if (secret.keys.viewKeyStr) {
|
||||||
hashes.viewHash = getViewHashFromKeys(channel, secret.keys);
|
hashes.viewHash = getViewHashFromKeys(secret);
|
||||||
}
|
}
|
||||||
if (secret.keys.fileKeyStr) {
|
if (secret.keys.fileKeyStr) {
|
||||||
hashes.fileHash = getFileHashFromKeys(channel, secret.keys.fileKeyStr);
|
hashes.fileHash = getFileHashFromKeys(secret);
|
||||||
}
|
}
|
||||||
return hashes;
|
return hashes;
|
||||||
};
|
};
|
||||||
|
|
||||||
var createChannelId = Hash.createChannelId = function () {
|
|
||||||
var id = uint8ArrayToHex(Crypto.Nacl.randomBytes(16));
|
|
||||||
if (id.length !== 32 || /[^a-f0-9]/.test(id)) {
|
|
||||||
throw new Error('channel ids must consist of 32 hex characters');
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
};
|
|
||||||
|
|
||||||
Hash.createRandomHash = function () {
|
|
||||||
// 16 byte channel Id
|
|
||||||
var channelId = Util.hexToBase64(createChannelId());
|
|
||||||
// 18 byte encryption key
|
|
||||||
var key = Crypto.b64RemoveSlashes(Crypto.rand64(18));
|
|
||||||
return '/1/edit/' + [channelId, key].join('/') + '/';
|
|
||||||
};
|
|
||||||
|
|
||||||
// STORAGE
|
// STORAGE
|
||||||
Hash.findWeaker = function (href, recents) {
|
Hash.findWeaker = function (href, channel, recents) {
|
||||||
var rHref = href || getRelativeHref(window.location.href);
|
var parsed = parsePadUrl(href);
|
||||||
var parsed = parsePadUrl(rHref);
|
|
||||||
if (!parsed.hash) { return false; }
|
if (!parsed.hash) { return false; }
|
||||||
var weaker;
|
var weaker;
|
||||||
Object.keys(recents).some(function (id) {
|
Object.keys(recents).some(function (id) {
|
||||||
@ -279,6 +380,8 @@ Version 1
|
|||||||
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
|
||||||
|
if (channel !== pad.channel) { return; } // Not the same channel
|
||||||
|
|
||||||
var pHash = p.hashData;
|
var pHash = p.hashData;
|
||||||
var parsedHash = parsed.hashData;
|
var parsedHash = parsed.hashData;
|
||||||
if (!parsedHash || !pHash) { return; }
|
if (!parsedHash || !pHash) { return; }
|
||||||
@ -287,18 +390,16 @@ Version 1
|
|||||||
if (pHash.type !== 'pad' && parsedHash.type !== 'pad') { return; }
|
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.mode === 'view' && parsedHash.mode === 'edit') {
|
if (pHash.mode === 'view' && parsedHash.mode === 'edit') {
|
||||||
weaker = pad.href;
|
weaker = pad;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
return weaker;
|
return weaker;
|
||||||
};
|
};
|
||||||
var findStronger = Hash.findStronger = function (href, recents) {
|
Hash.findStronger = function (href, channel, recents) {
|
||||||
var rHref = href || getRelativeHref(window.location.href);
|
var parsed = parsePadUrl(href);
|
||||||
var parsed = parsePadUrl(rHref);
|
|
||||||
if (!parsed.hash) { return false; }
|
if (!parsed.hash) { return false; }
|
||||||
// We can't have a stronger hash if we're already in edit mode
|
// We can't have a stronger hash if we're already in edit mode
|
||||||
if (parsed.hashData && parsed.hashData.mode === 'edit') { return; }
|
if (parsed.hashData && parsed.hashData.mode === 'edit') { return; }
|
||||||
@ -308,6 +409,8 @@ Version 1
|
|||||||
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
|
||||||
|
if (channel !== pad.channel) { return; } // Not the same channel
|
||||||
|
|
||||||
var pHash = p.hashData;
|
var pHash = p.hashData;
|
||||||
var parsedHash = parsed.hashData;
|
var parsedHash = parsed.hashData;
|
||||||
if (!parsedHash || !pHash) { return; }
|
if (!parsedHash || !pHash) { return; }
|
||||||
@ -316,37 +419,20 @@ Version 1
|
|||||||
if (pHash.type !== 'pad' && parsedHash.type !== 'pad') { return; }
|
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.mode === 'edit' && parsedHash.mode === 'view') {
|
if (pHash.mode === 'edit' && parsedHash.mode === 'view') {
|
||||||
stronger = pad.href;
|
stronger = pad;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
return stronger;
|
return stronger;
|
||||||
};
|
};
|
||||||
Hash.isNotStrongestStored = function (href, recents) {
|
|
||||||
return findStronger(href, recents);
|
|
||||||
};
|
|
||||||
|
|
||||||
Hash.hrefToHexChannelId = function (href) {
|
Hash.hrefToHexChannelId = function (href, password) {
|
||||||
var parsed = Hash.parsePadUrl(href);
|
var parsed = Hash.parsePadUrl(href);
|
||||||
if (!parsed || !parsed.hash) { return; }
|
if (!parsed || !parsed.hash) { return; }
|
||||||
|
var secret = Hash.getSecrets(parsed.type, parsed.hash, password);
|
||||||
parsed = parsed.hashData;
|
return secret.channel;
|
||||||
if (parsed.version === 0) {
|
|
||||||
return parsed.channel;
|
|
||||||
} else if (parsed.version !== 1 && parsed.version !== 2) {
|
|
||||||
console.error("parsed href had no version");
|
|
||||||
console.error(parsed);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var channel = parsed.channel;
|
|
||||||
if (!channel) { return; }
|
|
||||||
|
|
||||||
var hex = base64ToHex(channel);
|
|
||||||
return hex;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Hash.getBlobPathFromHex = function (id) {
|
Hash.getBlobPathFromHex = function (id) {
|
||||||
|
|||||||
@ -594,7 +594,12 @@ define([
|
|||||||
$('.cp-loading-spinner-container').hide();
|
$('.cp-loading-spinner-container').hide();
|
||||||
$('#cp-loading-tip').remove();
|
$('#cp-loading-tip').remove();
|
||||||
if (transparent) { $('#' + LOADING).css('opacity', 0.9); }
|
if (transparent) { $('#' + LOADING).css('opacity', 0.9); }
|
||||||
$('#' + LOADING).find('p').show().html(error || Messages.error);
|
var $error = $('#' + LOADING).find('p').show();
|
||||||
|
if (error instanceof Element) {
|
||||||
|
$error.html('').append(error);
|
||||||
|
} else {
|
||||||
|
$error.html(error || Messages.error);
|
||||||
|
}
|
||||||
if (exitable) {
|
if (exitable) {
|
||||||
$(window).focus();
|
$(window).focus();
|
||||||
$(window).keydown(function (e) {
|
$(window).keydown(function (e) {
|
||||||
|
|||||||
@ -99,7 +99,7 @@ define([
|
|||||||
try {
|
try {
|
||||||
var parsed = Hash.parsePadUrl(window.location.href);
|
var parsed = Hash.parsePadUrl(window.location.href);
|
||||||
if (!parsed.hashData) { return; }
|
if (!parsed.hashData) { return; }
|
||||||
var chan = parsed.hashData.channel;
|
var chan = Hash.hrefToHexChannelId(window.location.href);
|
||||||
// Decrypt
|
// Decrypt
|
||||||
var keyStr = parsed.hashData.key;
|
var keyStr = parsed.hashData.key;
|
||||||
var cryptor = Crypto.createEditCryptor(keyStr);
|
var cryptor = Crypto.createEditCryptor(keyStr);
|
||||||
@ -113,7 +113,7 @@ define([
|
|||||||
if (!decryptMsg) { return; }
|
if (!decryptMsg) { return; }
|
||||||
// Parse
|
// Parse
|
||||||
msg = JSON.parse(decryptMsg);
|
msg = JSON.parse(decryptMsg);
|
||||||
if (msg[1] !== parsed.hashData.channel) { return; }
|
if (msg[1] !== chan) { return; }
|
||||||
var msgData = msg[2];
|
var msgData = msg[2];
|
||||||
var msgStr;
|
var msgStr;
|
||||||
if (msg[0] === "FRIEND_REQ") {
|
if (msg[0] === "FRIEND_REQ") {
|
||||||
@ -199,7 +199,7 @@ define([
|
|||||||
var parsed = Hash.parsePadUrl(data.href);
|
var parsed = Hash.parsePadUrl(data.href);
|
||||||
if (!parsed.hashData) { return; }
|
if (!parsed.hashData) { return; }
|
||||||
// Message
|
// Message
|
||||||
var chan = parsed.hashData.channel;
|
var chan = Hash.hrefToHexChannelId(data.href);
|
||||||
var myData = createData(cfg.proxy);
|
var myData = createData(cfg.proxy);
|
||||||
var msg = ["FRIEND_REQ", chan, myData];
|
var msg = ["FRIEND_REQ", chan, myData];
|
||||||
// Encryption
|
// Encryption
|
||||||
|
|||||||
@ -205,7 +205,7 @@ define([
|
|||||||
if (content === oldThumbnailState) { return; }
|
if (content === oldThumbnailState) { return; }
|
||||||
oldThumbnailState = content;
|
oldThumbnailState = content;
|
||||||
Thumb.fromDOM(opts, function (err, b64) {
|
Thumb.fromDOM(opts, function (err, b64) {
|
||||||
Thumb.setPadThumbnail(common, opts.href, b64);
|
Thumb.setPadThumbnail(common, opts.href, null, b64);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var nafa = Util.notAgainForAnother(mkThumbnail, Thumb.UPDATE_INTERVAL);
|
var nafa = Util.notAgainForAnother(mkThumbnail, Thumb.UPDATE_INTERVAL);
|
||||||
@ -240,20 +240,22 @@ define([
|
|||||||
Thumb.addThumbnail = function(thumb, $span, cb) {
|
Thumb.addThumbnail = function(thumb, $span, cb) {
|
||||||
return addThumbnail(null, thumb, $span, cb);
|
return addThumbnail(null, thumb, $span, cb);
|
||||||
};
|
};
|
||||||
var getKey = function (href) {
|
var getKey = function (type, channel) {
|
||||||
var parsed = Hash.parsePadUrl(href);
|
return 'thumbnail-' + type + '-' + channel;
|
||||||
return 'thumbnail-' + parsed.type + '-' + parsed.hashData.channel;
|
|
||||||
};
|
};
|
||||||
Thumb.setPadThumbnail = function (common, href, b64, cb) {
|
Thumb.setPadThumbnail = function (common, href, channel, b64, cb) {
|
||||||
cb = cb || function () {};
|
cb = cb || function () {};
|
||||||
var k = getKey(href);
|
var parsed = Hash.parsePadUrl(href);
|
||||||
|
channel = channel || common.getMetadataMgr().getPrivateData().channel;
|
||||||
|
var k = getKey(parsed.type, channel);
|
||||||
common.setThumbnail(k, b64, cb);
|
common.setThumbnail(k, b64, cb);
|
||||||
};
|
};
|
||||||
Thumb.displayThumbnail = function (common, href, $container, cb) {
|
Thumb.displayThumbnail = function (common, href, channel, $container, cb) {
|
||||||
cb = cb || function () {};
|
cb = cb || function () {};
|
||||||
var parsed = Hash.parsePadUrl(href);
|
var parsed = Hash.parsePadUrl(href);
|
||||||
var k = getKey(href);
|
var k = getKey(parsed.type, channel);
|
||||||
var whenNewThumb = function () {
|
var whenNewThumb = function () {
|
||||||
|
// PASSWORD_FILES
|
||||||
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);
|
||||||
var src = Hash.getBlobPathFromHex(hexFileName);
|
var src = Hash.getBlobPathFromHex(hexFileName);
|
||||||
@ -270,7 +272,7 @@ define([
|
|||||||
if (!v) {
|
if (!v) {
|
||||||
v = 'EMPTY';
|
v = 'EMPTY';
|
||||||
}
|
}
|
||||||
Thumb.setPadThumbnail(common, href, v, function (err) {
|
Thumb.setPadThumbnail(common, href, hexFileName, v, function (err) {
|
||||||
if (!metadata.thumbnail) { return; }
|
if (!metadata.thumbnail) { return; }
|
||||||
addThumbnail(err, metadata.thumbnail, $container, cb);
|
addThumbnail(err, metadata.thumbnail, $container, cb);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -60,6 +60,10 @@ define([
|
|||||||
var getPropertiesData = function (common, cb) {
|
var getPropertiesData = function (common, cb) {
|
||||||
var data = {};
|
var data = {};
|
||||||
NThen(function (waitFor) {
|
NThen(function (waitFor) {
|
||||||
|
common.getPadAttribute('password', waitFor(function (err, val) {
|
||||||
|
data.password = val;
|
||||||
|
}));
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
common.getPadAttribute('href', waitFor(function (err, val) {
|
common.getPadAttribute('href', waitFor(function (err, val) {
|
||||||
var base = common.getMetadataMgr().getPrivateData().origin;
|
var base = common.getMetadataMgr().getPrivateData().origin;
|
||||||
|
|
||||||
@ -71,15 +75,19 @@ define([
|
|||||||
|
|
||||||
// We're not in a read-only pad
|
// We're not in a read-only pad
|
||||||
data.href = base + val;
|
data.href = base + val;
|
||||||
|
|
||||||
// Get Read-only href
|
// Get Read-only href
|
||||||
if (parsed.hashData.type !== "pad") { return; }
|
if (parsed.hashData.type !== "pad") { return; }
|
||||||
var i = data.href.indexOf('#') + 1;
|
var i = data.href.indexOf('#') + 1;
|
||||||
var hBase = data.href.slice(0, i);
|
var hBase = data.href.slice(0, i);
|
||||||
var hrefsecret = Hash.getSecrets(parsed.type, parsed.hash);
|
var hrefsecret = Hash.getSecrets(parsed.type, parsed.hash, data.password);
|
||||||
if (!hrefsecret.keys) { return; }
|
if (!hrefsecret.keys) { return; }
|
||||||
var viewHash = Hash.getViewHashFromKeys(hrefsecret.channel, hrefsecret.keys);
|
var viewHash = Hash.getViewHashFromKeys(hrefsecret);
|
||||||
data.roHref = hBase + viewHash;
|
data.roHref = hBase + viewHash;
|
||||||
}));
|
}));
|
||||||
|
common.getPadAttribute('channel', waitFor(function (err, val) {
|
||||||
|
data.channel = val;
|
||||||
|
}));
|
||||||
common.getPadAttribute('atime', waitFor(function (err, val) {
|
common.getPadAttribute('atime', waitFor(function (err, val) {
|
||||||
data.atime = val;
|
data.atime = val;
|
||||||
}));
|
}));
|
||||||
@ -176,7 +184,7 @@ define([
|
|||||||
|
|
||||||
if (common.isLoggedIn() && AppConfig.enablePinning) {
|
if (common.isLoggedIn() && AppConfig.enablePinning) {
|
||||||
// check the size of this file...
|
// check the size of this file...
|
||||||
common.getFileSize(data.href, function (e, bytes) {
|
common.getFileSize(data.channel, function (e, bytes) {
|
||||||
if (e) {
|
if (e) {
|
||||||
// there was a problem with the RPC
|
// there was a problem with the RPC
|
||||||
console.error(e);
|
console.error(e);
|
||||||
@ -926,14 +934,14 @@ define([
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
UIElements.createHelpMenu = function (common, categories) {
|
|
||||||
var type = common.getMetadataMgr().getMetadata().type || 'pad';
|
|
||||||
|
|
||||||
var setHTML = function (e, html) {
|
var setHTML = function (e, html) {
|
||||||
e.innerHTML = html;
|
e.innerHTML = html;
|
||||||
return e;
|
return e;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
UIElements.createHelpMenu = function (common, categories) {
|
||||||
|
var type = common.getMetadataMgr().getMetadata().type || 'pad';
|
||||||
|
|
||||||
var elements = [];
|
var elements = [];
|
||||||
if (Messages.help && Messages.help.generic) {
|
if (Messages.help && Messages.help.generic) {
|
||||||
Object.keys(Messages.help.generic).forEach(function (el) {
|
Object.keys(Messages.help.generic).forEach(function (el) {
|
||||||
@ -1135,12 +1143,13 @@ define([
|
|||||||
};
|
};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// No password for avatars
|
||||||
var secret = Hash.getSecrets('file', parsed.hash);
|
var secret = Hash.getSecrets('file', parsed.hash);
|
||||||
if (secret.keys && secret.channel) {
|
if (secret.keys && secret.channel) {
|
||||||
var cryptKey = secret.keys && secret.keys.fileKeyStr;
|
var cryptKey = secret.keys && secret.keys.fileKeyStr;
|
||||||
var hexFileName = Util.base64ToHex(secret.channel);
|
var hexFileName = Util.base64ToHex(secret.channel);
|
||||||
var src = Hash.getBlobPathFromHex(hexFileName);
|
var src = Hash.getBlobPathFromHex(hexFileName);
|
||||||
Common.getFileSize(href, function (e, data) {
|
Common.getFileSize(hexFileName, function (e, data) {
|
||||||
if (e) {
|
if (e) {
|
||||||
displayDefault();
|
displayDefault();
|
||||||
return void console.error(e);
|
return void console.error(e);
|
||||||
@ -1907,6 +1916,17 @@ define([
|
|||||||
createHelper('/faq.html#keywords-expiring', Messages.creation_expire2),
|
createHelper('/faq.html#keywords-expiring', Messages.creation_expire2),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Password
|
||||||
|
var password = h('div.cp-creation-password', [
|
||||||
|
UI.createCheckbox('cp-creation-password', Messages.creation_password, false),
|
||||||
|
h('span.cp-creation-password-picker.cp-creation-slider', [
|
||||||
|
h('input#cp-creation-password-val', {
|
||||||
|
type: "text" // TODO type password with click to show
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
//createHelper('#', "TODO: password protection adds another layer of security ........") // TODO
|
||||||
|
]);
|
||||||
|
|
||||||
var right = h('span.fa.fa-chevron-right.cp-creation-template-more');
|
var right = h('span.fa.fa-chevron-right.cp-creation-template-more');
|
||||||
var left = h('span.fa.fa-chevron-left.cp-creation-template-more');
|
var left = h('span.fa.fa-chevron-left.cp-creation-template-more');
|
||||||
var templates = h('div.cp-creation-template', [
|
var templates = h('div.cp-creation-template', [
|
||||||
@ -1932,6 +1952,7 @@ define([
|
|||||||
$(h('div#cp-creation-form', [
|
$(h('div#cp-creation-form', [
|
||||||
owned,
|
owned,
|
||||||
expire,
|
expire,
|
||||||
|
password,
|
||||||
settings,
|
settings,
|
||||||
templates,
|
templates,
|
||||||
createDiv
|
createDiv
|
||||||
@ -2042,6 +2063,19 @@ define([
|
|||||||
$creation.focus();
|
$creation.focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Display expiration form when checkbox checked
|
||||||
|
$creation.find('#cp-creation-password').on('change', function () {
|
||||||
|
if ($(this).is(':checked')) {
|
||||||
|
$creation.find('.cp-creation-password-picker:not(.active)').addClass('active');
|
||||||
|
$creation.find('.cp-creation-password:not(.active)').addClass('active');
|
||||||
|
$creation.find('#cp-creation-password-val').focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$creation.find('.cp-creation-password-picker').removeClass('active');
|
||||||
|
$creation.find('.cp-creation-password').removeClass('active');
|
||||||
|
$creation.focus();
|
||||||
|
});
|
||||||
|
|
||||||
// Display settings help when checkbox checked
|
// Display settings help when checkbox checked
|
||||||
$creation.find('#cp-creation-remember').on('change', function () {
|
$creation.find('#cp-creation-remember').on('change', function () {
|
||||||
if ($(this).is(':checked')) {
|
if ($(this).is(':checked')) {
|
||||||
@ -2090,12 +2124,16 @@ define([
|
|||||||
}
|
}
|
||||||
expireVal = ($('#cp-creation-expire-val').val() || 0) * unit;
|
expireVal = ($('#cp-creation-expire-val').val() || 0) * unit;
|
||||||
}
|
}
|
||||||
|
// Password
|
||||||
|
var passwordVal = $('#cp-creation-password').is(':checked') ?
|
||||||
|
$('#cp-creation-password-val').val() : undefined;
|
||||||
|
|
||||||
var $template = $creation.find('.cp-creation-template-selected');
|
var $template = $creation.find('.cp-creation-template-selected');
|
||||||
var templateId = $template.data('id') || undefined;
|
var templateId = $template.data('id') || undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
owned: ownedVal,
|
owned: ownedVal,
|
||||||
|
password: passwordVal,
|
||||||
expire: expireVal,
|
expire: expireVal,
|
||||||
templateId: templateId
|
templateId: templateId
|
||||||
};
|
};
|
||||||
@ -2165,5 +2203,39 @@ define([
|
|||||||
(cb || function () {})();
|
(cb || function () {})();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
UIElements.displayPasswordPrompt = function (common, isError) {
|
||||||
|
var error;
|
||||||
|
if (isError) { error = setHTML(h('p.cp-password-error'), Messages.password_error); }
|
||||||
|
var info = h('p.cp-password-info', Messages.password_info);
|
||||||
|
var input = h('input', {
|
||||||
|
type: "password",
|
||||||
|
placeholder: Messages.password_placeholder
|
||||||
|
});
|
||||||
|
var button = h('button', Messages.password_submit);
|
||||||
|
|
||||||
|
var submit = function () {
|
||||||
|
var value = $(input).val();
|
||||||
|
UI.addLoadingScreen();
|
||||||
|
common.getSframeChannel().query('Q_PAD_PASSWORD_VALUE', value, function (err, data) {
|
||||||
|
if (!data) {
|
||||||
|
UIElements.displayPasswordPrompt(common, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
$(input).on('keydown', function (e) { if (e.which === 13) { submit(); } });
|
||||||
|
$(button).on('click', function () { submit(); });
|
||||||
|
|
||||||
|
|
||||||
|
var block = h('div#cp-loading-password-prompt', [
|
||||||
|
error,
|
||||||
|
info,
|
||||||
|
h('p.cp-password-form', [
|
||||||
|
input,
|
||||||
|
button
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
UI.errorLoadingScreen(block);
|
||||||
|
};
|
||||||
|
|
||||||
return UIElements;
|
return UIElements;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -20,9 +20,9 @@ define([
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var makeConfig = function (hash) {
|
var makeConfig = function (hash, password) {
|
||||||
// We can't use cryptget with a file or a user so we can use 'pad' as hash type
|
// We can't use cryptget with a file or a user so we can use 'pad' as hash type
|
||||||
var secret = Hash.getSecrets('pad', hash);
|
var secret = Hash.getSecrets('pad', hash, password);
|
||||||
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: NetConfig.getWebsocketURL(),
|
websocketURL: NetConfig.getWebsocketURL(),
|
||||||
@ -47,8 +47,10 @@ define([
|
|||||||
if (typeof(cb) !== 'function') {
|
if (typeof(cb) !== 'function') {
|
||||||
throw new Error('Cryptget expects a callback');
|
throw new Error('Cryptget expects a callback');
|
||||||
}
|
}
|
||||||
|
opt = opt || {};
|
||||||
|
|
||||||
|
var config = makeConfig(hash, opt.password);
|
||||||
var Session = { cb: cb, };
|
var Session = { cb: cb, };
|
||||||
var config = makeConfig(hash);
|
|
||||||
|
|
||||||
config.onReady = function (info) {
|
config.onReady = function (info) {
|
||||||
var rt = Session.session = info.realtime;
|
var rt = Session.session = info.realtime;
|
||||||
@ -64,9 +66,11 @@ define([
|
|||||||
if (typeof(cb) !== 'function') {
|
if (typeof(cb) !== 'function') {
|
||||||
throw new Error('Cryptput expects a callback');
|
throw new Error('Cryptput expects a callback');
|
||||||
}
|
}
|
||||||
|
opt = opt || {};
|
||||||
|
|
||||||
var config = makeConfig(hash);
|
var config = makeConfig(hash, opt.password);
|
||||||
var Session = { cb: cb, };
|
var Session = { cb: cb, };
|
||||||
|
|
||||||
config.onReady = function (info) {
|
config.onReady = function (info) {
|
||||||
var realtime = Session.session = info.realtime;
|
var realtime = Session.session = info.realtime;
|
||||||
Session.network = info.network;
|
Session.network = info.network;
|
||||||
|
|||||||
@ -246,8 +246,8 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
common.getFileSize = function (href, cb) {
|
common.getFileSize = function (href, password, cb) {
|
||||||
postMessage("GET_FILE_SIZE", {href: href}, function (obj) {
|
postMessage("GET_FILE_SIZE", {href: href, password: password}, function (obj) {
|
||||||
if (obj && obj.error) { return void cb(obj.error); }
|
if (obj && obj.error) { return void cb(obj.error); }
|
||||||
cb(undefined, obj.size);
|
cb(undefined, obj.size);
|
||||||
});
|
});
|
||||||
@ -260,8 +260,8 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
common.isNewChannel = function (href, cb) {
|
common.isNewChannel = function (href, password, cb) {
|
||||||
postMessage('IS_NEW_CHANNEL', {href: href}, function (obj) {
|
postMessage('IS_NEW_CHANNEL', {href: href, password: password}, function (obj) {
|
||||||
if (obj.error) { return void cb(obj.error); }
|
if (obj.error) { return void cb(obj.error); }
|
||||||
if (!obj) { return void cb('INVALID_RESPONSE'); }
|
if (!obj) { return void cb('INVALID_RESPONSE'); }
|
||||||
cb(undefined, obj.isNew);
|
cb(undefined, obj.isNew);
|
||||||
@ -395,8 +395,10 @@ define([
|
|||||||
common.saveAsTemplate = function (Cryptput, data, cb) {
|
common.saveAsTemplate = function (Cryptput, data, cb) {
|
||||||
var p = Hash.parsePadUrl(window.location.href);
|
var p = Hash.parsePadUrl(window.location.href);
|
||||||
if (!p.type) { return; }
|
if (!p.type) { return; }
|
||||||
var hash = Hash.createRandomHash();
|
// PPP: password for the new template?
|
||||||
|
var hash = Hash.createRandomHash(p.type);
|
||||||
var href = '/' + p.type + '/#' + hash;
|
var href = '/' + p.type + '/#' + hash;
|
||||||
|
// PPP: add password as cryptput option
|
||||||
Cryptput(hash, data.toSave, function (e) {
|
Cryptput(hash, data.toSave, function (e) {
|
||||||
if (e) { throw new Error(e); }
|
if (e) { throw new Error(e); }
|
||||||
postMessage("ADD_PAD", {
|
postMessage("ADD_PAD", {
|
||||||
@ -419,16 +421,33 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
common.useTemplate = function (href, Crypt, cb, opts) {
|
common.useTemplate = function (href, Crypt, cb, optsPut) {
|
||||||
// opts is used to overrides options for chainpad-netflux in cryptput
|
// opts is used to overrides options for chainpad-netflux in cryptput
|
||||||
// it allows us to add owners and expiration time if it is a new file
|
// it allows us to add owners and expiration time if it is a new file
|
||||||
|
|
||||||
var parsed = Hash.parsePadUrl(href);
|
var parsed = Hash.parsePadUrl(href);
|
||||||
|
var parsed2 = Hash.parsePadUrl(window.location.href);
|
||||||
if(!parsed) { throw new Error("Cannot get template hash"); }
|
if(!parsed) { throw new Error("Cannot get template hash"); }
|
||||||
postMessage("INCREMENT_TEMPLATE_USE", href);
|
postMessage("INCREMENT_TEMPLATE_USE", href);
|
||||||
|
|
||||||
|
optsPut = optsPut || {};
|
||||||
|
var optsGet = {};
|
||||||
|
Nthen(function (waitFor) {
|
||||||
|
if (parsed.hashData && parsed.hashData.password) {
|
||||||
|
common.getPadAttribute('password', waitFor(function (err, password) {
|
||||||
|
optsGet.password = password;
|
||||||
|
}), href);
|
||||||
|
}
|
||||||
|
if (parsed2.hashData && parsed2.hashData.password) {
|
||||||
|
common.getPadAttribute('password', waitFor(function (err, password) {
|
||||||
|
optsPut.password = password;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}).nThen(function () {
|
||||||
Crypt.get(parsed.hash, function (err, val) {
|
Crypt.get(parsed.hash, function (err, val) {
|
||||||
if (err) { throw new Error(err); }
|
if (err) { throw new Error(err); }
|
||||||
var p = Hash.parsePadUrl(window.location.href);
|
Crypt.put(parsed2.hash, val, cb, optsPut);
|
||||||
Crypt.put(p.hash, val, cb, opts);
|
}, optsGet);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -439,20 +458,18 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
// When opening a new pad or renaming it, store the new title
|
// When opening a new pad or renaming it, store the new title
|
||||||
common.setPadTitle = function (title, padHref, path, cb) {
|
common.setPadTitle = function (data, cb) {
|
||||||
var href = padHref || window.location.href;
|
if (!data || typeof (data) !== "object") { return cb ('Data is not an object'); }
|
||||||
|
|
||||||
|
var href = data.href || window.location.href;
|
||||||
var parsed = Hash.parsePadUrl(href);
|
var parsed = Hash.parsePadUrl(href);
|
||||||
if (!parsed.hash) { return; }
|
if (!parsed.hash) { return cb ('Invalid hash'); }
|
||||||
href = parsed.getUrl({present: parsed.present});
|
data.href = parsed.getUrl({present: parsed.present});
|
||||||
|
|
||||||
if (title === null) { return; }
|
if (typeof (data.title) !== "string") { return cb('Missing title'); }
|
||||||
if (title.trim() === "") { title = Hash.getDefaultName(parsed); }
|
if (data.title.trim() === "") { data.title = Hash.getDefaultName(parsed); }
|
||||||
|
|
||||||
postMessage("SET_PAD_TITLE", {
|
postMessage("SET_PAD_TITLE", data, function (obj) {
|
||||||
href: href,
|
|
||||||
title: title,
|
|
||||||
path: path
|
|
||||||
}, function (obj) {
|
|
||||||
if (obj && obj.error) {
|
if (obj && obj.error) {
|
||||||
console.log("unable to set pad title");
|
console.log("unable to set pad title");
|
||||||
return void cb(obj.error);
|
return void cb(obj.error);
|
||||||
@ -473,10 +490,6 @@ define([
|
|||||||
cb(void 0, data);
|
cb(void 0, data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
// Set initial path when creating a pad from pad creation screen
|
|
||||||
common.setInitialPath = function (path) {
|
|
||||||
postMessage("SET_INITIAL_PATH", path);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Messaging (manage friends from the userlist)
|
// Messaging (manage friends from the userlist)
|
||||||
common.inviteFromUserlist = function (netfluxId, cb) {
|
common.inviteFromUserlist = function (netfluxId, cb) {
|
||||||
@ -556,15 +569,15 @@ define([
|
|||||||
common.getShareHashes = function (secret, cb) {
|
common.getShareHashes = function (secret, cb) {
|
||||||
var hashes;
|
var hashes;
|
||||||
if (!window.location.hash) {
|
if (!window.location.hash) {
|
||||||
hashes = Hash.getHashes(secret.channel, secret);
|
hashes = Hash.getHashes(secret);
|
||||||
return void cb(null, hashes);
|
return void cb(null, hashes);
|
||||||
}
|
}
|
||||||
var parsed = Hash.parsePadUrl(window.location.href);
|
var parsed = Hash.parsePadUrl(window.location.href);
|
||||||
if (!parsed.type || !parsed.hashData) { return void cb('E_INVALID_HREF'); }
|
if (!parsed.type || !parsed.hashData) { return void cb('E_INVALID_HREF'); }
|
||||||
if (parsed.type === 'file') { secret.channel = Util.base64ToHex(secret.channel); }
|
if (parsed.type === 'file') { secret.channel = Util.base64ToHex(secret.channel); }
|
||||||
hashes = Hash.getHashes(secret.channel, secret);
|
hashes = Hash.getHashes(secret);
|
||||||
|
|
||||||
if (!hashes.editHash && !hashes.viewHash && parsed.hashData && !parsed.hashData.mode) {
|
if (secret.version === 0) {
|
||||||
// It means we're using an old hash
|
// It means we're using an old hash
|
||||||
hashes.editHash = window.location.hash.slice(1);
|
hashes.editHash = window.location.hash.slice(1);
|
||||||
return void cb(null, hashes);
|
return void cb(null, hashes);
|
||||||
@ -576,7 +589,8 @@ define([
|
|||||||
}
|
}
|
||||||
|
|
||||||
postMessage("GET_STRONGER_HASH", {
|
postMessage("GET_STRONGER_HASH", {
|
||||||
href: window.location.href
|
href: window.location.href,
|
||||||
|
password: secret.password
|
||||||
}, function (hash) {
|
}, function (hash) {
|
||||||
if (hash) { hashes.editHash = hash; }
|
if (hash) { hashes.editHash = hash; }
|
||||||
cb(null, hashes);
|
cb(null, hashes);
|
||||||
@ -813,18 +827,18 @@ define([
|
|||||||
window.onhashchange = function (ev) {
|
window.onhashchange = function (ev) {
|
||||||
if (ev && ev.reset) { oldHref = document.location.href; return; }
|
if (ev && ev.reset) { oldHref = document.location.href; return; }
|
||||||
var newHref = document.location.href;
|
var newHref = document.location.href;
|
||||||
var parsedOld = Hash.parsePadUrl(oldHref).hashData;
|
|
||||||
var parsedNew = Hash.parsePadUrl(newHref).hashData;
|
// Compare the URLs without /embed and /present
|
||||||
if (parsedOld && parsedNew && (
|
var parsedOld = Hash.parsePadUrl(oldHref);
|
||||||
parsedOld.type !== parsedNew.type
|
var parsedNew = Hash.parsePadUrl(newHref);
|
||||||
|| parsedOld.channel !== parsedNew.channel
|
if (parsedOld.hashData && parsedNew.hashData &&
|
||||||
|| parsedOld.mode !== parsedNew.mode
|
parsedOld.getUrl() !== parsedNew.getUrl()) {
|
||||||
|| parsedOld.key !== parsedNew.key)) {
|
if (!parsedOld.hashData.key) { oldHref = newHref; return; }
|
||||||
if (!parsedOld.channel) { oldHref = newHref; return; }
|
// If different, reload
|
||||||
document.location.reload();
|
document.location.reload();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (parsedNew) { oldHref = newHref; }
|
if (parsedNew.hashData) { oldHref = newHref; }
|
||||||
};
|
};
|
||||||
// Listen for login/logout in other tabs
|
// Listen for login/logout in other tabs
|
||||||
window.addEventListener('storage', function (e) {
|
window.addEventListener('storage', function (e) {
|
||||||
|
|||||||
@ -41,6 +41,7 @@ define([
|
|||||||
};
|
};
|
||||||
renderer.image = function (href, title, text) {
|
renderer.image = function (href, title, text) {
|
||||||
if (href.slice(0,6) === '/file/') {
|
if (href.slice(0,6) === '/file/') {
|
||||||
|
// PASSWORD_FILES
|
||||||
var parsed = Hash.parsePadUrl(href);
|
var parsed = Hash.parsePadUrl(href);
|
||||||
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
||||||
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
||||||
|
|||||||
@ -122,21 +122,15 @@ define([
|
|||||||
// Do not migrate a pad if we already have it, it would create a duplicate in the drive
|
// Do not migrate a pad if we already have it, it would create a duplicate in the drive
|
||||||
if (newHrefs.indexOf(href) !== -1) { return; }
|
if (newHrefs.indexOf(href) !== -1) { return; }
|
||||||
// If we have a stronger version, do not add the current href
|
// If we have a stronger version, do not add the current href
|
||||||
if (Hash.findStronger(href, newRecentPads)) { return; }
|
if (Hash.findStronger(href, oldRecentPads[id].channel, newRecentPads)) { return; }
|
||||||
// If we have a weaker version, replace the href by the new one
|
// If we have a weaker version, replace the href by the new one
|
||||||
// NOTE: if that weaker version is in the trash, the strong one will be put in unsorted
|
// NOTE: if that weaker version is in the trash, the strong one will be put in unsorted
|
||||||
var weaker = Hash.findWeaker(href, newRecentPads);
|
var weaker = Hash.findWeaker(href, oldRecentPads[id].channel, newRecentPads);
|
||||||
if (weaker) {
|
if (weaker) {
|
||||||
// Update RECENTPADS
|
// Update RECENTPADS
|
||||||
newRecentPads.some(function (pad) {
|
weaker.href = href;
|
||||||
if (pad.href === weaker) {
|
|
||||||
pad.href = href;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
// Update the file in the drive
|
// Update the file in the drive
|
||||||
newFo.replace(weaker, href);
|
newFo.replace(weaker.href, href);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Here it means we have a new href, so we should add it to the drive at its old location
|
// Here it means we have a new href, so we should add it to the drive at its old location
|
||||||
|
|||||||
@ -68,8 +68,9 @@ define([
|
|||||||
var userHash = storeHash;
|
var userHash = storeHash;
|
||||||
if (!userHash) { return null; }
|
if (!userHash) { return null; }
|
||||||
|
|
||||||
var userParsedHash = Hash.parseTypeHash('drive', userHash);
|
// No password for drive
|
||||||
var userChannel = userParsedHash && userParsedHash.channel;
|
var secret = Hash.getSecrets('drive', userHash);
|
||||||
|
var userChannel = secret.channel;
|
||||||
if (!userChannel) { return null; }
|
if (!userChannel) { return null; }
|
||||||
|
|
||||||
// Get the list of pads' channel ID in your drive
|
// Get the list of pads' channel ID in your drive
|
||||||
@ -81,16 +82,16 @@ define([
|
|||||||
var d = store.userObject.getFileData(id);
|
var d = store.userObject.getFileData(id);
|
||||||
if (d.owners && d.owners.length && edPublic &&
|
if (d.owners && d.owners.length && edPublic &&
|
||||||
d.owners.indexOf(edPublic) === -1) { return; }
|
d.owners.indexOf(edPublic) === -1) { return; }
|
||||||
return Hash.hrefToHexChannelId(d.href);
|
return d.channel;
|
||||||
})
|
})
|
||||||
.filter(function (x) { return x; });
|
.filter(function (x) { return x; });
|
||||||
|
|
||||||
// Get the avatar
|
// Get the avatar
|
||||||
var profile = store.proxy.profile;
|
var profile = store.proxy.profile;
|
||||||
if (profile) {
|
if (profile) {
|
||||||
var profileChan = profile.edit ? Hash.hrefToHexChannelId('/profile/#' + profile.edit) : null;
|
var profileChan = profile.edit ? Hash.hrefToHexChannelId('/profile/#' + profile.edit, null) : null;
|
||||||
if (profileChan) { list.push(profileChan); }
|
if (profileChan) { list.push(profileChan); }
|
||||||
var avatarChan = profile.avatar ? Hash.hrefToHexChannelId(profile.avatar) : null;
|
var avatarChan = profile.avatar ? Hash.hrefToHexChannelId(profile.avatar, null) : null;
|
||||||
if (avatarChan) { list.push(avatarChan); }
|
if (avatarChan) { list.push(avatarChan); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +100,7 @@ define([
|
|||||||
list = list.concat(fList);
|
list = list.concat(fList);
|
||||||
}
|
}
|
||||||
|
|
||||||
list.push(Util.base64ToHex(userChannel));
|
list.push(userChannel);
|
||||||
list.sort();
|
list.sort();
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
@ -115,7 +116,7 @@ define([
|
|||||||
// because of the expiration time
|
// because of the expiration time
|
||||||
if ((data.owners && data.owners.length && data.owners.indexOf(edPublic) === -1) ||
|
if ((data.owners && data.owners.length && data.owners.indexOf(edPublic) === -1) ||
|
||||||
(data.expire && data.expire < (+new Date()))) {
|
(data.expire && data.expire < (+new Date()))) {
|
||||||
list.push(Hash.hrefToHexChannelId(data.href));
|
list.push(data.channel);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return list;
|
return list;
|
||||||
@ -303,7 +304,7 @@ define([
|
|||||||
Store.getFileSize = function (data, cb) {
|
Store.getFileSize = function (data, cb) {
|
||||||
if (!store.anon_rpc) { return void cb({error: 'ANON_RPC_NOT_READY'}); }
|
if (!store.anon_rpc) { return void cb({error: 'ANON_RPC_NOT_READY'}); }
|
||||||
|
|
||||||
var channelId = Hash.hrefToHexChannelId(data.href);
|
var channelId = Hash.hrefToHexChannelId(data.href, data.password);
|
||||||
store.anon_rpc.send("GET_FILE_SIZE", channelId, function (e, response) {
|
store.anon_rpc.send("GET_FILE_SIZE", channelId, function (e, response) {
|
||||||
if (e) { return void cb({error: e}); }
|
if (e) { return void cb({error: e}); }
|
||||||
if (response && response.length && typeof(response[0]) === 'number') {
|
if (response && response.length && typeof(response[0]) === 'number') {
|
||||||
@ -316,7 +317,7 @@ define([
|
|||||||
|
|
||||||
Store.isNewChannel = function (data, cb) {
|
Store.isNewChannel = function (data, cb) {
|
||||||
if (!store.anon_rpc) { return void cb({error: 'ANON_RPC_NOT_READY'}); }
|
if (!store.anon_rpc) { return void cb({error: 'ANON_RPC_NOT_READY'}); }
|
||||||
var channelId = Hash.hrefToHexChannelId(data.href);
|
var channelId = Hash.hrefToHexChannelId(data.href, data.password);
|
||||||
store.anon_rpc.send("IS_NEW_CHANNEL", channelId, function (e, response) {
|
store.anon_rpc.send("IS_NEW_CHANNEL", channelId, function (e, response) {
|
||||||
if (e) { return void cb({error: e}); }
|
if (e) { return void cb({error: e}); }
|
||||||
if (response && response.length && typeof(response[0]) === 'boolean') {
|
if (response && response.length && typeof(response[0]) === 'boolean') {
|
||||||
@ -416,6 +417,8 @@ define([
|
|||||||
var pad = makePad(data.href, data.title);
|
var pad = makePad(data.href, data.title);
|
||||||
if (data.owners) { pad.owners = data.owners; }
|
if (data.owners) { pad.owners = data.owners; }
|
||||||
if (data.expire) { pad.expire = data.expire; }
|
if (data.expire) { pad.expire = data.expire; }
|
||||||
|
if (data.password) { pad.password = data.password; }
|
||||||
|
if (data.channel) { pad.channel = data.channel; }
|
||||||
store.userObject.pushData(pad, function (e, id) {
|
store.userObject.pushData(pad, function (e, id) {
|
||||||
if (e) { return void cb({error: "Error while adding a template:"+ e}); }
|
if (e) { return void cb({error: "Error while adding a template:"+ e}); }
|
||||||
var path = data.path || ['root'];
|
var path = data.path || ['root'];
|
||||||
@ -433,14 +436,16 @@ define([
|
|||||||
// Push channels owned by someone else or channel that should have expired
|
// Push channels owned by someone else or channel that should have expired
|
||||||
// because of the expiration time
|
// because of the expiration time
|
||||||
if (data.owners && data.owners.length === 1 && data.owners.indexOf(edPublic) !== -1) {
|
if (data.owners && data.owners.length === 1 && data.owners.indexOf(edPublic) !== -1) {
|
||||||
list.push(Hash.hrefToHexChannelId(data.href));
|
list.push(data.channel);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (store.proxy.todo) {
|
if (store.proxy.todo) {
|
||||||
list.push(Hash.hrefToHexChannelId('/todo/#' + store.proxy.todo));
|
// No password for todo
|
||||||
|
list.push(Hash.hrefToHexChannelId('/todo/#' + store.proxy.todo, null));
|
||||||
}
|
}
|
||||||
if (store.proxy.profile && store.proxy.profile.edit) {
|
if (store.proxy.profile && store.proxy.profile.edit) {
|
||||||
list.push(Hash.hrefToHexChannelId('/profile/#' + store.proxy.profile.edit));
|
// No password for profile
|
||||||
|
list.push(Hash.hrefToHexChannelId('/profile/#' + store.proxy.profile.edit, null));
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
};
|
};
|
||||||
@ -461,6 +466,7 @@ define([
|
|||||||
|
|
||||||
Store.deleteAccount = function (data, cb) {
|
Store.deleteAccount = function (data, cb) {
|
||||||
var edPublic = store.proxy.edPublic;
|
var edPublic = store.proxy.edPublic;
|
||||||
|
// No password for drive
|
||||||
var secret = Hash.getSecrets('drive', storeHash);
|
var secret = Hash.getSecrets('drive', storeHash);
|
||||||
Store.anonRpcMsg({
|
Store.anonRpcMsg({
|
||||||
msg: 'GET_METADATA',
|
msg: 'GET_METADATA',
|
||||||
@ -524,25 +530,19 @@ define([
|
|||||||
*/
|
*/
|
||||||
Store.createReadme = function (data, cb) {
|
Store.createReadme = function (data, cb) {
|
||||||
require(['/common/cryptget.js'], function (Crypt) {
|
require(['/common/cryptget.js'], function (Crypt) {
|
||||||
var hash = Hash.createRandomHash();
|
var hash = Hash.createRandomHash('pad');
|
||||||
Crypt.put(hash, data.driveReadme, function (e) {
|
Crypt.put(hash, data.driveReadme, function (e) {
|
||||||
if (e) {
|
if (e) {
|
||||||
return void cb({ error: "Error while creating the default pad:"+ e});
|
return void cb({ error: "Error while creating the default pad:"+ e});
|
||||||
}
|
}
|
||||||
var href = '/pad/#' + hash;
|
var href = '/pad/#' + hash;
|
||||||
|
var channel = Hash.hrefToHexChannelId(href, null);
|
||||||
var fileData = {
|
var fileData = {
|
||||||
href: href,
|
href: href,
|
||||||
|
channel: channel,
|
||||||
title: data.driveReadmeTitle,
|
title: data.driveReadmeTitle,
|
||||||
atime: +new Date(),
|
|
||||||
ctime: +new Date()
|
|
||||||
};
|
};
|
||||||
store.userObject.pushData(fileData, function (e, id) {
|
Store.addPad(fileData, cb);
|
||||||
if (e) {
|
|
||||||
return void cb({ error: "Error while creating the default pad:"+ e});
|
|
||||||
}
|
|
||||||
store.userObject.add(id);
|
|
||||||
onSync(cb);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -679,20 +679,22 @@ define([
|
|||||||
Store.setPadTitle = function (data, cb) {
|
Store.setPadTitle = function (data, cb) {
|
||||||
var title = data.title;
|
var title = data.title;
|
||||||
var href = data.href;
|
var href = data.href;
|
||||||
|
var channel = data.channel;
|
||||||
var p = Hash.parsePadUrl(href);
|
var p = Hash.parsePadUrl(href);
|
||||||
var h = p.hashData;
|
var h = p.hashData;
|
||||||
|
|
||||||
if (AppConfig.disableAnonymousStore && !store.loggedIn) { return void cb(); }
|
if (AppConfig.disableAnonymousStore && !store.loggedIn) { return void cb(); }
|
||||||
|
|
||||||
var owners;
|
var owners;
|
||||||
if (Store.channel && Store.channel.wc && Util.base64ToHex(h.channel) === Store.channel.wc.id) {
|
if (Store.channel && Store.channel.wc && channel === Store.channel.wc.id) {
|
||||||
owners = Store.channel.data.owners || undefined;
|
owners = Store.channel.data.owners || undefined;
|
||||||
}
|
}
|
||||||
var expire;
|
var expire;
|
||||||
if (Store.channel && Store.channel.wc && Util.base64ToHex(h.channel) === Store.channel.wc.id) {
|
if (Store.channel && Store.channel.wc && channel === Store.channel.wc.id) {
|
||||||
expire = +Store.channel.data.expire || undefined;
|
expire = +Store.channel.data.expire || undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(owners, expire);
|
||||||
var allPads = Util.find(store.proxy, ['drive', 'filesData']) || {};
|
var allPads = Util.find(store.proxy, ['drive', 'filesData']) || {};
|
||||||
var isStronger;
|
var isStronger;
|
||||||
|
|
||||||
@ -712,13 +714,13 @@ define([
|
|||||||
// Different types, proceed to the next one
|
// Different types, proceed to the next one
|
||||||
// No hash data: corrupted pad?
|
// No hash data: corrupted pad?
|
||||||
if (p.type !== p2.type || !h2) { continue; }
|
if (p.type !== p2.type || !h2) { continue; }
|
||||||
|
// Different channel: continue
|
||||||
|
if (pad.channel !== channel) { continue; }
|
||||||
|
|
||||||
var shouldUpdate = p.hash.replace(/\/$/, '') === p2.hash.replace(/\/$/, '');
|
var shouldUpdate = p.hash.replace(/\/$/, '') === p2.hash.replace(/\/$/, '');
|
||||||
|
|
||||||
// If the hash is different but represents the same channel, check if weaker or stronger
|
// If the hash is different but represents the same channel, check if weaker or stronger
|
||||||
if (!shouldUpdate &&
|
if (!shouldUpdate && h.version !== 0) {
|
||||||
h.version === 1 && h2.version === 1 &&
|
|
||||||
h.channel === h2.channel) {
|
|
||||||
// We had view & now we have edit, update
|
// We had view & now we have edit, update
|
||||||
if (h2.mode === 'view' && h.mode === 'edit') { shouldUpdate = true; }
|
if (h2.mode === 'view' && h.mode === 'edit') { shouldUpdate = true; }
|
||||||
// Same mode and we had present URL, update
|
// Same mode and we had present URL, update
|
||||||
@ -755,10 +757,12 @@ define([
|
|||||||
if (!contains) {
|
if (!contains) {
|
||||||
Store.addPad({
|
Store.addPad({
|
||||||
href: href,
|
href: href,
|
||||||
|
channel: channel,
|
||||||
title: title,
|
title: title,
|
||||||
owners: owners,
|
owners: owners,
|
||||||
expire: expire,
|
expire: expire,
|
||||||
path: data.path || (store.data && store.data.initialPath)
|
password: data.password,
|
||||||
|
path: data.path
|
||||||
}, cb);
|
}, cb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -798,10 +802,7 @@ define([
|
|||||||
Store.getPadData = function (id, cb) {
|
Store.getPadData = function (id, cb) {
|
||||||
cb(store.userObject.getFileData(id));
|
cb(store.userObject.getFileData(id));
|
||||||
};
|
};
|
||||||
Store.setInitialPath = function (path) {
|
|
||||||
if (!store.data) { return; }
|
|
||||||
store.data.initialPath = path;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Messaging (manage friends from the userlist)
|
// Messaging (manage friends from the userlist)
|
||||||
var getMessagingCfg = function () {
|
var getMessagingCfg = function () {
|
||||||
@ -833,9 +834,9 @@ define([
|
|||||||
var allPads = Util.find(store.proxy, ['drive', 'filesData']) || {};
|
var allPads = Util.find(store.proxy, ['drive', 'filesData']) || {};
|
||||||
|
|
||||||
// If we have a stronger version in drive, add it and add a redirect button
|
// If we have a stronger version in drive, add it and add a redirect button
|
||||||
var stronger = Hash.findStronger(data.href, allPads);
|
var stronger = Hash.findStronger(data.href, data.channel, allPads);
|
||||||
if (stronger) {
|
if (stronger) {
|
||||||
var parsed2 = Hash.parsePadUrl(stronger);
|
var parsed2 = Hash.parsePadUrl(stronger.href);
|
||||||
return void cb(parsed2.hash);
|
return void cb(parsed2.hash);
|
||||||
}
|
}
|
||||||
cb();
|
cb();
|
||||||
@ -1123,11 +1124,12 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
var connect = function (data, cb) {
|
var connect = function (data, cb) {
|
||||||
var hash = data.userHash || data.anonHash || Hash.createRandomHash();
|
var hash = data.userHash || data.anonHash || Hash.createRandomHash('drive');
|
||||||
storeHash = hash;
|
storeHash = hash;
|
||||||
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...');
|
||||||
}
|
}
|
||||||
|
// No password for drive
|
||||||
var secret = Hash.getSecrets('drive', hash);
|
var secret = Hash.getSecrets('drive', hash);
|
||||||
var listmapConfig = {
|
var listmapConfig = {
|
||||||
data: {},
|
data: {},
|
||||||
@ -1150,7 +1152,7 @@ define([
|
|||||||
store.realtime = info.realtime;
|
store.realtime = info.realtime;
|
||||||
store.network = info.network;
|
store.network = info.network;
|
||||||
if (!data.userHash) {
|
if (!data.userHash) {
|
||||||
returned.anonHash = Hash.getEditHashFromKeys(info.channel, secret.keys);
|
returned.anonHash = Hash.getEditHashFromKeys(secret);
|
||||||
}
|
}
|
||||||
}).on('ready', function () {
|
}).on('ready', function () {
|
||||||
if (store.userObject) { return; } // the store is already ready, it is a reconnection
|
if (store.userObject) { return; } // the store is already ready, it is a reconnection
|
||||||
|
|||||||
@ -108,7 +108,7 @@ define([
|
|||||||
// Make sure we have an FS_hash in localStorage before reloading all the tabs
|
// Make sure we have an FS_hash in localStorage before reloading all the tabs
|
||||||
// so that we don't end up with tabs using different anon hashes
|
// so that we don't end up with tabs using different anon hashes
|
||||||
if (!LocalStore.getFSHash()) {
|
if (!LocalStore.getFSHash()) {
|
||||||
LocalStore.setFSHash(Hash.createRandomHash());
|
LocalStore.setFSHash(Hash.createRandomHash('drive'));
|
||||||
}
|
}
|
||||||
eraseTempSessionValues();
|
eraseTempSessionValues();
|
||||||
|
|
||||||
|
|||||||
@ -120,9 +120,6 @@ define([
|
|||||||
case 'GET_PAD_DATA': {
|
case 'GET_PAD_DATA': {
|
||||||
Store.getPadData(data, cb); break;
|
Store.getPadData(data, cb); break;
|
||||||
}
|
}
|
||||||
case 'SET_INITIAL_PATH': {
|
|
||||||
Store.setInitialPath(data); break;
|
|
||||||
}
|
|
||||||
case 'GET_STRONGER_HASH': {
|
case 'GET_STRONGER_HASH': {
|
||||||
Store.getStrongerHash(data, cb); break;
|
Store.getStrongerHash(data, cb); break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,14 +51,28 @@ define([
|
|||||||
|
|
||||||
var b64Key = Nacl.util.encodeBase64(key);
|
var b64Key = Nacl.util.encodeBase64(key);
|
||||||
|
|
||||||
var hash = Hash.getFileHashFromKeys(id, b64Key);
|
var secret = {
|
||||||
|
version: 1,
|
||||||
|
channel: id,
|
||||||
|
keys: {
|
||||||
|
fileKeyStr: b64Key
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var hash = Hash.getFileHashFromKeys(secret);
|
||||||
var href = '/file/#' + hash;
|
var href = '/file/#' + hash;
|
||||||
|
|
||||||
var title = metadata.name;
|
var title = metadata.name;
|
||||||
|
|
||||||
if (noStore) { return void onComplete(href); }
|
if (noStore) { return void onComplete(href); }
|
||||||
|
|
||||||
common.setPadTitle(title || "", href, path, function (err) {
|
// PASSWORD_FILES
|
||||||
|
var data = {
|
||||||
|
title: title || "",
|
||||||
|
href: href,
|
||||||
|
path: path,
|
||||||
|
channel: id
|
||||||
|
};
|
||||||
|
common.setPadTitle(data, function (err) {
|
||||||
if (err) { return void console.error(err); }
|
if (err) { return void console.error(err); }
|
||||||
onComplete(href);
|
onComplete(href);
|
||||||
common.setPadAttribute('fileType', metadata.type, null, href);
|
common.setPadAttribute('fileType', metadata.type, null, href);
|
||||||
|
|||||||
@ -75,7 +75,7 @@ define([
|
|||||||
return void todo();
|
return void todo();
|
||||||
}
|
}
|
||||||
if (!pinPads) { return; }
|
if (!pinPads) { return; }
|
||||||
pinPads([Hash.hrefToHexChannelId(data.href)], function (obj) {
|
pinPads([data.channel], function (obj) {
|
||||||
if (obj && obj.error) { return void cb(obj.error); }
|
if (obj && obj.error) { return void cb(obj.error); }
|
||||||
todo();
|
todo();
|
||||||
});
|
});
|
||||||
@ -98,7 +98,7 @@ define([
|
|||||||
exp.getFiles([FILES_DATA]).forEach(function (id) {
|
exp.getFiles([FILES_DATA]).forEach(function (id) {
|
||||||
if (filesList.indexOf(id) === -1) {
|
if (filesList.indexOf(id) === -1) {
|
||||||
var fd = exp.getFileData(id);
|
var fd = exp.getFileData(id);
|
||||||
var channelId = fd && fd.href && Hash.hrefToHexChannelId(fd.href);
|
var channelId = fd.channel;
|
||||||
// If trying to remove an owned pad, remove it from server also
|
// If trying to remove an owned pad, remove it from server also
|
||||||
if (!isOwnPadRemoved &&
|
if (!isOwnPadRemoved &&
|
||||||
fd.owners && fd.owners.indexOf(edPublic) !== -1 && channelId) {
|
fd.owners && fd.owners.indexOf(edPublic) !== -1 && channelId) {
|
||||||
@ -552,32 +552,52 @@ define([
|
|||||||
for (var id in fd) {
|
for (var id in fd) {
|
||||||
id = Number(id);
|
id = Number(id);
|
||||||
var el = fd[id];
|
var el = fd[id];
|
||||||
|
|
||||||
|
// Clean corrupted data
|
||||||
if (!el || typeof(el) !== "object") {
|
if (!el || typeof(el) !== "object") {
|
||||||
debug("An element in filesData was not an object.", el);
|
debug("An element in filesData was not an object.", el);
|
||||||
toClean.push(id);
|
toClean.push(id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Clean missing href
|
||||||
if (!el.href) {
|
if (!el.href) {
|
||||||
debug("Removing an element in filesData with a missing href.", el);
|
debug("Removing an element in filesData with a missing href.", el);
|
||||||
toClean.push(id);
|
toClean.push(id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (/^https*:\/\//.test(el.href)) { el.href = Hash.getRelativeHref(el.href); }
|
|
||||||
if (!el.ctime) { el.ctime = el.atime; }
|
|
||||||
|
|
||||||
var parsed = Hash.parsePadUrl(el.href);
|
var parsed = Hash.parsePadUrl(el.href);
|
||||||
if (!el.title) { el.title = Hash.getDefaultName(parsed); }
|
// Clean invalid hash
|
||||||
if (!parsed.hash) {
|
if (!parsed.hash) {
|
||||||
debug("Removing an element in filesData with a invalid href.", el);
|
debug("Removing an element in filesData with a invalid href.", el);
|
||||||
toClean.push(id);
|
toClean.push(id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Clean invalid type
|
||||||
if (!parsed.type) {
|
if (!parsed.type) {
|
||||||
debug("Removing an element in filesData with a invalid type.", el);
|
debug("Removing an element in filesData with a invalid type.", el);
|
||||||
toClean.push(id);
|
toClean.push(id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix href
|
||||||
|
if (/^https*:\/\//.test(el.href)) { el.href = Hash.getRelativeHref(el.href); }
|
||||||
|
// Fix creation time
|
||||||
|
if (!el.ctime) { el.ctime = el.atime; }
|
||||||
|
// Fix title
|
||||||
|
if (!el.title) { el.title = Hash.getDefaultName(parsed); }
|
||||||
|
// Fix channel
|
||||||
|
if (!el.channel) {
|
||||||
|
if (parsed.hashData && parsed.hashData.type === "file") {
|
||||||
|
// PASSWORD_FILES
|
||||||
|
el.channel = Util.base64ToHex(parsed.hashData.channel);
|
||||||
|
} else {
|
||||||
|
var secret = Hash.getSecrets(parsed.type, parsed.hash, el.password);
|
||||||
|
el.channel = secret.channel;
|
||||||
|
}
|
||||||
|
console.log('Adding missing channel in filesData ', el.channel);
|
||||||
|
}
|
||||||
|
|
||||||
if ((loggedIn || config.testMode) && rootFiles.indexOf(id) === -1) {
|
if ((loggedIn || config.testMode) && rootFiles.indexOf(id) === -1) {
|
||||||
debug("An element in filesData was not in ROOT, TEMPLATE or TRASH.", id, el);
|
debug("An element in filesData was not in ROOT, TEMPLATE or TRASH.", id, el);
|
||||||
var newName = Hash.createChannelId();
|
var newName = Hash.createChannelId();
|
||||||
|
|||||||
@ -315,8 +315,7 @@ define([
|
|||||||
privateDat.availableHashes.viewHash;
|
privateDat.availableHashes.viewHash;
|
||||||
var href = privateDat.pathname + '#' + hash;
|
var href = privateDat.pathname + '#' + hash;
|
||||||
if (AppConfig.textAnalyzer && textContentGetter) {
|
if (AppConfig.textAnalyzer && textContentGetter) {
|
||||||
var channelId = Hash.hrefToHexChannelId(href);
|
AppConfig.textAnalyzer(textContentGetter, privateDat.channel);
|
||||||
AppConfig.textAnalyzer(textContentGetter, channelId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.thumbnail && privateDat.thumbnails) {
|
if (options.thumbnail && privateDat.thumbnails) {
|
||||||
|
|||||||
@ -332,6 +332,7 @@ define([
|
|||||||
//var cursor = editor.getCursor();
|
//var cursor = editor.getCursor();
|
||||||
//var cleanName = data.name.replace(/[\[\]]/g, '');
|
//var cleanName = data.name.replace(/[\[\]]/g, '');
|
||||||
//var text = '';
|
//var text = '';
|
||||||
|
// PASSWORD_FILES
|
||||||
var parsed = Hash.parsePadUrl(data.url);
|
var parsed = Hash.parsePadUrl(data.url);
|
||||||
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
||||||
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
||||||
|
|||||||
@ -24,6 +24,8 @@ define([
|
|||||||
var Utils = {};
|
var Utils = {};
|
||||||
var AppConfig;
|
var AppConfig;
|
||||||
var Test;
|
var Test;
|
||||||
|
var password;
|
||||||
|
var initialPathInDrive;
|
||||||
|
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
// Load #2, the loading screen is up so grab whatever you need...
|
// Load #2, the loading screen is up so grab whatever you need...
|
||||||
@ -113,6 +115,7 @@ define([
|
|||||||
|
|
||||||
if (cfg.getSecrets) {
|
if (cfg.getSecrets) {
|
||||||
var w = waitFor();
|
var w = waitFor();
|
||||||
|
// No password for drive, profile and todo
|
||||||
cfg.getSecrets(Cryptpad, Utils, waitFor(function (err, s) {
|
cfg.getSecrets(Cryptpad, Utils, waitFor(function (err, s) {
|
||||||
secret = s;
|
secret = s;
|
||||||
Cryptpad.getShareHashes(secret, function (err, h) {
|
Cryptpad.getShareHashes(secret, function (err, h) {
|
||||||
@ -121,19 +124,54 @@ define([
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
secret = Utils.Hash.getSecrets();
|
var parsed = Utils.Hash.parsePadUrl(window.location.href);
|
||||||
if (!secret.channel) {
|
var todo = function () {
|
||||||
// New pad: create a new random channel id
|
secret = Utils.Hash.getSecrets(parsed.type, void 0, password);
|
||||||
secret.channel = Utils.Hash.createChannelId();
|
|
||||||
}
|
|
||||||
Cryptpad.getShareHashes(secret, waitFor(function (err, h) { hashes = h; }));
|
Cryptpad.getShareHashes(secret, waitFor(function (err, h) { hashes = h; }));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prompt the password here if we have a hash containing /p/
|
||||||
|
// or get it from the pad attributes
|
||||||
|
var needPassword = parsed.hashData && parsed.hashData.password;
|
||||||
|
if (needPassword) {
|
||||||
|
Cryptpad.getPadAttribute('password', waitFor(function (err, val) {
|
||||||
|
if (val) {
|
||||||
|
// We already know the password, use it!
|
||||||
|
password = val;
|
||||||
|
todo();
|
||||||
|
} else {
|
||||||
|
// Ask for the password and check if the pad exists
|
||||||
|
// If the pad doesn't exist, it means the password is oncorrect
|
||||||
|
// or the pad has been deleted
|
||||||
|
var correctPassword = waitFor();
|
||||||
|
sframeChan.on('Q_PAD_PASSWORD_VALUE', function (data, cb) {
|
||||||
|
password = data;
|
||||||
|
Cryptpad.isNewChannel(window.location.href, password, function (e, isNew) {
|
||||||
|
if (Boolean(isNew)) {
|
||||||
|
// Ask again in the inner iframe
|
||||||
|
// We should receive a new Q_PAD_PASSWORD_VALUE
|
||||||
|
cb(false);
|
||||||
|
} else {
|
||||||
|
todo();
|
||||||
|
correctPassword();
|
||||||
|
cb(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
sframeChan.event("EV_PAD_PASSWORD");
|
||||||
|
}
|
||||||
|
}), parsed.getUrl());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If no password, continue...
|
||||||
|
todo();
|
||||||
}
|
}
|
||||||
}).nThen(function (waitFor) {
|
}).nThen(function (waitFor) {
|
||||||
// Check if the pad exists on server
|
// Check if the pad exists on server
|
||||||
if (!window.location.hash) { isNewFile = true; return; }
|
if (!window.location.hash) { isNewFile = true; return; }
|
||||||
|
|
||||||
if (realtime) {
|
if (realtime) {
|
||||||
Cryptpad.isNewChannel(window.location.href, waitFor(function (e, isNew) {
|
Cryptpad.isNewChannel(window.location.href, password, waitFor(function (e, isNew) {
|
||||||
if (e) { return console.error(e); }
|
if (e) { return console.error(e); }
|
||||||
isNewFile = Boolean(isNew);
|
isNewFile = Boolean(isNew);
|
||||||
}));
|
}));
|
||||||
@ -188,7 +226,9 @@ define([
|
|||||||
},
|
},
|
||||||
isNewFile: isNewFile,
|
isNewFile: isNewFile,
|
||||||
isDeleted: isNewFile && window.location.hash.length > 0,
|
isDeleted: isNewFile && window.location.hash.length > 0,
|
||||||
forceCreationScreen: forceCreationScreen
|
forceCreationScreen: forceCreationScreen,
|
||||||
|
password: password,
|
||||||
|
channel: secret.channel
|
||||||
};
|
};
|
||||||
for (var k in additionalPriv) { metaObj.priv[k] = additionalPriv[k]; }
|
for (var k in additionalPriv) { metaObj.priv[k] = additionalPriv[k]; }
|
||||||
|
|
||||||
@ -256,7 +296,13 @@ define([
|
|||||||
sframeChan.on('Q_SET_PAD_TITLE_IN_DRIVE', function (newTitle, cb) {
|
sframeChan.on('Q_SET_PAD_TITLE_IN_DRIVE', function (newTitle, cb) {
|
||||||
currentTitle = newTitle;
|
currentTitle = newTitle;
|
||||||
setDocumentTitle();
|
setDocumentTitle();
|
||||||
Cryptpad.setPadTitle(newTitle, undefined, undefined, function (err) {
|
var data = {
|
||||||
|
password: password,
|
||||||
|
title: newTitle,
|
||||||
|
channel: secret.channel,
|
||||||
|
path: initialPathInDrive // Where to store the pad if we don't have it in our drive
|
||||||
|
};
|
||||||
|
Cryptpad.setPadTitle(data, function (err) {
|
||||||
cb(err);
|
cb(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -473,9 +519,9 @@ define([
|
|||||||
cb(templates.length > 0);
|
cb(templates.length > 0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
var getKey = function (href) {
|
var getKey = function (href, channel) {
|
||||||
var parsed = Utils.Hash.parsePadUrl(href);
|
var parsed = Utils.Hash.parsePadUrl(href);
|
||||||
return 'thumbnail-' + parsed.type + '-' + parsed.hashData.channel;
|
return 'thumbnail-' + parsed.type + '-' + channel;
|
||||||
};
|
};
|
||||||
sframeChan.on('Q_CREATE_TEMPLATES', function (type, cb) {
|
sframeChan.on('Q_CREATE_TEMPLATES', function (type, cb) {
|
||||||
Cryptpad.getSecureFilesList({
|
Cryptpad.getSecureFilesList({
|
||||||
@ -488,7 +534,7 @@ define([
|
|||||||
var res = [];
|
var res = [];
|
||||||
nThen(function (waitFor) {
|
nThen(function (waitFor) {
|
||||||
Object.keys(data).map(function (el) {
|
Object.keys(data).map(function (el) {
|
||||||
var k = getKey(data[el].href);
|
var k = getKey(data[el].href, data[el].channel);
|
||||||
Utils.LocalStore.getThumbnail(k, waitFor(function (e, thumb) {
|
Utils.LocalStore.getThumbnail(k, waitFor(function (e, thumb) {
|
||||||
res.push({
|
res.push({
|
||||||
id: el,
|
id: el,
|
||||||
@ -635,7 +681,7 @@ define([
|
|||||||
isNewHash: isNewHash,
|
isNewHash: isNewHash,
|
||||||
readOnly: readOnly,
|
readOnly: readOnly,
|
||||||
crypto: Crypto.createEncryptor(secret.keys),
|
crypto: Crypto.createEncryptor(secret.keys),
|
||||||
onConnect: function (wc) {
|
onConnect: function () {
|
||||||
if (window.location.hash && window.location.hash !== '#') {
|
if (window.location.hash && window.location.hash !== '#') {
|
||||||
window.location = parsed.getUrl({
|
window.location = parsed.getUrl({
|
||||||
present: parsed.hashData.present,
|
present: parsed.hashData.present,
|
||||||
@ -644,7 +690,7 @@ define([
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (readOnly || cfg.noHash) { return; }
|
if (readOnly || cfg.noHash) { return; }
|
||||||
replaceHash(Utils.Hash.getEditHashFromKeys(wc, secret.keys));
|
replaceHash(Utils.Hash.getEditHashFromKeys(secret));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -671,8 +717,9 @@ define([
|
|||||||
sframeChan.on('Q_CREATE_PAD', function (data, cb) {
|
sframeChan.on('Q_CREATE_PAD', function (data, cb) {
|
||||||
if (!isNewFile || rtStarted) { return; }
|
if (!isNewFile || rtStarted) { return; }
|
||||||
// Create a new hash
|
// Create a new hash
|
||||||
var newHash = Utils.Hash.createRandomHash();
|
password = data.password;
|
||||||
secret = Utils.Hash.getSecrets(parsed.type, newHash);
|
var newHash = Utils.Hash.createRandomHash(parsed.type, password);
|
||||||
|
secret = Utils.Hash.getSecrets(parsed.type, newHash, password);
|
||||||
|
|
||||||
// Update the hash in the address bar
|
// Update the hash in the address bar
|
||||||
var ohc = window.onhashchange;
|
var ohc = window.onhashchange;
|
||||||
@ -684,7 +731,7 @@ define([
|
|||||||
// Update metadata values and send new metadata inside
|
// Update metadata values and send new metadata inside
|
||||||
parsed = Utils.Hash.parsePadUrl(window.location.href);
|
parsed = Utils.Hash.parsePadUrl(window.location.href);
|
||||||
defaultTitle = Utils.Hash.getDefaultName(parsed);
|
defaultTitle = Utils.Hash.getDefaultName(parsed);
|
||||||
hashes = Utils.Hash.getHashes(secret.channel, secret);
|
hashes = Utils.Hash.getHashes(secret);
|
||||||
readOnly = false;
|
readOnly = false;
|
||||||
updateMeta();
|
updateMeta();
|
||||||
|
|
||||||
@ -698,7 +745,7 @@ define([
|
|||||||
nThen(function(waitFor) {
|
nThen(function(waitFor) {
|
||||||
if (data.templateId) {
|
if (data.templateId) {
|
||||||
if (data.templateId === -1) {
|
if (data.templateId === -1) {
|
||||||
Cryptpad.setInitialPath(['template']);
|
initialPathInDrive = ['template'];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Cryptpad.getPadData(data.templateId, waitFor(function (err, d) {
|
Cryptpad.getPadData(data.templateId, waitFor(function (err, d) {
|
||||||
|
|||||||
@ -113,6 +113,7 @@ define([
|
|||||||
return '<script src="' + origin + '/common/media-tag-nacl.min.js"></script>';
|
return '<script src="' + origin + '/common/media-tag-nacl.min.js"></script>';
|
||||||
};
|
};
|
||||||
funcs.getMediatagFromHref = function (href) {
|
funcs.getMediatagFromHref = function (href) {
|
||||||
|
// PASSWORD_FILES
|
||||||
var parsed = Hash.parsePadUrl(href);
|
var parsed = Hash.parsePadUrl(href);
|
||||||
var secret = Hash.getSecrets('file', parsed.hash);
|
var secret = Hash.getSecrets('file', parsed.hash);
|
||||||
var data = ctx.metadataMgr.getPrivateData();
|
var data = ctx.metadataMgr.getPrivateData();
|
||||||
@ -126,8 +127,7 @@ define([
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
funcs.getFileSize = function (href, cb) {
|
funcs.getFileSize = function (channelId, cb) {
|
||||||
var channelId = Hash.hrefToHexChannelId(href);
|
|
||||||
funcs.sendAnonRpcMsg("GET_FILE_SIZE", channelId, function (data) {
|
funcs.sendAnonRpcMsg("GET_FILE_SIZE", channelId, function (data) {
|
||||||
if (!data) { return void cb("No response"); }
|
if (!data) { return void cb("No response"); }
|
||||||
if (data.error) { return void cb(data.error); }
|
if (data.error) { return void cb(data.error); }
|
||||||
@ -197,6 +197,7 @@ define([
|
|||||||
ctx.sframeChan.query("Q_CREATE_PAD", {
|
ctx.sframeChan.query("Q_CREATE_PAD", {
|
||||||
owned: cfg.owned,
|
owned: cfg.owned,
|
||||||
expire: cfg.expire,
|
expire: cfg.expire,
|
||||||
|
password: cfg.password,
|
||||||
template: cfg.template,
|
template: cfg.template,
|
||||||
templateId: cfg.templateId
|
templateId: cfg.templateId
|
||||||
}, cb);
|
}, cb);
|
||||||
@ -378,6 +379,7 @@ define([
|
|||||||
Object.freeze(funcs);
|
Object.freeze(funcs);
|
||||||
return { create: function (cb) {
|
return { create: function (cb) {
|
||||||
|
|
||||||
|
console.log('create');
|
||||||
if (window.CryptPad_sframe_common) {
|
if (window.CryptPad_sframe_common) {
|
||||||
throw new Error("Sframe-common should only be created once");
|
throw new Error("Sframe-common should only be created once");
|
||||||
}
|
}
|
||||||
@ -428,6 +430,10 @@ define([
|
|||||||
UI.log(data.logText);
|
UI.log(data.logText);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ctx.sframeChan.on("EV_PAD_PASSWORD", function () {
|
||||||
|
UIElements.displayPasswordPrompt(funcs);
|
||||||
|
});
|
||||||
|
|
||||||
ctx.metadataMgr.onReady(waitFor());
|
ctx.metadataMgr.onReady(waitFor());
|
||||||
}).nThen(function () {
|
}).nThen(function () {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -230,4 +230,8 @@ define({
|
|||||||
|
|
||||||
// Critical error outside the iframe during loading screen
|
// Critical error outside the iframe during loading screen
|
||||||
'EV_LOADING_ERROR': true,
|
'EV_LOADING_ERROR': true,
|
||||||
|
|
||||||
|
// Ask for the pad password when a pad is protected
|
||||||
|
'EV_PAD_PASSWORD': true,
|
||||||
|
'Q_PAD_PASSWORD_VALUE': true,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -577,8 +577,7 @@ define([
|
|||||||
var pd = config.metadataMgr.getPrivateData();
|
var pd = config.metadataMgr.getPrivateData();
|
||||||
var o = pd.origin;
|
var o = pd.origin;
|
||||||
var hashes = pd.availableHashes;
|
var hashes = pd.availableHashes;
|
||||||
var url = pd.origin + pd.pathname + '#' + (hashes.editHash || hashes.viewHash);
|
var cid = pd.channel;
|
||||||
var cid = Hash.hrefToHexChannelId(url);
|
|
||||||
Common.sendAnonRpcMsg('IS_CHANNEL_PINNED', cid, function (x) {
|
Common.sendAnonRpcMsg('IS_CHANNEL_PINNED', cid, function (x) {
|
||||||
if (x.error || !Array.isArray(x.response)) { return void console.log(x); }
|
if (x.error || !Array.isArray(x.response)) { return void console.log(x); }
|
||||||
if (x.response[0] === true) {
|
if (x.response[0] === true) {
|
||||||
|
|||||||
@ -384,11 +384,9 @@ define([
|
|||||||
// Get drive ids of files from their channel ids
|
// Get drive ids of files from their channel ids
|
||||||
exp.findChannels = function (channels) {
|
exp.findChannels = function (channels) {
|
||||||
var allFilesList = files[FILES_DATA];
|
var allFilesList = files[FILES_DATA];
|
||||||
var channels64 = channels.slice().map(Util.hexToBase64);
|
|
||||||
return getFiles([FILES_DATA]).filter(function (k) {
|
return getFiles([FILES_DATA]).filter(function (k) {
|
||||||
var data = allFilesList[k];
|
var data = allFilesList[k];
|
||||||
var parsed = Hash.parsePadUrl(data.href);
|
return channels.indexOf(data.channel) !== -1;
|
||||||
return parsed.hashData && channels64.indexOf(parsed.hashData.channel) !== -1;
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1296,7 +1296,7 @@ define([
|
|||||||
$span.attr('title', name);
|
$span.attr('title', name);
|
||||||
|
|
||||||
var type = Messages.type[hrefData.type] || hrefData.type;
|
var type = Messages.type[hrefData.type] || hrefData.type;
|
||||||
common.displayThumbnail(data.href, $span, function ($thumb) {
|
common.displayThumbnail(data.href, data.channel, $span, function ($thumb) {
|
||||||
// Called only if the thumbnail exists
|
// Called only if the thumbnail exists
|
||||||
// Remove the .hide() added by displayThumnail() because it hides the icon in
|
// Remove the .hide() added by displayThumnail() because it hides the icon in
|
||||||
// list mode too
|
// list mode too
|
||||||
@ -2653,9 +2653,9 @@ define([
|
|||||||
if (parsed.hashData.type !== "pad") { return; }
|
if (parsed.hashData.type !== "pad") { return; }
|
||||||
var i = data.href.indexOf('#') + 1;
|
var i = data.href.indexOf('#') + 1;
|
||||||
var base = data.href.slice(0, i);
|
var base = data.href.slice(0, i);
|
||||||
var hrefsecret = Hash.getSecrets(parsed.type, parsed.hash);
|
var hrefsecret = Hash.getSecrets(parsed.type, parsed.hash, data.password);
|
||||||
if (!hrefsecret.keys) { return; }
|
if (!hrefsecret.keys) { return; }
|
||||||
var viewHash = Hash.getViewHashFromKeys(hrefsecret.channel, hrefsecret.keys);
|
var viewHash = Hash.getViewHashFromKeys(hrefsecret);
|
||||||
return base + viewHash;
|
return base + viewHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2720,24 +2720,6 @@ define([
|
|||||||
$(window).focus();
|
$(window).focus();
|
||||||
if (!res) { return; }
|
if (!res) { return; }
|
||||||
filesOp.delete(pathsList, refresh);
|
filesOp.delete(pathsList, refresh);
|
||||||
/*
|
|
||||||
// Try to delete each selected pad from server, and delete from drive if no error
|
|
||||||
var n = nThen(function () {});
|
|
||||||
pathsList.forEach(function (p) {
|
|
||||||
var el = filesOp.find(p);
|
|
||||||
var data = filesOp.getFileData(el);
|
|
||||||
var parsed = Hash.parsePadUrl(data.href);
|
|
||||||
var channel = Util.base64ToHex(parsed.hashData.channel);
|
|
||||||
n = n.nThen(function (waitFor) {
|
|
||||||
sframeChan.query('Q_REMOVE_OWNED_CHANNEL', channel,
|
|
||||||
waitFor(function (e) {
|
|
||||||
if (e) { return void console.error(e); }
|
|
||||||
filesOp.delete([p], function () {}, false, true);
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
n.nThen(function () { refresh(); });
|
|
||||||
*/
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
$contextMenu.on("click", "a", function(e) {
|
$contextMenu.on("click", "a", function(e) {
|
||||||
|
|||||||
@ -39,6 +39,7 @@ define([
|
|||||||
var getSecrets = function (Cryptpad, Utils, cb) {
|
var getSecrets = function (Cryptpad, Utils, cb) {
|
||||||
var hash = window.location.hash.slice(1) || Utils.LocalStore.getUserHash() ||
|
var hash = window.location.hash.slice(1) || Utils.LocalStore.getUserHash() ||
|
||||||
Utils.LocalStore.getFSHash();
|
Utils.LocalStore.getFSHash();
|
||||||
|
// No password for drive
|
||||||
cb(null, Utils.Hash.getSecrets('drive', hash));
|
cb(null, Utils.Hash.getSecrets('drive', hash));
|
||||||
};
|
};
|
||||||
var addRpc = function (sframeChan, Cryptpad, Utils) {
|
var addRpc = function (sframeChan, Cryptpad, Utils) {
|
||||||
|
|||||||
@ -61,6 +61,7 @@ define([
|
|||||||
if (!priv.filehash) {
|
if (!priv.filehash) {
|
||||||
uploadMode = true;
|
uploadMode = true;
|
||||||
} else {
|
} else {
|
||||||
|
// PASSWORD_FILES
|
||||||
secret = Hash.getSecrets('file', priv.filehash);
|
secret = Hash.getSecrets('file', priv.filehash);
|
||||||
if (!secret.keys) { throw new Error("You need a hash"); }
|
if (!secret.keys) { throw new Error("You need a hash"); }
|
||||||
hexFileName = Util.base64ToHex(secret.channel);
|
hexFileName = Util.base64ToHex(secret.channel);
|
||||||
@ -233,8 +234,7 @@ define([
|
|||||||
if (typeof(sizeMb) === 'number' && sizeMb < 5) { return void onClick(); }
|
if (typeof(sizeMb) === 'number' && sizeMb < 5) { return void onClick(); }
|
||||||
$dlform.find('#cp-app-file-dlfile, #cp-app-file-dlprogress').click(onClick);
|
$dlform.find('#cp-app-file-dlfile, #cp-app-file-dlprogress').click(onClick);
|
||||||
};
|
};
|
||||||
var href = priv.origin + priv.pathname + priv.filehash;
|
common.getFileSize(hexFileName, function (e, data) {
|
||||||
common.getFileSize(href, function (e, data) {
|
|
||||||
if (e) {
|
if (e) {
|
||||||
return void UI.errorLoadingScreen(e);
|
return void UI.errorLoadingScreen(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,7 @@ define([
|
|||||||
var parsed = Hash.parsePadUrl(data.url);
|
var parsed = Hash.parsePadUrl(data.url);
|
||||||
hideFileDialog();
|
hideFileDialog();
|
||||||
if (parsed.type === 'file') {
|
if (parsed.type === 'file') {
|
||||||
|
// PASSWORD_FILES
|
||||||
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
||||||
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
||||||
sframeChan.event("EV_FILE_PICKED", {
|
sframeChan.event("EV_FILE_PICKED", {
|
||||||
@ -138,7 +139,7 @@ define([
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Add thumbnail if it exists
|
// Add thumbnail if it exists
|
||||||
common.displayThumbnail(data.href, $span);
|
common.displayThumbnail(data.href, data.channel, $span);
|
||||||
});
|
});
|
||||||
$input.focus();
|
$input.focus();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -552,6 +552,7 @@ define([
|
|||||||
ckeditor: editor,
|
ckeditor: editor,
|
||||||
body: $('body'),
|
body: $('body'),
|
||||||
onUploaded: function (ev, data) {
|
onUploaded: function (ev, data) {
|
||||||
|
// PASSWORD_FILES
|
||||||
var parsed = Hash.parsePadUrl(data.url);
|
var parsed = Hash.parsePadUrl(data.url);
|
||||||
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
||||||
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
||||||
|
|||||||
@ -2,7 +2,6 @@ define([
|
|||||||
'jquery',
|
'jquery',
|
||||||
'/common/toolbar3.js',
|
'/common/toolbar3.js',
|
||||||
'/common/common-util.js',
|
'/common/common-util.js',
|
||||||
'/common/cryptget.js',
|
|
||||||
'/bower_components/nthen/index.js',
|
'/bower_components/nthen/index.js',
|
||||||
'/common/sframe-common.js',
|
'/common/sframe-common.js',
|
||||||
'/common/common-realtime.js',
|
'/common/common-realtime.js',
|
||||||
@ -32,7 +31,6 @@ define([
|
|||||||
$,
|
$,
|
||||||
Toolbar,
|
Toolbar,
|
||||||
Util,
|
Util,
|
||||||
Cryptget,
|
|
||||||
nThen,
|
nThen,
|
||||||
SFCommon,
|
SFCommon,
|
||||||
CommonRealtime,
|
CommonRealtime,
|
||||||
|
|||||||
@ -40,6 +40,7 @@ define([
|
|||||||
var Hash = Utils.Hash;
|
var Hash = Utils.Hash;
|
||||||
// 1st case: visiting someone else's profile with hash in the URL
|
// 1st case: visiting someone else's profile with hash in the URL
|
||||||
if (window.location.hash) {
|
if (window.location.hash) {
|
||||||
|
// No password for profiles
|
||||||
return void cb(null, Hash.getSecrets('profile', window.location.hash.slice(1)));
|
return void cb(null, Hash.getSecrets('profile', window.location.hash.slice(1)));
|
||||||
}
|
}
|
||||||
var editHash;
|
var editHash;
|
||||||
@ -50,6 +51,7 @@ define([
|
|||||||
}));
|
}));
|
||||||
}).nThen(function () {
|
}).nThen(function () {
|
||||||
if (editHash) {
|
if (editHash) {
|
||||||
|
// No password for profile
|
||||||
return void cb(null, Hash.getSecrets('profile', editHash));
|
return void cb(null, Hash.getSecrets('profile', editHash));
|
||||||
}
|
}
|
||||||
// 3rd case: profile creation (create a new random hash, store it later if needed)
|
// 3rd case: profile creation (create a new random hash, store it later if needed)
|
||||||
@ -58,7 +60,8 @@ define([
|
|||||||
window.location.href = '/drive/';
|
window.location.href = '/drive/';
|
||||||
return void cb();
|
return void cb();
|
||||||
}
|
}
|
||||||
var hash = Hash.createRandomHash();
|
// No password for profile
|
||||||
|
var hash = Hash.createRandomHash('profile');
|
||||||
var secret = Hash.getSecrets('profile', hash);
|
var secret = Hash.getSecrets('profile', hash);
|
||||||
Cryptpad.pinPads([secret.channel], function (e) {
|
Cryptpad.pinPads([secret.channel], function (e) {
|
||||||
if (e) {
|
if (e) {
|
||||||
@ -69,8 +72,8 @@ define([
|
|||||||
//return void UI.log(Messages._getKey('profile_error', [e])) // TODO
|
//return void UI.log(Messages._getKey('profile_error', [e])) // TODO
|
||||||
}
|
}
|
||||||
var profile = {};
|
var profile = {};
|
||||||
profile.edit = Utils.Hash.getEditHashFromKeys(secret.channel, secret.keys);
|
profile.edit = Utils.Hash.getEditHashFromKeys(secret);
|
||||||
profile.view = Utils.Hash.getViewHashFromKeys(secret.channel, secret.keys);
|
profile.view = Utils.Hash.getViewHashFromKeys(secret);
|
||||||
Cryptpad.setNewProfile(profile);
|
Cryptpad.setNewProfile(profile);
|
||||||
});
|
});
|
||||||
cb(null, secret);
|
cb(null, secret);
|
||||||
@ -79,7 +82,7 @@ define([
|
|||||||
var addRpc = function (sframeChan, Cryptpad, Utils) {
|
var addRpc = function (sframeChan, Cryptpad, Utils) {
|
||||||
// Adding a new avatar from the profile: pin it and store it in the object
|
// Adding a new avatar from the profile: pin it and store it in the object
|
||||||
sframeChan.on('Q_PROFILE_AVATAR_ADD', function (data, cb) {
|
sframeChan.on('Q_PROFILE_AVATAR_ADD', function (data, cb) {
|
||||||
var chanId = Utils.Hash.hrefToHexChannelId(data);
|
var chanId = Utils.Hash.hrefToHexChannelId(data, null);
|
||||||
Cryptpad.pinPads([chanId], function (e) {
|
Cryptpad.pinPads([chanId], function (e) {
|
||||||
if (e) { return void cb(e); }
|
if (e) { return void cb(e); }
|
||||||
Cryptpad.setAvatar(data, cb);
|
Cryptpad.setAvatar(data, cb);
|
||||||
@ -87,7 +90,7 @@ define([
|
|||||||
});
|
});
|
||||||
// Removing the avatar from the profile: unpin it
|
// Removing the avatar from the profile: unpin it
|
||||||
sframeChan.on('Q_PROFILE_AVATAR_REMOVE', function (data, cb) {
|
sframeChan.on('Q_PROFILE_AVATAR_REMOVE', function (data, cb) {
|
||||||
var chanId = Utils.Hash.hrefToHexChannelId(data);
|
var chanId = Utils.Hash.hrefToHexChannelId(data, null);
|
||||||
Cryptpad.unpinPads([chanId], function () {
|
Cryptpad.unpinPads([chanId], function () {
|
||||||
Cryptpad.setAvatar(undefined, cb);
|
Cryptpad.setAvatar(undefined, cb);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -500,9 +500,7 @@ define([
|
|||||||
dropArea: $('.CodeMirror'),
|
dropArea: $('.CodeMirror'),
|
||||||
body: $('body'),
|
body: $('body'),
|
||||||
onUploaded: function (ev, data) {
|
onUploaded: function (ev, data) {
|
||||||
//var cursor = editor.getCursor();
|
// PASSWORD_FILES
|
||||||
//var cleanName = data.name.replace(/[\[\]]/g, '');
|
|
||||||
//var text = '';
|
|
||||||
var parsed = Hash.parsePadUrl(data.url);
|
var parsed = Hash.parsePadUrl(data.url);
|
||||||
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
|
||||||
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
|
||||||
|
|||||||
@ -38,7 +38,8 @@ define([
|
|||||||
}).nThen(function (/*waitFor*/) {
|
}).nThen(function (/*waitFor*/) {
|
||||||
var getSecrets = function (Cryptpad, Utils, cb) {
|
var getSecrets = function (Cryptpad, Utils, cb) {
|
||||||
Cryptpad.getTodoHash(function (hash) {
|
Cryptpad.getTodoHash(function (hash) {
|
||||||
var nHash = hash || Utils.Hash.createRandomHash();
|
// No password for todo
|
||||||
|
var nHash = hash || Utils.Hash.createRandomHash('todo');
|
||||||
if (!hash) { Cryptpad.setTodoHash(nHash); }
|
if (!hash) { Cryptpad.setTodoHash(nHash); }
|
||||||
cb(null, Utils.Hash.getSecrets('todo', nHash));
|
cb(null, Utils.Hash.getSecrets('todo', nHash));
|
||||||
});
|
});
|
||||||
|
|||||||
@ -389,7 +389,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(common, href, b64);
|
Thumb.setPadThumbnail(common, href, privateDat.channel, b64);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
window.setInterval(mkThumbnail, Thumb.UPDATE_INTERVAL);
|
window.setInterval(mkThumbnail, Thumb.UPDATE_INTERVAL);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user