diff --git a/bower.json b/bower.json
index 5704b3aec..a6fc85b41 100644
--- a/bower.json
+++ b/bower.json
@@ -29,7 +29,7 @@
"rangy": "rangy-release#~1.3.0",
"json.sortify": "~2.1.0",
"fabric.js": "fabric#~1.6.0",
- "hyperjson": "~1.3.1",
+ "hyperjson": "~1.4.0",
"textpatcher": "^1.3.0",
"proxy-polyfill": "^0.1.5",
"chainpad": "^0.3.0",
diff --git a/config.js.dist b/config.js.dist
index 91bf38d95..da80bb374 100644
--- a/config.js.dist
+++ b/config.js.dist
@@ -14,24 +14,35 @@ module.exports = {
* Examples are provided below
*/
-/*
httpHeaders: {
- "Content-Security-Policy": [
- "default-src 'none'",
- "style-src 'unsafe-inline' 'self'",
- "script-src 'self' 'unsafe-eval' 'unsafe-inline'",
- "child-src 'self' cryptpad.fr *.cryptpad.fr",
- "font-src 'self'",
- "connect-src 'self' wss://cryptpad.fr",
- // data: is used by codemirror, (insecure remote) images are included by
- // users of the wysiwyg who embed photos in their pads
- "img-src data: *",
- ].join('; '),
-
"X-XSS-Protection": "1; mode=block",
"X-Content-Type-Options": "nosniff",
// 'X-Frame-Options': 'SAMEORIGIN',
- },*/
+ },
+
+ contentSecurity: [
+ "default-src 'none'",
+ "style-src 'unsafe-inline' 'self'",
+ "script-src 'self'",
+ "child-src 'self' cryptpad.fr *.cryptpad.fr",
+ "font-src 'self'",
+ "connect-src 'self' wss://cryptpad.fr",
+ // data: is used by codemirror
+ "img-src 'self' data:",
+ ].join('; '),
+
+ // CKEditor requires significantly more lax content security policy in order to function.
+ padContentSecurity: [
+ "default-src 'none'",
+ "style-src 'unsafe-inline' 'self'",
+ // Unsafe inline, unsafe-eval are needed for ckeditor :(
+ "script-src 'self' 'unsafe-eval' 'unsafe-inline'",
+ "child-src 'self' cryptpad.fr *.cryptpad.fr",
+ "font-src 'self'",
+ "connect-src 'self' wss://cryptpad.fr",
+ // (insecure remote) images are included by users of the wysiwyg who embed photos in their pads
+ "img-src *",
+ ].join('; '),
httpPort: 3000,
@@ -51,7 +62,7 @@ module.exports = {
//websocketPort: 3000,
/* if you want to run a different version of cryptpad but using the same websocket
- * server, you should use the other server port as websocketPort and disable
+ * server, you should use the other server port as websocketPort and disable
* the websockets on that server
*/
//useExternalWebsocket: false,
diff --git a/customize.dist/about.html b/customize.dist/about.html
index c0f3a0b97..988efafc3 100644
--- a/customize.dist/about.html
+++ b/customize.dist/about.html
@@ -1,5 +1,6 @@
+
Cryptpad: Zero Knowledge, Collaborative Real Time Editing
@@ -9,16 +10,8 @@
-
+
-
-
-
@@ -126,4 +119,3 @@
-
diff --git a/customize.dist/contact.html b/customize.dist/contact.html
index 7b2cd03ae..1985d8347 100644
--- a/customize.dist/contact.html
+++ b/customize.dist/contact.html
@@ -1,5 +1,6 @@
+
Cryptpad: Zero Knowledge, Collaborative Real Time Editing
@@ -9,16 +10,8 @@
-
+
-
-
-
@@ -123,4 +116,3 @@
-
diff --git a/customize.dist/index.html b/customize.dist/index.html
index eb1815e34..12697787e 100644
--- a/customize.dist/index.html
+++ b/customize.dist/index.html
@@ -1,5 +1,6 @@
+
Cryptpad: Zero Knowledge, Collaborative Real Time Editing
@@ -9,16 +10,8 @@
-
+
-
-
-
@@ -127,4 +120,3 @@
-
diff --git a/customize.dist/toolbar.css b/customize.dist/toolbar.css
index de846b7bd..e0e0bda64 100644
--- a/customize.dist/toolbar.css
+++ b/customize.dist/toolbar.css
@@ -372,8 +372,8 @@
float: left;
margin-bottom: -1px;
}
-.cryptpad-toolbar-leftside .cryptpad-user-list {
- float: right;
+.cryptpad-toolbar-leftside .cryptpad-user-list pre {
+ white-space: pre;
}
.cryptpad-toolbar-leftside button {
margin: 2px 4px 2px 0px;
diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js
index c32f346eb..d04b3d015 100644
--- a/customize.dist/translations/messages.js
+++ b/customize.dist/translations/messages.js
@@ -50,10 +50,8 @@ define(function () {
out.orangeLight = "Your slow connection may impact your experience";
out.redLight = "You are disconnected from the session";
- out.importButton = 'IMPORT';
out.importButtonTitle = 'Import a pad from a local file';
- out.exportButton = 'EXPORT';
out.exportButtonTitle = 'Export this pad to a local file';
out.exportPrompt = 'What would you like to name your file?';
@@ -64,7 +62,6 @@ define(function () {
out.clickToEdit = "Click to edit";
- out.forgetButton = 'FORGET';
out.forgetButtonTitle = 'Move this pad to the trash';
out.forgetPrompt = 'Clicking OK will move this pad to your trash. Are you sure?';
out.movedToTrash = 'That pad has been moved to the trash. Access my Drive';
@@ -75,19 +72,14 @@ define(function () {
out.newButton = 'New';
out.newButtonTitle = 'Create a new pad';
- out.presentButton = 'PRESENT';
out.presentButtonTitle = "Enter presentation mode";
out.presentSuccess = 'Hit ESC to exit presentation mode';
- out.sourceButton = 'VIEW SOURCE'; //TODO remove? hidden behind the present mode
- out.sourceButtonTitle = "Leave presentation mode";
- out.backgroundButton = 'BACKGROUND COLOR';
out.backgroundButtonTitle = 'Change the background color in the presentation';
- out.colorButton = 'TEXT COLOR';
out.colorButtonTitle = 'Change the text color in presentation mode';
out.editShare = "Editing link";
- out.editShareTitle = "Copy the edit link to clipboard";
+ out.editShareTitle = "Copy the editing link to clipboard";
out.viewShare = "Read-only link";
out.viewShareTitle = "Copy the read-only link to clipboard";
out.viewOpen = "Open read-only link in new tab";
@@ -110,7 +102,6 @@ define(function () {
out.poll_p_save = "Your settings are updated instantly, so you never need to save.";
out.poll_p_encryption = "All your input is encrypted so only people who have the link can access it. Even the server cannot see what you change.";
- out.wizardButton = 'WIZARD';
out.wizardLog = "Click the button in the top left to return to your poll";
out.wizardTitle = "Use the wizard to create your poll";
out.wizardConfirm = "Are you really ready to add these options to your poll?";
@@ -221,7 +212,7 @@ define(function () {
out.login_noSuchUser = 'Invalid username or password. Try again, or sign up';
out.login_invalUser = 'Username required';
out.login_invalPass = 'Password required';
- out.login_unhandledError = 'An unexpected error occured :(';
+ out.login_unhandledError = 'An unexpected error occurred :(';
out.register_importRecent = "Import pad history (Recommended)";
out.register_acceptTerms = "I accept the terms of service";
diff --git a/package.json b/package.json
index 05b1862fe..ba331a899 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "cryptpad",
"description": "realtime collaborative visual editor with zero knowlege server",
- "version": "1.1.0",
+ "version": "1.1.1",
"dependencies": {
"express": "~4.10.1",
"ws": "^1.0.1",
diff --git a/server.js b/server.js
index 548a78949..503558c1f 100644
--- a/server.js
+++ b/server.js
@@ -7,6 +7,7 @@ var Https = require('https');
var Fs = require('fs');
var WebSocketServer = require('ws').Server;
var NetfluxSrv = require('./NetfluxWebsocketSrv');
+var Package = require('./package.json');
var config = require('./config');
var websocketPort = config.websocketPort || config.httpPort;
@@ -19,20 +20,31 @@ var app = Express();
var httpsOpts;
+const clone = (x) => (JSON.parse(JSON.stringify(x)));
+
var setHeaders = (function () {
if (typeof(config.httpHeaders) !== 'object') { return function () {}; }
- var headers = JSON.parse(JSON.stringify(config.httpHeaders));
+ const headers = clone(config.httpHeaders);
+ if (config.contentSecurity) {
+ headers['Content-Security-Policy'] = clone(config.contentSecurity);
+ }
+ const padHeaders = clone(headers);
+ if (config.padContentSecurity) {
+ padHeaders['Content-Security-Policy'] = clone(config.padContentSecurity);
+ }
if (Object.keys(headers).length) {
- return function (res) {
- for (var header in headers) { res.setHeader(header, headers[header]); }
+ return function (req, res) {
+ const h = /^\/pad\/inner\.html.*/.test(req.url) ? padHeaders : headers;
+ for (let header in h) { res.setHeader(header, h[header]); }
};
}
return function () {};
}());
app.use(function (req, res, next) {
- setHeaders(res);
+ setHeaders(req, res);
+ if (/[\?\&]ver=[^\/]+$/.test(req.url)) { res.setHeader("Cache-Control", "max-age=31536000"); }
next();
});
@@ -82,6 +94,10 @@ app.get('/api/config', function(req, res){
var host = req.headers.host.replace(/\:[0-9]+/, '');
res.setHeader('Content-Type', 'text/javascript');
res.send('define(' + JSON.stringify({
+ requireConf: {
+ waitSeconds: 60,
+ urlArgs: 'ver=' + Package.version
+ },
websocketPath: config.useExternalWebsocket ? undefined : config.websocketPath,
websocketURL:'ws' + ((useSecureWebsockets) ? 's' : '') + '://' + host + ':' +
websocketPort + '/cryptpad_websocket',
diff --git a/www/code/index.html b/www/code/index.html
index df3fe1142..af6247a40 100644
--- a/www/code/index.html
+++ b/www/code/index.html
@@ -4,13 +4,7 @@
CryptPad
-
-
+