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

pull/1/head
yflory 8 years ago
commit 89a993be3c

@ -116,6 +116,12 @@ module.exports = {
'contact', 'contact',
], ],
/* Domain
* If you want to have enable payments on your CryptPad instance, it has to be able to tell
* our account server what is your domain
*/
// domain: 'https://cryptpad.fr',
/* /*
You have the option of specifying an alternative storage adaptor. You have the option of specifying an alternative storage adaptor.
These status of these alternatives are specified in their READMEs, These status of these alternatives are specified in their READMEs,

@ -1,7 +1,7 @@
{ {
"name": "cryptpad", "name": "cryptpad",
"description": "realtime collaborative visual editor with zero knowlege server", "description": "realtime collaborative visual editor with zero knowlege server",
"version": "1.6.0", "version": "1.8.0",
"dependencies": { "dependencies": {
"chainpad-server": "^1.0.1", "chainpad-server": "^1.0.1",
"express": "~4.10.1", "express": "~4.10.1",

@ -7,11 +7,14 @@ var Nacl = require("tweetnacl");
var Fs = require("fs"); var Fs = require("fs");
var Path = require("path"); var Path = require("path");
var Https = require("https");
var RPC = module.exports; var RPC = module.exports;
var Store = require("./storage/file"); var Store = require("./storage/file");
var DEFAULT_LIMIT = 100;
var isValidChannel = function (chan) { var isValidChannel = function (chan) {
return /^[a-fA-F0-9]/.test(chan) || return /^[a-fA-F0-9]/.test(chan) ||
[32, 48].indexOf(chan.length) !== -1; [32, 48].indexOf(chan.length) !== -1;
@ -454,8 +457,64 @@ var isPrivilegedUser = function (publicKey, cb) {
}); });
}; };
var getLimit = function (cb) { // The limits object contains storage limits for all the publicKey that have paid
cb = cb; // TODO // To each key is associated an object containing the 'limit' value and a 'note' explaining that limit
var limits = {};
var updateLimits = function (config, publicKey, cb) {
if (typeof cb !== "function") { cb = function () {}; }
var body = JSON.stringify({
domain: config.domain,
subdomain: config.subdomain
});
var options = {
host: 'accounts.cryptpad.fr',
path: '/api/getauthorized',
method: 'POST',
headers: {
"Content-Type": "application/json",
"Content-Length": Buffer.byteLength(body)
}
};
var req = Https.request(options, function (response) {
if (!('' + req.statusCode).match(/^2\d\d$/)) {
return void cb('SERVER ERROR ' + req.statusCode);
}
var str = '';
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
try {
var json = JSON.parse(str);
limits = json;
var l;
if (publicKey) {
var limit = limits[publicKey];
l = limit && typeof limit.limit === "number" ? limit.limit : DEFAULT_LIMIT;
}
cb(void 0, l);
} catch (e) {
cb(e);
}
});
});
req.on('error', function (e) {
if (!config.domain) { return cb(); }
cb(e);
});
req.end(body);
};
var getLimit = function (publicKey, cb) {
var limit = limits[publicKey];
cb(void 0, limit && typeof(limit.limit) === "number"?
limit.limit : DEFAULT_LIMIT);
}; };
var safeMkdir = function (path, cb) { var safeMkdir = function (path, cb) {
@ -714,10 +773,16 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
}); });
case 'GET_FILE_SIZE': case 'GET_FILE_SIZE':
return void getFileSize(ctx.store, msg[1], Respond); return void getFileSize(ctx.store, msg[1], Respond);
case 'GET_LIMIT': // TODO implement this and cache it per-user case 'UPDATE_LIMITS':
return void getLimit(function (e, limit) { return void updateLimits(config, safeKey, function (e, limit) {
if (e) { return void Respond(e); }
Respond(void 0, limit);
});
case 'GET_LIMIT':
return void getLimit(safeKey, function (e, limit) {
if (e) { return void Respond(e); }
limit = limit; limit = limit;
Respond('NOT_IMPLEMENTED'); Respond(void 0, limit);
}); });
case 'GET_MULTIPLE_FILE_SIZE': case 'GET_MULTIPLE_FILE_SIZE':
return void getMultipleFileSize(ctx.store, msg[1], function (e, dict) { return void getMultipleFileSize(ctx.store, msg[1], function (e, dict) {
@ -725,7 +790,6 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
Respond(void 0, dict); Respond(void 0, dict);
}); });
// restricted to privileged users... // restricted to privileged users...
case 'UPLOAD': case 'UPLOAD':
if (!privileged) { return deny(); } if (!privileged) { return deny(); }
@ -775,6 +839,14 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
handleMessage(session.privilege); handleMessage(session.privilege);
}; };
var updateLimitDaily = function () {
updateLimits(config, undefined, function (e) {
if (e) { console.error('Error updating the storage limits', e); }
});
};
updateLimitDaily();
setInterval(updateLimitDaily, 24*3600*1000);
Store.create({ Store.create({
filePath: pinPath, filePath: pinPath,
}, function (s) { }, function (s) {

@ -21,7 +21,7 @@ define([], function () {
.replace(/ +$/, "") .replace(/ +$/, "")
.split(" "); .split(" ");
var byteString = String.fromCharCode.apply(null, hexArray); var byteString = String.fromCharCode.apply(null, hexArray);
return window.btoa(byteString).replace(/\//g, '-').slice(0,-2); return window.btoa(byteString).replace(/\//g, '-').replace(/=+$/, '');
}; };
Util.base64ToHex = function (b64String) { Util.base64ToHex = function (b64String) {
@ -90,11 +90,21 @@ define([], function () {
}; };
Util.fetch = function (src, cb) { Util.fetch = function (src, cb) {
var done = false;
var CB = function (err, res) {
if (done) { return; }
done = true;
cb(err, res);
};
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.open("GET", src, true); xhr.open("GET", src, true);
xhr.responseType = "arraybuffer"; xhr.responseType = "arraybuffer";
xhr.onload = function () { xhr.onload = function () {
return void cb(void 0, new Uint8Array(xhr.response)); return void CB(void 0, new Uint8Array(xhr.response));
};
xhr.onerror = function () {
CB('XHR_ERROR');
}; };
xhr.send(null); xhr.send(null);
}; };

@ -746,8 +746,15 @@ define([
}); });
}; };
common.updatePinLimit = function (cb) {
if (!pinsReady()) { return void cb('[RPC_NOT_READY]'); }
rpc.getFileListSize(cb);
};
common.getPinLimit = function (cb) { common.getPinLimit = function (cb) {
cb(void 0, typeof(AppConfig.pinLimit) === 'number'? AppConfig.pinLimit: 1000); if (!pinsReady()) { return void cb('[RPC_NOT_READY]'); }
rpc.getFileListSize(cb);
//cb(void 0, typeof(AppConfig.pinLimit) === 'number'? AppConfig.pinLimit: 1000);
}; };
common.isOverPinLimit = function (cb) { common.isOverPinLimit = function (cb) {

File diff suppressed because one or more lines are too long

@ -121,6 +121,29 @@ define([
}); });
}; };
// Update the limit value for all the users and return the limit for your publicKey
exp.updatePinLimits = function (cb) {
rpc.send('UPDATE_LIMITS', undefined, function (e, response) {
if (e) { return void cb(e); }
if (response && typeof response === "number") {
cb (void 0, response);
} else {
cb('INVALID_RESPONSE');
}
});
};
// Get the storage limit associated with your publicKey
exp.getLimit = function (cb) {
rpc.send('GET_LIMIT', undefined, function (e, response) {
if (e) { return void cb(e); }
if (response && typeof response === "number") {
cb (void 0, response);
} else {
cb('INVALID_RESPONSE');
}
});
};
cb(e, exp); cb(e, exp);
}); });
}; };

@ -7,6 +7,12 @@ define([
var plainChunkLength = 128 * 1024; var plainChunkLength = 128 * 1024;
var cypherChunkLength = 131088; var cypherChunkLength = 131088;
var computeEncryptedSize = function (bytes, meta) {
var metasize = Nacl.util.decodeUTF8(JSON.stringify(meta)).length;
var chunks = Math.ceil(bytes / plainChunkLength);
return metasize + 18 + (chunks * 16) + bytes;
};
var encodePrefix = function (p) { var encodePrefix = function (p) {
return [ return [
65280, // 255 << 8 65280, // 255 << 8
@ -131,23 +137,15 @@ define([
var i = 0; var i = 0;
/*
0: metadata
1: u8
2: done
*/
var state = 0; var state = 0;
var next = function (cb) { var next = function (cb) {
if (state === 2) { return void cb(); }
var start; var start;
var end; var end;
var part; var part;
var box; var box;
// DONE
if (state === 2) { return void cb(); }
if (state === 0) { // metadata... if (state === 0) { // metadata...
part = new Uint8Array(plaintext); part = new Uint8Array(plaintext);
box = Nacl.secretbox(part, nonce, key); box = Nacl.secretbox(part, nonce, key);
@ -159,6 +157,7 @@ define([
var prefixed = new Uint8Array(encodePrefix(box.length) var prefixed = new Uint8Array(encodePrefix(box.length)
.concat(slice(box))); .concat(slice(box)));
state++; state++;
return void cb(void 0, prefixed); return void cb(void 0, prefixed);
} }
@ -184,5 +183,6 @@ define([
decrypt: decrypt, decrypt: decrypt,
encrypt: encrypt, encrypt: encrypt,
joinChunks: joinChunks, joinChunks: joinChunks,
computeEncryptedSize: computeEncryptedSize,
}; };
}); });

