Merge branch 'staging' of github.com:xwiki-labs/cryptpad into staging

pull/1/head
yflory 8 years ago
commit 33e19d5918

@ -12,6 +12,8 @@ define(function() {
*/
config.notificationTimeout = 5000;
config.enablePinning = true;
config.whiteboardPalette = [
'#000000', // black
'#FFFFFF', // white

@ -17,7 +17,7 @@
"scripts": {
"lint": "jshint --config .jshintrc --exclude-path .jshintignore .",
"test": "node TestSelenium.js",
"style": "lessc ./customize.dist/src/less/cryptpad.less > ./customize.dist/main.css && lessc ./customize.dist/src/less/toolbar.less > ./customize.dist/toolbar.css && lessc ./www/drive/file.less > ./www/drive/file.css && lessc ./www/settings/main.less > ./www/settings/main.css && lessc ./www/slide/slide.less > ./www/slide/slide.css",
"style": "lessc ./customize.dist/src/less/cryptpad.less > ./customize.dist/main.css && lessc ./customize.dist/src/less/toolbar.less > ./customize.dist/toolbar.css && lessc ./www/drive/file.less > ./www/drive/file.css && lessc ./www/settings/main.less > ./www/settings/main.css && lessc ./www/slide/slide.less > ./www/slide/slide.css && lessc ./www/whiteboard/whiteboard.less > ./www/whiteboard/whiteboard.css",
"template": "cd customize.dist/src && node build.js"
}
}

@ -144,16 +144,11 @@ var getChannelList = function (store, publicKey, cb) {
pins[pin] = false;
});
if (!parsed[1] || parsed[1].length) {
break;
}
else {
if (parsed[1] && parsed[1].length) {
parsed[1].forEach(function (channel) {
pins[channel] = true;
});
break;
}
break;
default:
console.error('invalid message read from store');

@ -6,9 +6,11 @@ define([
'/bower_components/alertifyjs/dist/js/alertify.js',
'/common/clipboard.js',
'/customize/application_config.js',
'/common/pinpad.js', /* TODO
load pinpad dynamically only after you know that it will be needed */
'/bower_components/jquery/dist/jquery.min.js',
], function (Config, Messages, Store, Crypto, Alertify, Clipboard, AppConfig) {
], function (Config, Messages, Store, Crypto, Alertify, Clipboard, Pinpad, AppConfig) {
/* This file exposes functionality which is specific to Cryptpad, but not to
any particular pad type. This includes functions for committing metadata
about pads to your local storage for future use and improved usability.
@ -25,6 +27,8 @@ define([
var store;
var PINNING_ENABLED = AppConfig.enablePinning;
var rpc;
var find = common.find = function (map, path) {
return (map && path.reduce(function (p, n) {
@ -36,6 +40,11 @@ define([
if (store) { return store; }
throw new Error("Store is not ready!");
};
var getProxy = common.getProxy = function () {
if (store && store.getProxy()) {
return store.getProxy().proxy;
}
};
var getNetwork = common.getNetwork = function () {
if (store) {
if (store.getProxy() && store.getProxy().info) {
@ -168,7 +177,6 @@ define([
return typeof getUserHash() === "string";
};
// var isArray = function (o) { return Object.prototype.toString.call(o) === '[object Array]'; };
var isArray = common.isArray = $.isArray;
var fixHTML = common.fixHTML = function (str) {
@ -206,7 +214,7 @@ define([
return hexArray.join("");
};
var deduplicate = common.deduplicateString = function (array) {
var deduplicateString = common.deduplicateString = function (array) {
var a = array.slice();
for(var i=0; i<a.length; i++) {
for(var j=i+1; j<a.length; j++) {
@ -216,7 +224,6 @@ define([
return a;
};
var parseHash = common.parseHash = function (hash) {
var parsed = {};
if (hash.slice(0,1) !== '/' && hash.length >= 56) {
@ -289,14 +296,6 @@ define([
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, '/');
if (secret.channel.length !== 32 || secret.key.length !== 24) {
common.alert("The channel key and/or the encryption key is invalid");
throw new Error("The channel key and/or the encryption key is invalid");
}
}*/
if (version === "1") {
var mode = hashArray[2];
if (mode === 'edit') {
@ -492,12 +491,6 @@ define([
var untitledIndex = 1;
var name = (Messages.type)[type] + ' - ' + new Date().toString().split(' ').slice(0,4).join(' ');
return name;
/*
* Pad titles are shared in the document so it does not make sense anymore to avoid duplicates
if (isNameAvailable(name, parsed, recentPads)) { return name; }
while (!isNameAvailable(name + ' - ' + untitledIndex, parsed, recentPads)) { untitledIndex++; }
return name + ' - ' + untitledIndex;
*/
};
var isDefaultName = common.isDefaultName = function (parsed, title) {
var name = getDefaultName(parsed, []);
@ -579,6 +572,7 @@ define([
// STORAGE
/* commit a list of pads to localStorage */
// TODO integrate pinning if enabled
var setRecentPads = common.setRecentPads = function (pads, cb) {
getStore().setDrive(storageKey, pads, function (err, data) {
cb(err, data);
@ -605,6 +599,7 @@ define([
// STORAGE
// TODO integrate pinning if enabled
var forgetPad = common.forgetPad = function (href, cb) {
var parsed = parsePadUrl(href);
@ -686,6 +681,8 @@ define([
var isNotStrongestStored = common.isNotStrongestStored = function (href, recents) {
return findStronger(href, recents);
};
// TODO integrate pinning
var setPadTitle = common.setPadTitle = function (name, cb) {
var href = window.location.href;
var parsed = parsePadUrl(href);
@ -821,12 +818,14 @@ define([
// local name?
common.ready = function (f) {
var state = 0;
var block = 0;
var env = {};
var cb = function () {
block--;
if (!block) {
f(void 0, env);
}
};
if (sessionStorage[newPadNameKey]) {
@ -841,6 +840,9 @@ define([
Store.ready(function (err, storeObj) {
store = common.store = env.store = storeObj;
var proxy = getProxy();
var network = getNetwork();
$(function() {
// Race condition : if document.body is undefined when alertify.js is loaded, Alertify
// won't work. We have to reset it now to make sure it uses a correct "body"
@ -864,8 +866,34 @@ define([
}
};
if (PINNING_ENABLED && isLoggedIn()) {
console.log("logged in. pads will be pinned");
block++;
// TODO setTimeout in case rpc doesn't
// activate in reasonable time?
Pinpad.create(network, proxy, function (e, call) {
if (e) {
console.error(e);
return cb();
}
console.log('RPC handshake complete');
rpc = env.rpc = call;
// TODO check if pin list is up to date
// if not, reset
cb();
});
} else if (PINNING_ENABLED) {
console.log('not logged in. pads will not be pinned');
} else {
console.log('pinning disabled');
}
// Everything's ready, continue...
if($('#pad-iframe').length) {
block++;
var $iframe = $('#pad-iframe');
var iframe = $iframe[0];
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
@ -876,6 +904,8 @@ define([
$iframe.load(cb);
return;
}
block++;
cb();
});
}, common);
@ -966,6 +996,7 @@ define([
/*
* Buttons
*/
// TODO integrate pinning if enabled
var renamePad = common.renamePad = function (title, callback) {
if (title === null) { return; }
@ -982,30 +1013,6 @@ define([
}
callback(null, title);
});
/* Pad titles are shared in the document. We don't check for duplicates anymore.
common.causesNamingConflict(title, function (err, conflicts) {
if (err) {
console.log("Unable to determine if name caused a conflict");
console.error(err);
callback(err, title);
return;
}
if (conflicts) {
common.alert(Messages.renameConflict);
return;
}
common.setPadTitle(title, function (err, data) {
if (err) {
console.log("unable to set pad title");
console.log(err);
return;
}
callback(null, title);
});
});
*/
};
var getUserChannelList = common.getUserChannelList = function () {
@ -1047,6 +1054,10 @@ define([
return list;
};
var getCanonicalChannelList = common.getCanonicalChannelList = function () {
return deduplicateString(getUserChannelList()).sort();
};
var createButton = common.createButton = function (type, rightside, data, callback) {
var button;
var size = "17px";

@ -1,69 +1,12 @@
define([
'/common/cryptpad-common.js',
'/common/rpc.js',
'/bower_components/tweetnacl/nacl-fast.min.js'
], function (Cryptpad, Rpc) {
], function (Rpc) {
var Nacl = window.nacl;
var uniqueChannelList = function (list) {
list = list || Cryptpad.getUserChannelList();
return Cryptpad.deduplicateString(list).sort();
};
var localChannelsHash = function (fileList) {
var uniqueList = uniqueChannelList(fileList);
var hash = Nacl.util.encodeBase64(Nacl
.hash(Nacl.util.decodeUTF8( JSON.stringify(uniqueList) )));
return hash;
};
var getServerHash = function (rpc, edPublic, cb) {
rpc.send('GET_HASH', edPublic, function (e, hash) {
cb(e, hash[0]);
});
};
var getFileSize = function (rpc, file, cb) {
rpc.send('GET_FILE_SIZE', file, cb);
};
var getFileListSize = function (rpc, cb) {
return rpc.send('GET_TOTAL_SIZE', undefined, cb);
};
var pinChannel = function (rpc, channel, cb) {
rpc.send('PIN', channel, cb);
};
var unpinChannel = function (rpc, channel, cb) {
rpc.send('UNPIN', channel, cb);
};
var reset = function (rpc, cb) {
var list = uniqueChannelList();
rpc.send('RESET', list, cb);
};
/*
1. every time you want to pin or unpid a pad you send a message to the server
2. the server sends back a hash of the sorted list of your pinned pads
3. you hash your sorted list of pinned pads that you should have according to your drive
4. compare them, if same
AWESOME
if they are not
UNPIN all, send all
*/
// Don't use create until Cryptpad is ready
// (use Cryptpad.ready)
var create = function (cb) {
// you will need to communicate with the server
// use an already established
var network = Cryptpad.getNetwork();
// your user proxy contains credentials you will need to make RPC calls
var proxy = Cryptpad.getStore().getProxy().proxy;
var create = function (network, proxy, cb) {
if (!network) { return void cb('INVALID_NETWORK'); }
if (!proxy) { return void cb('INVALID_PROXY'); }
var edPrivate = proxy.edPrivate;
var edPublic = proxy.edPublic;
@ -74,32 +17,52 @@ define([
if (e) { return void cb(e); }
var exp = {};
// expose the supplied publicKey as an identifier
exp.publicKey = edPublic;
// expose the RPC module's raw 'send' command
exp.send = rpc.send;
exp.uniqueChannelList = uniqueChannelList;
// you can ask the server to pin a particular channel for you
exp.pin = function (channel, cb) {
rpc.send('PIN', channel, cb);
};
exp.getFileSize = function (file, cb) {
getFileSize(rpc, file, cb);
// you can also ask to unpin a particular channel
exp.unpin = function (channel, cb) {
rpc.send('UNPIN', channel, cb);
};
exp.getFileListSize = function (cb) {
getFileListSize(rpc, cb);
// This implementation must match that on the server
// it's used for a checksum
exp.hashChannelList = function (list) {
return Nacl.util.encodeBase64(Nacl.hash(Nacl.util
.decodeUTF8(JSON.stringify(list))));
};
// ask the server what it thinks your hash is
exp.getServerHash = function (cb) {
getServerHash(rpc, edPublic, cb);
rpc.send('GET_HASH', edPublic, function (e, hash) {
cb(e, hash[0]);
});
};
exp.pin = function (channel, cb) {
pinChannel(rpc, channel, cb);
};
exp.unpin = function (channel, cb) {
unpinChannel(rpc, channel, cb);
// if local and remote hashes don't match, send a reset
exp.reset = function (list, cb) {
rpc.send('RESET', list, cb);
};
exp.reset = function (cb) {
reset(rpc, cb);
// get the total stored size of a channel's patches (in bytes)
exp.getFileSize = function (file, cb) {
rpc.send('GET_FILE_SIZE', file, cb);
};
exp.localChannelsHash = localChannelsHash;
// get the combined size of all channels (in bytes) for all the
// channels which the server has pinned for your publicKey
exp.getFileListSize = function (cb) {
rpc.send('GET_TOTAL_SIZE', undefined, cb);
};
cb(e, exp);
});

@ -53,7 +53,8 @@ types of messages:
var pending = ctx.pending[txid];
if (!(parsed && parsed.slice)) {
return void console.error('MALFORMED_RPC_RESPONSE');
// RPC responses are arrays. this message isn't meant for us.
return;
}
var response = parsed.slice(2);
@ -70,9 +71,8 @@ types of messages:
}
}
pending(void 0, response);
} else {
console.log("No callback provided");
}
//else { console.log("No callback provided"); }
};
var create = function (network, edPrivateKey, edPublicKey, cb) {

@ -9,46 +9,16 @@ define([
Cryptpad: Cryptpad,
};
var then = function (call) {
call.getFileSize('26f014b2ab959418605ea37a6785f317', function (e, msg) {
if (e) {
if (e === 'ENOENT') { return; }
return void console.error(e);
}
console.error("EXPECTED ENOENT");
console.log(msg);
});
call.getFileSize('pewpew', function (e, msg) {
if (e) {
if (e === 'INVALID_CHAN') { return; }
return void console.error(e);
}
console.log(msg);
});
var list = Cryptpad.getUserChannelList();
if (list.length) {
call.getFileSize(list[0], function (e, msg) {
if (e) {
return void console.error(e);
}
console.log(msg);
});
}
call.getServerHash(function (e, hash) {
if (e) { return void console.error(e); }
console.log("the server believes your user hash is [%s]", hash);
});
};
var synchronize = function (call) {
var localHash = call.localChannelsHash();
// provide a sorted list of unique channels
var list = Cryptpad.getCanonicalChannelList();
var localHash = call.hashChannelList(list);
var serverHash;
call.getFileListSize(function (e, bytes) {
if (e) { return void console.error(e); }
console.log("%s total bytes used", bytes);
console.log("total %sK bytes used", bytes / 1000);
});
call.getServerHash(function (e, hash) {
@ -59,26 +29,22 @@ define([
return console.log("all your pads are pinned. There is nothing to do");
}
call.reset(function (e, response) {
call.reset(list, function (e, response) {
if (e) { return console.error(e); }
else {
return console.log('reset pin list. new hash is [%s]', response);
}
});
/*
console.log(JSON.stringify({
local: localHash,
remote: serverHash,
}, null, 2));*/
});
};
$(function () {
Cryptpad.ready(function (err, env) {
Pinpad.create(function (e, call) {
var network = Cryptpad.getNetwork();
var proxy = Cryptpad.getStore().getProxy().proxy;
Pinpad.create(network, proxy, function (e, call) {
if (e) { return void console.error(e); }
// then(call);
synchronize(call);
});
});

@ -11,82 +11,7 @@
id="favicon" />
<link rel="stylesheet" href="/bower_components/components-font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="/customize/main.css" />
<style>
html, body{
padding: 0px;
margin: 0px;
box-sizing: border-box;
}
body {
display: flex;
flex-flow: column;
height: 100%;
background: url('/customize/bg3.jpg') no-repeat center center;
background-size: cover;
background-position: center;
}
#canvas-area {
flex: 1;
display: flex;
}
.canvas-container {
border: 5px solid black;
margin: auto;
background: white;
}
#clear, #toggleDraw {
display: inline;
vertical-align: middle;
}
#colors {
z-index: 100;
border: 3px solid black;
padding: 5px;
vertical-align: top;
background: white;
}
.selected {
margin-left: 20px;
display: inline-block;
height: 100px;
}
.selected img {
vertical-align: middle;
}
#copy {
padding-left: 75px;
}
span.palette-color {
height: 4vw;
width: 4vw;
display: inline-block;
margin: 5px;
border: 2px solid black;
vertical-align: top;
}
#controls {
display: block;
position: relative;
border: 3px solid black;
background: white;
height: 100px;
line-height: 100px;
}
#width, #colors {
position: relative;
vertical-align: middle;
}
#color-picker {
display: block;
}
#pickers {
visibility: hidden;
position: absolute;
width: 0;
height: 0;
z-index: -5;
}
</style>
<link rel="stylesheet" href="whiteboard.css" />
</head>
<body>
<div id="toolbar" class="toolbar-container"></div>

@ -107,9 +107,8 @@ define([
type: 'color',
value: '#FFFFFF',
})
.css({
visibility: 'hidden'
})
// TODO confirm that this is safe to remove
//.css({ visibility: 'hidden' })
.on('change', function () {
var color = this.value;
cb(color);
@ -242,6 +241,7 @@ define([
};
var addColorToPalette = function (color, i) {
if (readOnly) { return; }
var $color = $('<span>', {
'class': 'palette-color',
})
@ -252,7 +252,6 @@ define([
var c = rgb2hex($color.css('background-color'));
setColor(c);
})
// FIXME double click doesn't seem to work in chromium currently
.on('dblclick', function (e) {
e.preventDefault();
pickColor(rgb2hex($color.css('background-color')), function (c) {
@ -263,19 +262,17 @@ define([
config.onLocal();
setColor(c);
});
// TODO commit chosen color to pad metadata:
// json.metadata.palette[i]
});
$colors.append($color);
};
palette.forEach(addColorToPalette);
var updatePalette = function (newPalette) {
palette = newPalette;
$colors.html('&nbsp;');
$colors.html('<div class="hidden">&nbsp;</div>');
palette.forEach(addColorToPalette);
};
updatePalette(palette);
var suggestName = function (fallback) {
if (document.title === defaultName) {

@ -0,0 +1,82 @@
.hidden {
display: none;
}
html,
body {
padding: 0px;
margin: 0px;
box-sizing: border-box;
}
body {
display: flex;
flex-flow: column;
height: 100%;
background: url('/customize/bg3.jpg') no-repeat center center;
background-size: cover;
background-position: center;
}
#canvas-area {
flex: 1;
display: flex;
}
.canvas-container {
border: 1px solid black;
margin: auto;
background: white;
}
#controls {
display: block;
position: relative;
border-top: 1px solid black;
background: white;
height: 100px;
line-height: 100px;
padding-bottom: 5px;
}
#controls #width {
position: relative;
vertical-align: middle;
}
#controls #clear,
#controls #toggleDraw {
display: inline;
vertical-align: middle;
}
#controls .selected {
margin-left: 20px;
display: inline-block;
height: 135px;
width: 135px;
z-index: 9001;
text-align: center;
}
#controls .selected img {
vertical-align: middle;
}
/* Colors */
#colors {
position: relative;
vertical-align: middle;
z-index: 100;
background: white;
display: flex;
justify-content: space-between;
}
#colors span.palette-color {
height: 4vw;
width: 4vw;
display: inline-block;
margin: 5px;
border: 1px solid black;
vertical-align: top;
}
#color-picker {
display: block;
}
#pickers {
visibility: hidden;
position: absolute;
width: 0;
height: 0;
z-index: -5;
}

@ -0,0 +1,97 @@
.middle () {
position: relative;
vertical-align: middle;
}
.hidden {
display: none;
}
html, body{
padding: 0px;
margin: 0px;
box-sizing: border-box;
}
body {
display: flex;
flex-flow: column;
height: 100%;
background: url('/customize/bg3.jpg') no-repeat center center;
background-size: cover;
background-position: center;
}
// created in the html
#canvas-area {
flex: 1;
display: flex;
}
// created by fabricjs. styled so defaults don't break anything
.canvas-container {
border: 1px solid black;
margin: auto;
background: white;
}
// contains user tools
#controls {
display: block;
position: relative;
border-top: 1px solid black;
background: white;
height: 100px;
line-height: 100px;
padding-bottom: 5px;
#width {
.middle;
}
#clear, #toggleDraw {
display: inline;
vertical-align: middle;
}
.selected {
margin-left: 20px;
display: inline-block;
height: 135px;
width: 135px;
z-index: 9001;
text-align: center;
img {
vertical-align: middle;
}
}
}
/* Colors */
#colors {
.middle;
z-index: 100;
background: white;
display: flex;
justify-content: space-between;
span.palette-color {
height: 4vw;
width: 4vw;
display: inline-block;
margin: 5px;
border: 1px solid black;
vertical-align: top;
}
}
// used in the toolbar if supported
#color-picker {
display: block;
}
// input[type=color] must exist in the dom to work correctly
// styled so that they don't break layouts
#pickers {
visibility: hidden;
position: absolute;
width: 0;
height: 0;
z-index: -5;
}
Loading…
Cancel
Save