diff --git a/customize.dist/messages.js b/customize.dist/messages.js index df5abbe44..90cba2818 100644 --- a/customize.dist/messages.js +++ b/customize.dist/messages.js @@ -73,5 +73,11 @@ define(function () { out.loginText = '
Your username and password are used to generate a unique key which is never known by our server.
\n' + 'Be careful not to forget your credentials, as they are impossible to recover
'; + out.type = {}; + out.type.pad = 'Pad'; + out.type.code = 'Code'; + out.type.poll = 'Poll'; + out.type.slide = 'Presentation'; + return out; }); diff --git a/www/code/main.js b/www/code/main.js index 554215681..764ff6698 100644 --- a/www/code/main.js +++ b/www/code/main.js @@ -25,6 +25,8 @@ define([ spinner: Cryptpad.spinner(document.body), }; + Cryptpad.styleAlerts(); + module.spinner.show(); var ifrw = module.ifrw = $('#pad-iframe')[0].contentWindow; @@ -240,12 +242,13 @@ define([ }; var suggestName = function () { - var hash = window.location.hash.slice(1, 9); + var parsed = Cryptpad.parsePadUrl(window.location.href); + var name = Cryptpad.getDefaultName(parsed, []); - if (document.title === hash) { - return getHeadingText() || hash; + if (document.title.slice(0, name.length) === name) { + return getHeadingText() || document.title; } else { - return document.title || getHeadingText() || hash; + return document.title || getHeadingText() || name; } }; @@ -375,7 +378,8 @@ define([ console.error(err); return; } - document.title = window.location.hash.slice(1,9); + var parsed = Cryptpad.parsePadUrl(href); + document.title = Cryptpad.getDefaultName(parsed, []); }); }); }); @@ -439,14 +443,14 @@ define([ configureTheme(); }); - window.location.hash = info.channel + secret.key; + window.location.hash = Cryptpad.getHashFromKeys(info.channel, secret.key); Cryptpad.getPadTitle(function (err, title) { if (err) { console.log("Unable to get pad title"); console.error(err); return; } - document.title = title || window.location.hash.slice(1,9); + document.title = title || info.channel.slice(0, 8); Cryptpad.rememberPad(title, function (err, data) { if (err) { console.log("Unable to set pad title"); @@ -622,7 +626,6 @@ define([ Cryptpad.alert(Messages.disconnectAlert); }; - Cryptpad.styleAlerts(); var realtime = module.realtime = Realtime.start(config); editor.on('change', onLocal); diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index 4da9816af..1e1a67069 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -100,7 +100,7 @@ define([ // don't do anything funny unless you're on a cryptpad subdomain if (!/cryptpad.fr$/i.test(hostname)) { return; } - if (hash.length >= 56) { + if (hash.length >= 25) { // you're on the right domain return; } @@ -116,15 +116,67 @@ define([ window.location.hostname = 'old.cryptpad.fr'; }; + var hexToBase64 = common.hexToBase64 = function (hex) { + var hexArray = hex + .replace(/\r|\n/g, "") + .replace(/([\da-fA-F]{2}) ?/g, "0x$1 ") + .replace(/ +$/, "") + .split(" "); + var byteString = String.fromCharCode.apply(null, hexArray); + return window.btoa(byteString).replace(/\//g, '-').slice(0,-2); + }; + + var base64ToHex = common.base64ToHex = function (b64String) { + var hexArray = []; + atob(b64String.replace(/-/g, '/') + "==").split("").forEach(function(e){ + var h = e.charCodeAt(0).toString(16); + if (h.length === 1) { h = "0"+h; } + hexArray.push(h); + }); + return hexArray.join(""); + }; + + var getHashFromKeys = common.getHashFromKeys = function (chanKey, cryptKey) { + return '/1/' + hexToBase64(chanKey) + '/' + cryptKey.replace(/\//g, '-'); + }; + var getSecrets = common.getSecrets = function () { var secret = {}; if (!/#/.test(window.location.href)) { secret.key = Crypto.genKey(); } else { var hash = window.location.hash.slice(1); + if (hash.length === 0) { + secret.key = Crypto.genKey(); + return secret; + } common.redirect(hash); - secret.channel = hash.slice(0, 32); - secret.key = hash.slice(32); + // old hash system : #{hexChanKey}{cryptKey} + // new hash system : #/{hashVersion}/{b64ChanKey}/{cryptKey} + if (hash.slice(0,1) !== '/' && hash.length >= 56) { + // Old hash + secret.channel = hash.slice(0, 32); + secret.key = hash.slice(32); + } + else { + // New hash + var hashArray = hash.split('/'); + if (hashArray.length < 4) { + common.alert("Unable to parse the key"); + throw new Error("Unable to parse the key"); + } + var version = hashArray[1]; + if (version === "1") { + secret.channel = base64ToHex(hashArray[2]); + secret.key = hashArray[3].replace(/-/g, '/'); //TODO replace / by - + if (secret.channel.length !== 32 || secret.key.length !== 24) { + common.alert("The channel key and/or the encryption key is invalid"); + console.log("Channel key length : " + secret.channel.length + " != 32"); + console.log("Encryption key length : " + secret.key.length + " != 24"); + throw new Error("The channel key and/or the encryption key is invalid"); + } + } + } } return secret; }; @@ -193,6 +245,25 @@ define([ return ret; }; + var isNameAvailable = function (title, parsed, pads) { + return !pads.some(function (pad) { + // another pad is already using that title + if (pad.title === title) { + return true; + } + }); + }; + + // Create untitled documents when no name is given + var getDefaultName = common.getDefaultName = function (parsed, recentPads) { + var type = parsed.type; + var untitledIndex = 1; + var name = (Messages.type)[type] + ' - ' + new Date().toString().split(' ').slice(0,4).join(' '); + if (isNameAvailable(name, parsed, recentPads)) { return name; } + while (!isNameAvailable(name + ' - ' + untitledIndex, parsed, recentPads)) { untitledIndex++; } + return name + ' - ' + untitledIndex; + }; + var makePad = function (href, title) { var now = ''+new Date(); return { @@ -379,6 +450,8 @@ define([ } }); + if (title === '') { title = getDefaultName(parsed, pads); } + cb(void 0, title); }); }; @@ -396,7 +469,7 @@ define([ var conflicts = pads.some(function (pad) { // another pad is already using that title if (pad.title === title) { - var p = parsePadUrl(href); + var p = parsePadUrl(pad.href); if (p.type === parsed.type && p.hash === parsed.hash) { // the duplicate pad has the same type and hash diff --git a/www/pad/main.js b/www/pad/main.js index c2f62b91f..fac663e51 100644 --- a/www/pad/main.js +++ b/www/pad/main.js @@ -21,13 +21,14 @@ define([ ], function (Config, Messages, Crypto, realtimeInput, Hyperjson, Toolbar, Cursor, JsonOT, TypingTest, JSONSortify, TextPatcher, Cryptpad, Visible, Notify) { - var $ = window.jQuery; var saveAs = window.saveAs; var ifrw = $('#pad-iframe')[0].contentWindow; var Ckeditor; // to be initialized later... var DiffDom = window.diffDOM; + Cryptpad.styleAlerts(); + var stringify = function (obj) { return JSONSortify(obj); }; @@ -439,12 +440,13 @@ define([ }; var suggestName = module.suggestName = function () { - var hash = window.location.hash.slice(1, 9); + var parsed = Cryptpad.parsePadUrl(window.location.href); + var name = Cryptpad.getDefaultName(parsed, []); - if (document.title === hash) { - return getHeadingText() || hash; + if (document.title.slice(0, name.length) === name) { + return getHeadingText() || document.title; } else { - return document.title || getHeadingText() || hash; + return document.title || getHeadingText() || name; } }; @@ -535,14 +537,15 @@ define([ Cryptpad.confirm(Messages.forgetPrompt, function (yes) { if (!yes) { return; } Cryptpad.forgetPad(href, function (err, data) { - document.title = window.location.hash.slice(1,9); + var parsed = Cryptpad.parsePadUrl(href); + document.title = Cryptpad.getDefaultName(parsed, []); }); }); }); $rightside.append($forgetPad); // set the hash - window.location.hash = info.channel + secret.key; + window.location.hash = Cryptpad.getHashFromKeys(info.channel, secret.key); Cryptpad.getPadTitle(function (err, title) { if (err) { @@ -550,7 +553,7 @@ define([ console.log("Couldn't get pad title"); return; } - document.title = title || window.location.hash.slice(1, 9); + document.title = title || info.channel.slice(0, 8); Cryptpad.rememberPad(title, function (err, data) { if (err) { console.log("Couldn't remember pad"); @@ -558,8 +561,6 @@ define([ } }); }); - - Cryptpad.styleAlerts(); }; // this should only ever get called once, when the chain syncs diff --git a/www/poll/main.js b/www/poll/main.js index 9ae642e13..9636beb4a 100644 --- a/www/poll/main.js +++ b/www/poll/main.js @@ -649,17 +649,6 @@ define([ setEditable(false); }); - Cryptpad.getPadTitle(function (err, title) { - title = document.title = title || window.location.hash.slice(1, 9); - - Cryptpad.rememberPad(title, function (err, data) { - if (err) { - console.log("unable to remember pad"); - console.log(err); - return; - } - }); - }); var $toolbar = $('#toolbar'); @@ -669,12 +658,15 @@ define([ return $('