@ -36,6 +36,7 @@ define([
var key = Nacl.randomBytes(32); var key = Nacl.randomBytes(32);
var next = FileCrypto.encrypt(u8, metadata, key); var next = FileCrypto.encrypt(u8, metadata, key);
var estimate = FileCrypto.computeEncryptedSize(blob.byteLength, metadata);
var chunks = []; var chunks = [];
var sendChunk = function (box, cb) { var sendChunk = function (box, cb) {
@ -47,15 +48,21 @@ define([
}); });
}; };
var actual = 0;
var again = function (err, box) { var again = function (err, box) {
if (err) { throw new Error(err); } if (err) { throw new Error(err); }
if (box) { if (box) {
actual += box.length;
return void sendChunk(box, function (e) { return void sendChunk(box, function (e) {
if (e) { return console.error(e); } if (e) { return console.error(e); }
next(again); next(again);
}); });
} }
if (actual !== estimate) {
console.error('Estimated size does not match actual size');
}
// if not box then done // if not box then done
Cryptpad.rpc.send('UPLOAD_COMPLETE', '', function (e, res) { Cryptpad.rpc.send('UPLOAD_COMPLETE', '', function (e, res) {
if (e) { return void console.error(e); } if (e) { return void console.error(e); }
@ -168,11 +175,15 @@ define([
if (!uploadMode) { if (!uploadMode) {
var src = Cryptpad.getBlobPathFromHex(hexFileName); var src = Cryptpad.getBlobPathFromHex(hexFileName);
return Cryptpad.fetch(src, function (e, u8) { return Cryptpad.fetch(src, function (e, u8) {
if (e) { return void Cryptpad.alert(e); }
// now decrypt the u8 // now decrypt the u8
if (e) { return window.alert('error'); }
var cryptKey = secret.keys && secret.keys.fileKeyStr; var cryptKey = secret.keys && secret.keys.fileKeyStr;
var key = Nacl.util.decodeBase64(cryptKey); var key = Nacl.util.decodeBase64(cryptKey);
if (!u8 || !u8.length) {
return void Cryptpad.errorLoadingScreen(e);
}
FileCrypto.decrypt(u8, key, function (e, data) { FileCrypto.decrypt(u8, key, function (e, data) {
if (e) { if (e) {
Cryptpad.removeLoadingScreen(); Cryptpad.removeLoadingScreen();

@ -16,6 +16,8 @@
} }
media-tag * { media-tag * {
max-width: 100%; max-width: 100%;
margin: auto;
display: block;
} }
</style> </style>
</head> </head>

@ -20,6 +20,11 @@ define([
Cryptpad.addLoadingScreen(); Cryptpad.addLoadingScreen();
var andThen = function () { var andThen = function () {
$(window.document).on('decryption', function (e) {
var decrypted = e.originalEvent;
console.log(decrypted.blob, decrypted.metadata);
});
var $bar = $iframe.find('.toolbar-container'); var $bar = $iframe.find('.toolbar-container');
var secret = Cryptpad.getSecrets(); var secret = Cryptpad.getSecrets();

Loading…
Cancel
Save