diff --git a/customize.dist/loading.js b/customize.dist/loading.js
index a2c1dcdfc..80e064a67 100644
--- a/customize.dist/loading.js
+++ b/customize.dist/loading.js
@@ -81,6 +81,38 @@ define([], function () {
text-align: center;
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 {
position: relative;
height: 100px;
diff --git a/customize.dist/src/less2/include/creation.less b/customize.dist/src/less2/include/creation.less
index b2f6fa46b..f37fbdb35 100644
--- a/customize.dist/src/less2/include/creation.less
+++ b/customize.dist/src/less2/include/creation.less
@@ -144,16 +144,18 @@
max-height: 100px;
}
}
+
+ input, select {
+ font-size: 14px;
+ border: 1px solid @colortheme_form-border;
+ height: 26px;
+ background-color: @colortheme_form-bg;
+ color: @colortheme_form-color;
+ }
+
.cp-creation-expire {
.cp-creation-expire-picker {
text-align: center;
- input, select {
- font-size: 14px;
- border: 1px solid @colortheme_form-border;
- height: 26px;
- background-color: @colortheme_form-bg;
- color: @colortheme_form-color;
- }
input {
width: 50px;
margin: 0 5px;
@@ -171,6 +173,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 {
button {
margin: 0;
@@ -314,7 +332,7 @@
width: 95%;
margin: 10px auto;
}
- .cp-creation-expire {
+ .cp-creation-expire, .cp-creation-password {
&.active {
label {
flex: 1;
diff --git a/customize.dist/translations/messages.fr.js b/customize.dist/translations/messages.fr.js
index 86f960bcb..e43cad6a1 100644
--- a/customize.dist/translations/messages.fr.js
+++ b/customize.dist/translations/messages.fr.js
@@ -1098,6 +1098,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 Espace pour changer sa valeur.";
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 !
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
out.share_linkCategory = "Partage";
out.share_linkAccess = "Droits d'accès";
diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js
index ddaa1158f..4c3720151 100644
--- a/customize.dist/translations/messages.js
+++ b/customize.dist/translations/messages.js
@@ -1144,6 +1144,12 @@ define(function () {
out.creation_newPadModalDescriptionAdvanced = "You can check the box (or press Space 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";
+ // 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!
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
out.share_linkCategory = "Share link";
out.share_linkAccess = "Access rights";
diff --git a/www/code/inner.js b/www/code/inner.js
index c2e5851bf..0a6b11abc 100644
--- a/www/code/inner.js
+++ b/www/code/inner.js
@@ -334,6 +334,7 @@ define([
//var cursor = editor.getCursor();
//var cleanName = data.name.replace(/[\[\]]/g, '');
//var text = '';
+ // PASSWORD_FILES
var parsed = Hash.parsePadUrl(data.url);
var hexFileName = Util.base64ToHex(parsed.hashData.channel);
var src = '/blob/' + hexFileName.slice(0,2) + '/' + hexFileName;
diff --git a/www/common/common-hash.js b/www/common/common-hash.js
index 852260acc..48d0e622f 100644
--- a/www/common/common-hash.js
+++ b/www/common/common-hash.js
@@ -96,6 +96,7 @@ define([
Hash.createRandomHash = function (type, password) {
var cryptor = Crypto.createEditCryptor2(void 0, void 0, password);
+ console.log(cryptor);
return getEditHashFromKeys({
password: Boolean(password),
version: 2,
@@ -262,6 +263,7 @@ Version 1
var getRelativeHref = Hash.getRelativeHref = function (href) {
if (!href) { return; }
if (href.indexOf('#') === -1) { return; }
+ // Password not needed to get the type or the hash
var parsed = parsePadUrl(href);
return '/' + parsed.type + '/#' + parsed.hash;
};
@@ -287,14 +289,15 @@ Version 1
var hash;
if (secretHash) {
if (!type) { throw new Error("getSecrets with a hash requires a type parameter"); }
+ // Password not needed here, we only use the hash key
parsed = parseTypeHash(type, secretHash);
hash = secretHash;
} else {
+ // Password not needed here, we only use the hash key
var pHref = parsePadUrl(window.location.href);
parsed = pHref.hashData;
hash = pHref.hash;
}
- //var parsed = parsePadUrl(window.location.href);
//var hash = secretHash || window.location.hash.slice(1);
if (hash.length === 0) {
generate();
@@ -337,10 +340,10 @@ Version 1
// New hash
secret.version = 2;
secret.type = type;
- secret.password = Boolean(password);
+ secret.password = password;
if (parsed.type === "pad") {
if (parsed.mode === 'edit') {
- secret.keys = Crypto.createEditCryptor2(parsed.key);
+ 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) {
@@ -348,7 +351,7 @@ Version 1
}
}
else if (parsed.mode === 'view') {
- secret.keys = Crypto.createViewCryptor2(parsed.key);
+ 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");
@@ -388,14 +391,14 @@ Version 1
};
// STORAGE
- Hash.findWeaker = function (href, recents) {
+ Hash.findWeaker = function (href, recents, password) {
var rHref = href || getRelativeHref(window.location.href);
- var parsed = parsePadUrl(rHref);
+ var parsed = parsePadUrl(rHref, password);
if (!parsed.hash) { return false; }
var weaker;
Object.keys(recents).some(function (id) {
var pad = recents[id];
- var p = parsePadUrl(pad.href);
+ var p = parsePadUrl(pad.href, pad.password);
if (p.type !== parsed.type) { return; } // Not the same type
if (p.hash === parsed.hash) { return; } // Same hash, not stronger
var pHash = p.hashData;
@@ -408,23 +411,23 @@ Version 1
if (pHash.version !== parsedHash.version) { return; }
if (pHash.channel !== parsedHash.channel) { return; }
if (pHash.mode === 'view' && parsedHash.mode === 'edit') {
- weaker = pad.href;
+ weaker = pad;
return true;
}
return;
});
return weaker;
};
- var findStronger = Hash.findStronger = function (href, recents) {
+ var findStronger = Hash.findStronger = function (href, recents, password) {
var rHref = href || getRelativeHref(window.location.href);
- var parsed = parsePadUrl(rHref);
+ var parsed = parsePadUrl(rHref, password);
if (!parsed.hash) { return false; }
// We can't have a stronger hash if we're already in edit mode
if (parsed.hashData && parsed.hashData.mode === 'edit') { return; }
var stronger;
Object.keys(recents).some(function (id) {
var pad = recents[id];
- var p = parsePadUrl(pad.href);
+ var p = parsePadUrl(pad.href, pad.password);
if (p.type !== parsed.type) { return; } // Not the same type
if (p.hash === parsed.hash) { return; } // Same hash, not stronger
var pHash = p.hashData;
@@ -437,19 +440,16 @@ Version 1
if (pHash.version !== parsedHash.version) { return; }
if (pHash.channel !== parsedHash.channel) { return; }
if (pHash.mode === 'edit' && parsedHash.mode === 'view') {
- stronger = pad.href;
+ stronger = pad;
return true;
}
return;
});
return stronger;
};
- Hash.isNotStrongestStored = function (href, recents) {
- return findStronger(href, recents);
- };
- Hash.hrefToHexChannelId = function (href) {
- var parsed = Hash.parsePadUrl(href);
+ Hash.hrefToHexChannelId = function (href, password) {
+ var parsed = Hash.parsePadUrl(href, password);
if (!parsed || !parsed.hash) { return; }
parsed = parsed.hashData;
diff --git a/www/common/common-interface.js b/www/common/common-interface.js
index ea2773e37..6f4850010 100644
--- a/www/common/common-interface.js
+++ b/www/common/common-interface.js
@@ -594,7 +594,12 @@ define([
$('.cp-loading-spinner-container').hide();
$('#cp-loading-tip').remove();
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) {
$(window).focus();
$(window).keydown(function (e) {
@@ -624,6 +629,7 @@ define([
var type = data.type;
if (!href && !type) { return $icon; }
+ // Password not needed to get the type
if (!type) { type = Hash.parsePadUrl(href).type; }
$icon = UI.getIcon(type);
diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js
index 2d09b2abe..9cfe64076 100644
--- a/www/common/common-ui-elements.js
+++ b/www/common/common-ui-elements.js
@@ -67,7 +67,7 @@ define([
common.getPadAttribute('href', waitFor(function (err, val) {
var base = common.getMetadataMgr().getPrivateData().origin;
- var parsed = Hash.parsePadUrl(val);
+ var parsed = Hash.parsePadUrl(val, data.password);
if (parsed.hashData.mode === "view") {
data.roHref = base + val;
return;
@@ -285,6 +285,7 @@ define([
var hash = (edit && hashes.editHash) ? hashes.editHash : hashes.viewHash;
var href = origin + pathname + '#' + hash;
+ // Password not needed here since we don't access hashData
var parsed = Hash.parsePadUrl(href);
return origin + parsed.getUrl({embed: embed, present: present});
};
@@ -322,6 +323,7 @@ define([
var getEmbedValue = function () {
var hash = hashes.viewHash || hashes.editHash;
var href = origin + pathname + '#' + hash;
+ // Password not needed here since we don't access hashData
var parsed = Hash.parsePadUrl(href);
var url = origin + parsed.getUrl({embed: true, present: true});
return '';
@@ -930,14 +932,14 @@ define([
};
};
+ var setHTML = function (e, html) {
+ e.innerHTML = html;
+ return e;
+ };
+
UIElements.createHelpMenu = function (common, categories) {
var type = common.getMetadataMgr().getMetadata().type || 'pad';
- var setHTML = function (e, html) {
- e.innerHTML = html;
- return e;
- };
-
var elements = [];
if (Messages.help && Messages.help.generic) {
Object.keys(Messages.help.generic).forEach(function (el) {
@@ -1911,6 +1913,17 @@ define([
createHelper('/faq.html#keywords-expiring', Messages.creation_expire2),
]);
+ // Password
+ var password = h('div.cp-creation-password', [
+ UI.createCheckbox('cp-creation-password', 'TODO Add a password', false), //XXX
+ 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 left = h('span.fa.fa-chevron-left.cp-creation-template-more');
var templates = h('div.cp-creation-template', [
@@ -1936,6 +1949,7 @@ define([
$(h('div#cp-creation-form', [
owned,
expire,
+ password,
settings,
templates,
createDiv
@@ -2046,6 +2060,19 @@ define([
$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
$creation.find('#cp-creation-remember').on('change', function () {
if ($(this).is(':checked')) {
@@ -2094,12 +2121,16 @@ define([
}
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 templateId = $template.data('id') || undefined;
return {
owned: ownedVal,
+ password: passwordVal,
expire: expireVal,
templateId: templateId
};
@@ -2169,5 +2200,43 @@ define([
(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;
});
diff --git a/www/common/cryptget.js b/www/common/cryptget.js
index d5cb3edc1..623f5946e 100644
--- a/www/common/cryptget.js
+++ b/www/common/cryptget.js
@@ -43,7 +43,6 @@ define([
Object.keys(b).forEach(function (k) { a[k] = b[k]; });
};
- // XXX make sure we pass the password here in opt
var get = function (hash, cb, opt) {
if (typeof(cb) !== 'function') {
throw new Error('Cryptget expects a callback');
@@ -63,7 +62,6 @@ define([
Session.realtime = CPNetflux.start(config);
};
- // XXX make sure we pass the password here in opt
var put = function (hash, doc, cb, opt) {
if (typeof(cb) !== 'function') {
throw new Error('Cryptput expects a callback');
diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js
index e473b397c..dbc69198b 100644
--- a/www/common/cryptpad-common.js
+++ b/www/common/cryptpad-common.js
@@ -385,6 +385,7 @@ define([
if (!type) { return void cb(null, obj); }
var templates = obj.filter(function (f) {
+ // Password not needed here since we don't access hashData
var parsed = Hash.parsePadUrl(f.href);
return parsed.type === type;
});
@@ -393,10 +394,13 @@ define([
};
common.saveAsTemplate = function (Cryptput, data, cb) {
+ // Password not needed here since we don't access hashData
var p = Hash.parsePadUrl(window.location.href);
if (!p.type) { return; }
+ // XXX PPP
var hash = Hash.createRandomHash(p.type);
var href = '/' + p.type + '/#' + hash;
+ // XXX PPP
Cryptput(hash, data.toSave, function (e) {
if (e) { throw new Error(e); }
postMessage("ADD_PAD", {
@@ -419,16 +423,35 @@ 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
// it allows us to add owners and expiration time if it is a new file
+
+ // Password not needed here, we only need the hash and to know if
+ // we need to get the password
var parsed = Hash.parsePadUrl(href);
+ var parsed2 = Hash.parsePadUrl(window.location.href);
if(!parsed) { throw new Error("Cannot get template hash"); }
postMessage("INCREMENT_TEMPLATE_USE", href);
- Crypt.get(parsed.hash, function (err, val) {
- if (err) { throw new Error(err); }
- var p = Hash.parsePadUrl(window.location.href);
- Crypt.put(p.hash, val, cb, opts);
+
+ 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 (waitFor) {
+ Crypt.get(parsed.hash, function (err, val) {
+ if (err) { throw new Error(err); }
+ Crypt.put(parsed2.hash, val, cb, optsPut);
+ }, optsGet);
});
};
@@ -441,6 +464,8 @@ define([
// When opening a new pad or renaming it, store the new title
common.setPadTitle = function (title, padHref, path, cb) {
var href = padHref || window.location.href;
+
+ // Password not needed here since we don't access hashData
var parsed = Hash.parsePadUrl(href);
if (!parsed.hash) { return; }
href = parsed.getUrl({present: parsed.present});
@@ -477,6 +502,9 @@ define([
common.setInitialPath = function (path) {
postMessage("SET_INITIAL_PATH", path);
};
+ common.setNewPadPassword = function (password) {
+ postMessage("SET_NEW_PAD_PASSWORD", password);
+ };
// Messaging (manage friends from the userlist)
common.inviteFromUserlist = function (netfluxId, cb) {
@@ -559,12 +587,13 @@ define([
hashes = Hash.getHashes(secret);
return void cb(null, hashes);
}
+ // Password not needed here since only want the type
var parsed = Hash.parsePadUrl(window.location.href);
if (!parsed.type || !parsed.hashData) { return void cb('E_INVALID_HREF'); }
if (parsed.type === 'file') { secret.channel = Util.base64ToHex(secret.channel); }
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
hashes.editHash = window.location.hash.slice(1);
return void cb(null, hashes);
@@ -576,7 +605,8 @@ define([
}
postMessage("GET_STRONGER_HASH", {
- href: window.location.href
+ href: window.location.href,
+ password: secret.password
}, function (hash) {
if (hash) { hashes.editHash = hash; }
cb(null, hashes);
diff --git a/www/common/mergeDrive.js b/www/common/mergeDrive.js
index c51428b2a..a20cd798b 100644
--- a/www/common/mergeDrive.js
+++ b/www/common/mergeDrive.js
@@ -122,21 +122,15 @@ define([
// 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 we have a stronger version, do not add the current href
- if (Hash.findStronger(href, newRecentPads)) { return; }
+ if (Hash.findStronger(href, newRecentPads, oldRecentPads[id].password)) { return; }
// 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
- var weaker = Hash.findWeaker(href, newRecentPads);
+ var weaker = Hash.findWeaker(href, newRecentPads, oldRecentPads[id].password);
if (weaker) {
// Update RECENTPADS
- newRecentPads.some(function (pad) {
- if (pad.href === weaker) {
- pad.href = href;
- return true;
- }
- return;
- });
+ weaker.href = href;
// Update the file in the drive
- newFo.replace(weaker, href);
+ newFo.replace(weaker.href, href);
return;
}
// Here it means we have a new href, so we should add it to the drive at its old location
diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js
index 676277475..2ce6d58f2 100644
--- a/www/common/outer/async-store.js
+++ b/www/common/outer/async-store.js
@@ -416,6 +416,7 @@ define([
var pad = makePad(data.href, data.title);
if (data.owners) { pad.owners = data.owners; }
if (data.expire) { pad.expire = data.expire; }
+ if (data.password) { pad.password = data.password; }
store.userObject.pushData(pad, function (e, id) {
if (e) { return void cb({error: "Error while adding a template:"+ e}); }
var path = data.path || ['root'];
@@ -758,8 +759,10 @@ define([
title: title,
owners: owners,
expire: expire,
+ password: store.data && store.data.newPadPassword,
path: data.path || (store.data && store.data.initialPath)
}, cb);
+ delete store.data.newPadPassword;
return;
}
onSync(cb);
@@ -802,6 +805,11 @@ define([
if (!store.data) { return; }
store.data.initialPath = path;
};
+ Store.setNewPadPassword = function (password) {
+ if (!store.data) { return; }
+ store.data.newPadPassword = password;
+ };
+
// Messaging (manage friends from the userlist)
var getMessagingCfg = function () {
@@ -833,9 +841,9 @@ define([
var allPads = Util.find(store.proxy, ['drive', 'filesData']) || {};
// 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, allPads, data.password);
if (stronger) {
- var parsed2 = Hash.parsePadUrl(stronger);
+ var parsed2 = Hash.parsePadUrl(stronger.href, stronger.password);
return void cb(parsed2.hash);
}
cb();
diff --git a/www/common/outer/store-rpc.js b/www/common/outer/store-rpc.js
index 1713d7a2a..e95f6e227 100644
--- a/www/common/outer/store-rpc.js
+++ b/www/common/outer/store-rpc.js
@@ -123,6 +123,9 @@ define([
case 'SET_INITIAL_PATH': {
Store.setInitialPath(data); break;
}
+ case 'SET_NEW_PAD_PASSWORD': {
+ Store.setNewPadPassword(data); break;
+ }
case 'GET_STRONGER_HASH': {
Store.getStrongerHash(data, cb); break;
}
diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js
index e6543bb30..990208ee3 100644
--- a/www/common/sframe-common-outer.js
+++ b/www/common/sframe-common-outer.js
@@ -24,6 +24,7 @@ define([
var Utils = {};
var AppConfig;
var Test;
+ var password;
nThen(function (waitFor) {
// Load #2, the loading screen is up so grab whatever you need...
@@ -121,26 +122,53 @@ define([
});
}));
} else {
- var parsedType = Utils.Hash.parsePadUrl(window.location.href).type;
- // XXX prompt the password here if we have a hash containing /p/
- // OR get it from the pad attributes
- secret = Utils.Hash.getSecrets(parsedType);
+ var parsed = Utils.Hash.parsePadUrl(window.location.href);
+ var todo = function () {
+ secret = Utils.Hash.getSecrets(parsed.type, void 0, password);
+ Cryptpad.getShareHashes(secret, waitFor(function (err, h) { hashes = h; }));
+ };
- // TODO: New hashes V2 already contain a channel ID so we can probably remove the following lines
- //if (!secret.channel) {
- // New pad: create a new random channel id
- //secret.channel = Utils.Hash.createChannelId();
- //}
-
- 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");
+ }
+ }));
+ return;
+ }
+ // If no password, continue...
+ todo();
}
}).nThen(function (waitFor) {
// Check if the pad exists on server
if (!window.location.hash) { isNewFile = true; return; }
if (realtime) {
- // XXX get password
- var password;
Cryptpad.isNewChannel(window.location.href, password, waitFor(function (e, isNew) {
if (e) { return console.error(e); }
isNewFile = Boolean(isNew);
@@ -679,11 +707,12 @@ define([
sframeChan.on('Q_CREATE_PAD', function (data, cb) {
if (!isNewFile || rtStarted) { return; }
// Create a new hash
- // XXX add password here
var password = data.password;
var newHash = Utils.Hash.createRandomHash(parsed.type, password);
secret = Utils.Hash.getSecrets(parsed.type, newHash, password);
+ Cryptpad.setNewPadPassword(password);
+
// Update the hash in the address bar
var ohc = window.onhashchange;
window.onhashchange = function () {};
diff --git a/www/common/sframe-common.js b/www/common/sframe-common.js
index a56afa382..444ee40e7 100644
--- a/www/common/sframe-common.js
+++ b/www/common/sframe-common.js
@@ -198,6 +198,7 @@ define([
ctx.sframeChan.query("Q_CREATE_PAD", {
owned: cfg.owned,
expire: cfg.expire,
+ password: cfg.password,
template: cfg.template,
templateId: cfg.templateId
}, cb);
@@ -379,6 +380,7 @@ define([
Object.freeze(funcs);
return { create: function (cb) {
+ console.log('create');
if (window.CryptPad_sframe_common) {
throw new Error("Sframe-common should only be created once");
}
@@ -429,6 +431,14 @@ define([
UI.log(data.logText);
});
+ ctx.sframeChan.on("EV_PAD_PASSWORD", function (data) {
+ UIElements.displayPasswordPrompt(funcs);
+ /*UI.prompt("Password?", "", function (val) {
+ ctx.sframeChan.event("EV_PAD_PASSWORD_VALUE", val);
+ });
+ $('div.alertify').last().css("z-index", Number.MAX_SAFE_INTEGER);*/
+ });
+
ctx.metadataMgr.onReady(waitFor());
}).nThen(function () {
try {
diff --git a/www/common/sframe-protocol.js b/www/common/sframe-protocol.js
index 8142694ce..970ec5524 100644
--- a/www/common/sframe-protocol.js
+++ b/www/common/sframe-protocol.js
@@ -230,4 +230,8 @@ define({
// Critical error outside the iframe during loading screen
'EV_LOADING_ERROR': true,
+
+ // Ask for the pad password when a pad is protected
+ 'EV_PAD_PASSWORD': true,
+ 'Q_PAD_PASSWORD_VALUE': true,
});
diff --git a/www/poll/inner.js b/www/poll/inner.js
index fabcad7e4..ad0ea5ada 100644
--- a/www/poll/inner.js
+++ b/www/poll/inner.js
@@ -2,7 +2,6 @@ define([
'jquery',
'/common/toolbar3.js',
'/common/common-util.js',
- '/common/cryptget.js',
'/bower_components/nthen/index.js',
'/common/sframe-common.js',
'/common/common-realtime.js',
@@ -32,7 +31,6 @@ define([
$,
Toolbar,
Util,
- Cryptget,
nThen,
SFCommon,
CommonRealtime,