diff --git a/.jshintrc b/.jshintrc
index aeddcda04..c95e9dbc4 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -7,7 +7,6 @@
"iterator": true,
"latedef": true,
"nocomma": true,
- "notypeof": true,
"shadow": false,
"undef": true,
"unused": true,
diff --git a/config.example.js b/config.example.js
index ce38b5c3a..3a097eb87 100644
--- a/config.example.js
+++ b/config.example.js
@@ -159,6 +159,24 @@ module.exports = {
*/
defaultStorageLimit: 50 * 1024 * 1024,
+ /*
+ * CryptPad allows administrators to give custom limits to their friends.
+ * add an entry for each friend, identified by their user id,
+ * which can be found on the settings page. Include a 'limit' (number of bytes),
+ * a 'plan' (string), and a 'note' (string).
+ *
+ * hint: 1GB is 1024 * 1024 * 1024 bytes
+ */
+ customLimits: {
+ /*
+ "https://my.awesome.website/user/#/1/cryptpad-user/YZgXQxKR0Rcb6r6CmxHPdAGLVludrAF2lEnkbx1vVOo=": {
+ limit: 20 * 1024 * 1024 * 1024,
+ plan: 'insider',
+ note: 'storage space donated by my.awesome.website'
+ }
+ */
+ },
+
/*
* By default, CryptPad also contacts our accounts server once a day to check for changes in
* the people who have accounts. This check-in will also send the version of your CryptPad
diff --git a/customize.dist/four-oh-four.js b/customize.dist/four-oh-four.js
index 91752b190..ab19f577d 100644
--- a/customize.dist/four-oh-four.js
+++ b/customize.dist/four-oh-four.js
@@ -18,7 +18,7 @@ define([
var loggedIn = LocalStore.isLoggedIn();
var link = h('a#cp-link', {
href: loggedIn? '/drive/': '/',
- }, loggedIn? Messages.four04_goToDrive: Messages.four04_goToHome);
+ }, loggedIn? Messages.header_logoTitle: Messages.header_homeTitle);
var content = h('div#cp-main', [
img,
@@ -68,10 +68,10 @@ define([
};
};
- makeDecryptor(brand, 90, 4, function () { })();
+ makeDecryptor(brand, 70, 2, function () { })();
makeDecryptor(title, 50, 14, function () { })();
- makeDecryptor(link, 20, 10, function () {})();
- makeDecryptor(message, 12, 5, function () {
+ makeDecryptor(link, 20, 4, function () {})();
+ makeDecryptor(message, 12, 3, function () {
console.log('done');
})();
});
diff --git a/customize.dist/src/less/bar.less b/customize.dist/src/less/bar.less
index 91744728b..289cdf265 100644
--- a/customize.dist/src/less/bar.less
+++ b/customize.dist/src/less/bar.less
@@ -1,5 +1,5 @@
/* Bottom Bar */
-@import (once) "../less2/include/colortheme.less";
+@import (once) "../less2/include/colortheme-all.less";
.top-bar, .bottom-bar {
position:fixed;
diff --git a/customize.dist/src/less/cryptpad.less b/customize.dist/src/less/cryptpad.less
index 12168ec88..23f7d7899 100644
--- a/customize.dist/src/less/cryptpad.less
+++ b/customize.dist/src/less/cryptpad.less
@@ -2,7 +2,7 @@
@import "./mixins.less";
@import "../less2/include/alertify.less";
-@import "../less2/include/colortheme.less";
+@import "../less2/include/colortheme-all.less";
@import "../less2/include/modal.less";
@import "../less2/include/font.less";
@import "../less2/loading.less";
diff --git a/customize.dist/src/less/footer.less b/customize.dist/src/less/footer.less
index 97b5bda8c..4baa4f04e 100644
--- a/customize.dist/src/less/footer.less
+++ b/customize.dist/src/less/footer.less
@@ -1,5 +1,5 @@
@import "./variables.less";
-@import (once) "../less2/include/colortheme.less";
+@import (once) "../less2/include/colortheme-all.less";
footer {
background: @category-bg;
diff --git a/customize.dist/src/less/sidebar-layout.less b/customize.dist/src/less/sidebar-layout.less
index 47e4e86f9..27bb67099 100644
--- a/customize.dist/src/less/sidebar-layout.less
+++ b/customize.dist/src/less/sidebar-layout.less
@@ -1,6 +1,6 @@
@import '/customize/src/less/variables.less';
@import '/customize/src/less/mixins.less';
-@import (once) "/customize/src/less2/include/colortheme.less";
+@import (once) "/customize/src/less2/include/colortheme-all.less";
@leftside-bg: @colortheme_sidebar-left-bg;
@leftside-color: @colortheme_sidebar-left-fg;
diff --git a/customize.dist/src/less/toolbar.less b/customize.dist/src/less/toolbar.less
index aadc0b6b0..126c08c8c 100644
--- a/customize.dist/src/less/toolbar.less
+++ b/customize.dist/src/less/toolbar.less
@@ -2,7 +2,7 @@
@import "./mixins.less";
@import (once) "../less2/include/dropdown.less";
-@import (once) "../less2/include/colortheme.less";
+@import (once) "../less2/include/colortheme-all.less";
@import (once) "../less2/include/ckeditor-fix.less";
@import (once) "../less2/include/icon-colors.less";
diff --git a/customize.dist/src/less/topbar.less b/customize.dist/src/less/topbar.less
index 2f7f55edb..154d44b29 100644
--- a/customize.dist/src/less/topbar.less
+++ b/customize.dist/src/less/topbar.less
@@ -1,5 +1,5 @@
@import "./variables.less";
-@import (once) "../less2/include/colortheme.less";
+@import (once) "../less2/include/colortheme-all.less";
#cryptpadTopBar {
background: @topbar-back;
diff --git a/customize.dist/src/less/variables.less b/customize.dist/src/less/variables.less
index 1d3415d89..74cd0fca7 100644
--- a/customize.dist/src/less/variables.less
+++ b/customize.dist/src/less/variables.less
@@ -1,4 +1,4 @@
-@import (once) '../less2/include/colortheme.less';
+@import (once) '../less2/include/colortheme-all.less';
@import (once) '../less2/include/browser.less';
@base: @colortheme_base;
diff --git a/customize.dist/src/less2/include/colortheme-all.less b/customize.dist/src/less2/include/colortheme-all.less
new file mode 100644
index 000000000..0495ff076
--- /dev/null
+++ b/customize.dist/src/less2/include/colortheme-all.less
@@ -0,0 +1,6 @@
+// Don't override/edit this file directly, you can create
+// create a file: customize/src/less2/include/colortheme.less
+// override whatever colors you want. When you update, the new colors will be
+// added ok because the original file is pulled in first.
+@import (once) "/customize.dist/src/less2/include/colortheme.less";
+@import (once) "/customize/src/less2/include/colortheme.less";
\ No newline at end of file
diff --git a/customize.dist/src/less2/include/colortheme.less b/customize.dist/src/less2/include/colortheme.less
index 4893f5fa2..8cebdaf20 100644
--- a/customize.dist/src/less2/include/colortheme.less
+++ b/customize.dist/src/less2/include/colortheme.less
@@ -42,42 +42,54 @@
@colortheme_pad-bg: #1c4fa0;
@colortheme_pad-color: #fff;
@colortheme_pad-toolbar-bg: #c1e7ff;
+@colortheme_pad-warn: #F83A3A;
@colortheme_slide-bg: #e57614;
@colortheme_slide-color: #fff;
+@colortheme_slide-warn: #7bccd1;
@colortheme_code-bg: #ffae00;
@colortheme_code-color: #000;
+@colortheme_code-warn: #005bef;
@colortheme_poll-bg: #006304;
@colortheme_poll-color: #fff;
@colortheme_poll-help-bg: #bbffbb;
@colortheme_poll-th-bg: #005bef;
@colortheme_poll-th-fg: #fff;
+@colortheme_poll-warn: #cd2532;
@colortheme_whiteboard-bg: #800080;
@colortheme_whiteboard-color: #fff;
+@colortheme_whiteboard-warn: #ffae00;
@colortheme_drive-bg: #0087ff;
@colortheme_drive-color: #fff;
+@colortheme_drive-warn: #cd2532;
@colortheme_file-bg: #cd2532;
@colortheme_file-color: #fff;
+@colortheme_file-warn: #ffae00;
@colortheme_friends-bg: #607b8d;
@colortheme_friends-color: #fff;
+@colortheme_friends-warn: #cd2532;
@colortheme_default-bg: #ddd;
@colortheme_default-color: #000;
+@colortheme_default-warn: #cd2532;
@colortheme_settings-bg: #0087ff;
@colortheme_settings-color: #fff;
+@colortheme_settings-warn: #cd2532;
@colortheme_profile-bg: #0087ff;
@colortheme_profile-color: #fff;
+@colortheme_profile-warn: #cd2532;
@colortheme_todo-bg: #7bccd1;
@colortheme_todo-color: #000;
+@colortheme_todo-warn: #cd2532;
// Sidebar layout (profile / settings)
@colortheme_sidebar-active: #fff;
diff --git a/customize.dist/src/less2/include/sidebar-layout.less b/customize.dist/src/less2/include/sidebar-layout.less
index 2d667cee5..89d23d946 100644
--- a/customize.dist/src/less2/include/sidebar-layout.less
+++ b/customize.dist/src/less2/include/sidebar-layout.less
@@ -1,4 +1,4 @@
-@import (once) "/customize/src/less2/include/colortheme.less";
+@import (once) "/customize/src/less2/include/colortheme-all.less";
@import (once) "/customize/src/less2/include/leftside-menu.less";
@leftside-bg: @colortheme_sidebar-left-bg;
diff --git a/customize.dist/src/less2/include/toolbar.less b/customize.dist/src/less2/include/toolbar.less
index 5143e4872..4e955af6c 100644
--- a/customize.dist/src/less2/include/toolbar.less
+++ b/customize.dist/src/less2/include/toolbar.less
@@ -7,6 +7,7 @@
@import (once) "./icon-colors.less";
@import (once) "./tools.less";
+@_cp-toolbar-color-warn: black;
.toolbar_main () {
@@ -224,6 +225,7 @@
}
.cp-toolbar-limit {
text-shadow: -1px 0 @color, 0 1px @color, 1px 0 @color, 0 -1px @color;
+ color: @_cp-toolbar-color-warn;
}
.cp-toolbar-leftside, .cp-toolbar-rightside {
background-color: lighten(@bgcolor, 8%);
@@ -238,6 +240,19 @@
width: 100%;
}
}
+ .cp-pad-not-pinned {
+ padding-left: 20px;
+ font-size: @colortheme_app-font-size;
+ color: @_cp-toolbar-color-warn;
+ a {
+ font-size: @colortheme_app-font-size;
+ font-weight: bold;
+ color: @_cp-toolbar-color-warn;
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+ }
.cp-toolbar-title-hoverable:hover {
.cp-toolbar-title-editable, .cp-toolbar-title-edit {
cursor: text;
@@ -383,7 +398,6 @@
vertical-align: middle;
line-height: @toolbar_top-height;
span {
- color: red;
cursor: pointer;
margin: auto;
font-size: 20px;
diff --git a/customize.dist/src/less2/loading.less b/customize.dist/src/less2/loading.less
index 504e1e393..e13a56de6 100644
--- a/customize.dist/src/less2/loading.less
+++ b/customize.dist/src/less2/loading.less
@@ -3,7 +3,7 @@ WARNING: THIS FILE DOES NOTHING
It exists only as a proposal of what CSS you should use in loading.js
The CSS inside of loading.js is precompiled in order to save 200ish milliseconds to the loading screen.
*/
-@import (once) "./include/colortheme.less";
+@import (once) "./include/colortheme-all.less";
@import (once) "./include/browser.less";
#cp-loading {
diff --git a/customize.dist/src/less2/pages/page-about.less b/customize.dist/src/less2/pages/page-about.less
index d356fecd0..f8decce8f 100644
--- a/customize.dist/src/less2/pages/page-about.less
+++ b/customize.dist/src/less2/pages/page-about.less
@@ -1,5 +1,5 @@
@import (once) "../include/infopages.less";
-@import (once) "../include/colortheme.less";
+@import (once) "../include/colortheme-all.less";
.infopages_main();
.infopages_topbar();
diff --git a/customize.dist/src/less2/pages/page-contact.less b/customize.dist/src/less2/pages/page-contact.less
index a8ce6fa04..19bbd57a2 100644
--- a/customize.dist/src/less2/pages/page-contact.less
+++ b/customize.dist/src/less2/pages/page-contact.less
@@ -1,5 +1,5 @@
@import (once) "../include/infopages.less";
-@import (once) "../include/colortheme.less";
+@import (once) "../include/colortheme-all.less";
.infopages_main();
.infopages_topbar();
diff --git a/customize.dist/src/less2/pages/page-index.less b/customize.dist/src/less2/pages/page-index.less
index 90a765a4a..49e179b75 100644
--- a/customize.dist/src/less2/pages/page-index.less
+++ b/customize.dist/src/less2/pages/page-index.less
@@ -1,7 +1,7 @@
//@import (once) "./variables.less";
@import (once) "../include/infopages.less";
-@import (once) "../include/colortheme.less";
+@import (once) "../include/colortheme-all.less";
.infopages_main();
diff --git a/customize.dist/src/less2/pages/page-login.less b/customize.dist/src/less2/pages/page-login.less
index 2b8064486..28916f730 100644
--- a/customize.dist/src/less2/pages/page-login.less
+++ b/customize.dist/src/less2/pages/page-login.less
@@ -1,5 +1,5 @@
@import (once) "../include/infopages.less";
-@import (once) "../include/colortheme.less";
+@import (once) "../include/colortheme-all.less";
@import (once) "../include/alertify.less";
@import (once) "../loading.less";
diff --git a/customize.dist/src/less2/pages/page-privacy.less b/customize.dist/src/less2/pages/page-privacy.less
index 59fa4b1fd..a1f8b2955 100644
--- a/customize.dist/src/less2/pages/page-privacy.less
+++ b/customize.dist/src/less2/pages/page-privacy.less
@@ -1,5 +1,5 @@
@import (once) "../include/infopages.less";
-@import (once) "../include/colortheme.less";
+@import (once) "../include/colortheme-all.less";
.infopages_main();
.infopages_topbar();
diff --git a/customize.dist/src/less2/pages/page-register.less b/customize.dist/src/less2/pages/page-register.less
index af2e06d51..311e877a4 100644
--- a/customize.dist/src/less2/pages/page-register.less
+++ b/customize.dist/src/less2/pages/page-register.less
@@ -1,5 +1,5 @@
@import (once) "../include/infopages.less";
-@import (once) "../include/colortheme.less";
+@import (once) "../include/colortheme-all.less";
@import (once) "../include/alertify.less";
@import (once) "../loading.less";
diff --git a/customize.dist/src/less2/pages/page-terms.less b/customize.dist/src/less2/pages/page-terms.less
index 59fa4b1fd..a1f8b2955 100644
--- a/customize.dist/src/less2/pages/page-terms.less
+++ b/customize.dist/src/less2/pages/page-terms.less
@@ -1,5 +1,5 @@
@import (once) "../include/infopages.less";
-@import (once) "../include/colortheme.less";
+@import (once) "../include/colortheme-all.less";
.infopages_main();
.infopages_topbar();
diff --git a/customize.dist/src/less2/pages/page-what-is-cryptpad.less b/customize.dist/src/less2/pages/page-what-is-cryptpad.less
index cf127e1ec..de7e552f2 100644
--- a/customize.dist/src/less2/pages/page-what-is-cryptpad.less
+++ b/customize.dist/src/less2/pages/page-what-is-cryptpad.less
@@ -1,5 +1,5 @@
@import (once) "../include/infopages.less";
-@import (once) "../include/colortheme.less";
+@import (once) "../include/colortheme-all.less";
.infopages_main();
.infopages_topbar();
diff --git a/customize.dist/translations/messages.fr.js b/customize.dist/translations/messages.fr.js
index 81b8c9421..0ba3413a3 100644
--- a/customize.dist/translations/messages.fr.js
+++ b/customize.dist/translations/messages.fr.js
@@ -683,10 +683,8 @@ define(function () {
out.tos_logs = "Les meta-données fournies par votre navigateur au serveur peuvent être enregistrées dans le but de maintenir le service.";
out.tos_3rdparties = "Nous ne fournissons aucune donnée individuelle à des tierces parties à moins d'y être contraints par la loi.";
- // BottomBar.html
-
- out.bottom_france = 'Fait avec en ';
- out.bottom_support = 'Un projet Labs avec le soutien de ';
+ // 404 page
+ out.four04_pageNotFound = "Nous n'avons pas trouvé la page que vous cherchez.";
// Header.html
diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js
index 160cf72fd..90ce1871e 100644
--- a/customize.dist/translations/messages.js
+++ b/customize.dist/translations/messages.js
@@ -31,6 +31,7 @@ define(function () {
out.typeError = "This pad is not compatible with the selected application";
out.onLogout = 'You are logged out, click here to log in
or press Escape to access your pad in read-only mode.';
out.wrongApp = "Unable to display the content of that realtime session in your browser. Please try to reload that page.";
+ out.padNotPinned = 'This pad will expire in 3 months, login or register to preserve it.';
out.loading = "Loading...";
out.error = "Error";
@@ -690,9 +691,8 @@ define(function () {
out.tos_logs = "Metadata provided by your browser to the server may be logged for the purpose of maintaining the service.";
out.tos_3rdparties = "We do not provide individualized data to third parties unless required to by law.";
+ // 404 page
out.four04_pageNotFound = "We couldn't find the page you were looking for.";
- out.four04_goToHome = "Go to the home page.";
- out.four04_goToDrive = "Go to my CryptDrive.";
// BottomBar.html
diff --git a/pinned.js b/pinned.js
new file mode 100644
index 000000000..372ed2d10
--- /dev/null
+++ b/pinned.js
@@ -0,0 +1,74 @@
+/* jshint esversion: 6, node: true */
+const Fs = require('fs');
+const Semaphore = require('saferphore');
+const nThen = require('nthen');
+
+const sema = Semaphore.create(20);
+
+let dirList;
+const fileList = [];
+const pinned = {};
+
+const hashesFromPinFile = (pinFile, fileName) => {
+ var pins = {};
+ pinFile.split('\n').filter((x)=>(x)).map((l) => JSON.parse(l)).forEach((l) => {
+ switch (l[0]) {
+ case 'RESET': {
+ pins = {};
+ //jshint -W086
+ // fallthrough
+ }
+ case 'PIN': {
+ l[1].forEach((x) => { pins[x] = 1; });
+ break;
+ }
+ case 'UNPIN': {
+ l[1].forEach((x) => { delete pins[x]; });
+ break;
+ }
+ default: throw new Error(JSON.stringify(l) + ' ' + fileName);
+ }
+ });
+ return Object.keys(pins);
+};
+
+module.exports.load = function (cb) {
+ nThen((waitFor) => {
+ Fs.readdir('./pins', waitFor((err, list) => {
+ if (err) { throw err; }
+ dirList = list;
+ }));
+ }).nThen((waitFor) => {
+ fileList.splice(0, fileList.length);
+ dirList.forEach((f) => {
+ sema.take((returnAfter) => {
+ Fs.readdir('./pins/' + f, waitFor(returnAfter((err, list2) => {
+ if (err) { throw err; }
+ list2.forEach((ff) => { fileList.push('./pins/' + f + '/' + ff); });
+ })));
+ });
+ });
+ }).nThen((waitFor) => {
+ fileList.forEach((f) => {
+ sema.take((returnAfter) => {
+ Fs.readFile(f, waitFor(returnAfter((err, content) => {
+ if (err) { throw err; }
+ const hashes = hashesFromPinFile(content.toString('utf8'), f);
+ hashes.forEach((x) => {
+ (pinned[x] = pinned[x] || {})[f.replace(/.*\/([^/]*).ndjson$/, (x, y)=>y)] = 1;
+ });
+ })));
+ });
+ });
+ }).nThen(() => {
+ cb(pinned);
+ });
+};
+
+if (!module.parent) {
+ module.exports.load(function (data) {
+ Object.keys(data).forEach(function (x) {
+ console.log(x + ' ' + JSON.stringify(data[x]));
+ });
+ });
+}
\ No newline at end of file
diff --git a/rpc.js b/rpc.js
index b0e3a0e6d..60bc00ac3 100644
--- a/rpc.js
+++ b/rpc.js
@@ -10,6 +10,7 @@ var Fs = require("fs");
var Path = require("path");
var Https = require("https");
const Package = require('./package.json');
+const Pinned = require('./pinned');
var RPC = module.exports;
@@ -212,7 +213,6 @@ var checkSignature = function (signedMsg, signature, publicKey) {
};
var loadUserPins = function (Env, publicKey, cb) {
- var pinStore = Env.pinStore;
var session = beginSession(Env.Sessions, publicKey);
if (session.channels) {
@@ -230,7 +230,7 @@ var loadUserPins = function (Env, publicKey, cb) {
pins[channel] = false;
};
- pinStore.getMessages(publicKey, function (msg) {
+ Env.pinStore.getMessages(publicKey, function (msg) {
// handle messages...
var parsed;
try {
@@ -325,9 +325,8 @@ var getFileSize = function (Env, channel, cb) {
};
var getMultipleFileSize = function (Env, channels, cb) {
- var msgStore = Env.msgStore;
if (!Array.isArray(channels)) { return cb('INVALID_PIN_LIST'); }
- if (typeof(msgStore.getChannelSize) !== 'function') {
+ if (typeof(Env.msgStore.getChannelSize) !== 'function') {
return cb('GET_CHANNEL_SIZE_UNSUPPORTED');
}
@@ -428,6 +427,28 @@ var updateLimits = function (config, publicKey, cb /*:(?string, ?any[])=>void*/)
"Content-Length": Buffer.byteLength(body)
}
};
+
+ // read custom limits from the config
+ var customLimits = (function (custom) {
+ var limits = {};
+ Object.keys(custom).forEach(function (k) {
+ k.replace(/\/([^\/]+)$/, function (all, safeKey) {
+ var id = unescapeKeyCharacters(safeKey || '');
+ limits[id] = custom[k];
+ return '';
+ });
+ });
+ return limits;
+ }(config.customLimits || {}));
+
+ var isLimit = function (o) {
+ var valid = o && typeof(o) === 'object' &&
+ typeof(o.limit) === 'number' &&
+ typeof(o.plan) === 'string' &&
+ typeof(o.note) === 'string';
+ return valid;
+ };
+
var req = Https.request(options, function (response) {
if (!('' + response.statusCode).match(/^2\d\d$/)) {
return void cb('SERVER ERROR ' + response.statusCode);
@@ -442,6 +463,11 @@ var updateLimits = function (config, publicKey, cb /*:(?string, ?any[])=>void*/)
try {
var json = JSON.parse(str);
limits = json;
+ Object.keys(customLimits).forEach(function (k) {
+ if (!isLimit(customLimits[k])) { return; }
+ limits[k] = customLimits[k];
+ });
+
var l;
if (userId) {
var limit = limits[userId];
@@ -499,6 +525,54 @@ var sumChannelSizes = function (sizes) {
.reduce(function (a, b) { return a + b; }, 0);
};
+// inform that the
+var loadChannelPins = function (Env) {
+ Pinned.load(function (data) {
+ Env.pinnedPads = data;
+ Env.evPinnedPadsReady.fire();
+ });
+};
+var addPinned = function (
+ Env,
+ publicKey /*:string*/,
+ channelList /*Array*/,
+ cb /*:()=>void*/)
+{
+ Env.evPinnedPadsReady.reg(() => {
+ channelList.forEach((c) => {
+ const x = Env.pinnedPads[c];
+ if (!x) { return; }
+ delete x[publicKey];
+ });
+ cb();
+ });
+};
+var removePinned = function (
+ Env,
+ publicKey /*:string*/,
+ channelList /*Array*/,
+ cb /*:()=>void*/)
+{
+ Env.evPinnedPadsReady.reg(() => {
+ channelList.forEach((c) => {
+ const x = Env.pinnedPads[c];
+ if (!x) { return; }
+ delete x[publicKey];
+ });
+ cb();
+ });
+};
+var isChannelPinned = function (Env, channel, cb) {
+ Env.evPinnedPadsReady.reg(() => {
+ if (Env.pinnedPads[channel] && Object.keys(Env.pinnedPads[channel]).length) {
+ cb(true);
+ } else {
+ delete Env.pinnedPads[channel];
+ cb(false);
+ }
+ });
+};
+
var pinChannel = function (Env, publicKey, channels, cb) {
if (!channels && channels.filter) {
return void cb('INVALID_PIN_LIST');
@@ -534,6 +608,7 @@ var pinChannel = function (Env, publicKey, channels, cb) {
toStore.forEach(function (channel) {
session.channels[channel] = true;
});
+ addPinned(Env, publicKey, toStore, () => {});
getHash(Env, publicKey, cb);
});
});
@@ -542,7 +617,6 @@ var pinChannel = function (Env, publicKey, channels, cb) {
};
var unpinChannel = function (Env, publicKey, channels, cb) {
- var pinStore = Env.pinStore;
if (!channels && channels.filter) {
// expected array
return void cb('INVALID_PIN_LIST');
@@ -560,13 +634,13 @@ var unpinChannel = function (Env, publicKey, channels, cb) {
return void getHash(Env, publicKey, cb);
}
- pinStore.message(publicKey, JSON.stringify(['UNPIN', toStore]),
+ Env.pinStore.message(publicKey, JSON.stringify(['UNPIN', toStore]),
function (e) {
if (e) { return void cb(e); }
toStore.forEach(function (channel) {
delete session.channels[channel];
});
-
+ removePinned(Env, publicKey, toStore, () => {});
getHash(Env, publicKey, cb);
});
});
@@ -574,7 +648,6 @@ var unpinChannel = function (Env, publicKey, channels, cb) {
var resetUserPins = function (Env, publicKey, channelList, cb) {
if (!Array.isArray(channelList)) { return void cb('INVALID_PIN_LIST'); }
- var pinStore = Env.pinStore;
var session = beginSession(Env.Sessions, publicKey);
if (!channelList.length) {
@@ -605,13 +678,18 @@ var resetUserPins = function (Env, publicKey, channelList, cb) {
They will not be able to pin additional pads until they upgrade
or delete enough files to go back under their limit. */
if (pinSize > limit[0] && session.hasPinned) { return void(cb('E_OVER_LIMIT')); }
- pinStore.message(publicKey, JSON.stringify(['RESET', channelList]),
+ Env.pinStore.message(publicKey, JSON.stringify(['RESET', channelList]),
function (e) {
if (e) { return void cb(e); }
channelList.forEach(function (channel) {
pins[channel] = true;
});
+ var oldChannels = Object.keys(session.channels);
+ removePinned(Env, publicKey, oldChannels, () => {
+ addPinned(Env, publicKey, channelList, ()=>{});
+ });
+
// update in-memory cache IFF the reset was allowed.
session.channels = pins;
getHash(Env, publicKey, function (e, hash) {
@@ -879,6 +957,7 @@ var isUnauthenticatedCall = function (call) {
return [
'GET_FILE_SIZE',
'GET_MULTIPLE_FILE_SIZE',
+ 'IS_CHANNEL_PINNED',
].indexOf(call) !== -1;
};
@@ -894,10 +973,31 @@ var isAuthenticatedCall = function (call) {
'GET_LIMIT',
'UPLOAD_COMPLETE',
'UPLOAD_CANCEL',
- 'EXPIRE_SESSION',
+ 'EXPIRE_SESSION'
].indexOf(call) !== -1;
};
+const mkEvent = function (once) {
+ var handlers = [];
+ var fired = false;
+ return {
+ reg: function (cb) {
+ if (once && fired) { return void setTimeout(cb); }
+ handlers.push(cb);
+ },
+ unreg: function (cb) {
+ if (handlers.indexOf(cb) === -1) { throw new Error("Not registered"); }
+ handlers.splice(handlers.indexOf(cb), 1);
+ },
+ fire: function () {
+ if (once && fired) { return; }
+ fired = true;
+ var args = Array.prototype.slice.call(arguments);
+ handlers.forEach(function (h) { h.apply(null, args); });
+ }
+ };
+};
+
/*::const ConfigType = require('./config.example.js');*/
RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)=>void*/) {
// load pin-store...
@@ -909,14 +1009,19 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
return typeof(config[key]) === 'string'? config[key]: def;
};
- var Env = {};
- Env.defaultStorageLimit = config.defaultStorageLimit;
-
- Env.maxUploadSize = config.maxUploadSize || (20 * 1024 * 1024);
-
- var Sessions = Env.Sessions = {};
+ var Env = {
+ defaultStorageLimit: config.defaultStorageLimit,
+ maxUploadSize: config.maxUploadSize || (20 * 1024 * 1024),
+ Sessions: {},
+ paths: {},
+ msgStore: (undefined /*:any*/),
+ pinStore: (undefined /*:any*/),
+ pinnedPads: {},
+ evPinnedPadsReady: mkEvent(true)
+ };
- var paths = Env.paths = {};
+ var Sessions = Env.Sessions;
+ var paths = Env.paths;
var pinPath = paths.pin = keyOrDefaultString('pinPath', './pins');
var blobPath = paths.blob = keyOrDefaultString('blobPath', './blob');
var blobStagingPath = paths.staging = keyOrDefaultString('blobStagingPath', './blobstage');
@@ -943,6 +1048,10 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
}
respond(e, [null, dict, null]);
});
+ case 'IS_CHANNEL_PINNED':
+ return void isChannelPinned(Env, msg[1], function (isPinned) {
+ respond(null, [null, isPinned, null]);
+ });
default:
console.error("unsupported!");
return respond('UNSUPPORTED_RPC_CALL', msg);
@@ -1174,6 +1283,8 @@ RPC.create = function (config /*:typeof(ConfigType)*/, cb /*:(?Error, ?Function)
updateLimitDaily();
setInterval(updateLimitDaily, 24*3600*1000);
+ loadChannelPins(Env);
+
Store.create({
filePath: pinPath,
}, function (s) {
diff --git a/server.js b/server.js
index 53e7bb9ad..4c64965fe 100644
--- a/server.js
+++ b/server.js
@@ -102,6 +102,7 @@ app.use("/blob", Express.static(Path.join(__dirname, (config.blobPath || './blob
app.use("/customize", Express.static(__dirname + '/customize'));
app.use("/customize", Express.static(__dirname + '/customize.dist'));
+app.use("/customize.dist", Express.static(__dirname + '/customize.dist'));
app.use(/^\/[^\/]*$/, Express.static('customize'));
app.use(/^\/[^\/]*$/, Express.static('customize.dist'));
diff --git a/www/code/app-code.less b/www/code/app-code.less
index 2541431ea..5025d4b3c 100644
--- a/www/code/app-code.less
+++ b/www/code/app-code.less
@@ -5,6 +5,8 @@
@import (once) '../../customize/src/less2/include/alertify.less';
@import (once) '../../customize/src/less2/include/tokenfield.less';
+@_cp-toolbar-color-warn: @colortheme_code-warn;
+
.toolbar_main();
.fileupload_main();
.alertify_main();
diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js
index 7ec06cb4f..60bcf0035 100644
--- a/www/common/cryptpad-common.js
+++ b/www/common/cryptpad-common.js
@@ -605,6 +605,7 @@ define([
var initialized = false;
return function (f, rdyCfg) {
+ rdyCfg = rdyCfg || {};
if (initialized) {
return void setTimeout(function () { f(void 0, env); });
}
diff --git a/www/common/file-dialog.less b/www/common/file-dialog.less
index d09c61f10..c27b6a377 100644
--- a/www/common/file-dialog.less
+++ b/www/common/file-dialog.less
@@ -1,4 +1,4 @@
-@import (once) '../customize/src/less2/include/colortheme.less';
+@import (once) '../customize/src/less2/include/colortheme-all.less';
@import '../customize/src/less2/include/modal.less';
.fileDialog_main () {
diff --git a/www/common/sframe-app-framework.js b/www/common/sframe-app-framework.js
index 1f7723cf3..b5620ca6f 100644
--- a/www/common/sframe-app-framework.js
+++ b/www/common/sframe-app-framework.js
@@ -461,7 +461,16 @@ define([
getHeadingText: function () { return titleRecommender(); }
}, onLocal);
var configTb = {
- displayed: ['userlist', 'title', 'useradmin', 'spinner', 'newpad', 'share', 'limit'],
+ displayed: [
+ 'userlist',
+ 'title',
+ 'useradmin',
+ 'spinner',
+ 'newpad',
+ 'share',
+ 'limit',
+ 'unpinnedWarning'
+ ],
title: title.getTitleConfig(),
metadataMgr: cpNfInner.metadataMgr,
readOnly: readOnly,
diff --git a/www/common/toolbar3.js b/www/common/toolbar3.js
index 5bc74b44f..5bdd8486d 100644
--- a/www/common/toolbar3.js
+++ b/www/common/toolbar3.js
@@ -719,6 +719,26 @@ define([
return $titleContainer;
};
+ var createUnpinnedWarning = function (toolbar, config) {
+ if (Common.isLoggedIn()) { return; }
+ var pd = config.metadataMgr.getPrivateData();
+ var o = pd.origin;
+ var hashes = pd.availableHashes;
+ var url = pd.origin + pd.pathname + '#' + (hashes.editHash || hashes.viewHash);
+ var cid = Hash.hrefToHexChannelId(url);
+ Common.sendAnonRpcMsg('IS_CHANNEL_PINNED', cid, function (x) {
+ if (x.error || !Array.isArray(x.response)) { return void console.log(x); }
+ if (x.response[0] === true) { return; }
+ var msg = $('', {
+ 'class': 'cp-pad-not-pinned',
+ }).append(
+ Messages._getKey('padNotPinned', [o + '/login', o + '/register'])
+ );
+ $('.cp-toolbar-title').append(msg);
+ console.log("This pad is not pinned");
+ });
+ };
+
var createPageTitle = function (toolbar, config) {
if (config.title || !config.pageTitle) { return; }
var $titleContainer = $('', {
@@ -1087,6 +1107,7 @@ define([
tb['upgrade'] = $.noop;
tb['newpad'] = createNewPad;
tb['useradmin'] = createUserAdmin;
+ tb['unpinnedWarning'] = createUnpinnedWarning;
var addElement = toolbar.addElement = function (arr, additionnalCfg, init) {
if (typeof additionnalCfg === "object") { $.extend(true, config, additionnalCfg); }
diff --git a/www/contacts/app-contacts.less b/www/contacts/app-contacts.less
index 6ae7a62da..26fba2c90 100644
--- a/www/contacts/app-contacts.less
+++ b/www/contacts/app-contacts.less
@@ -8,6 +8,7 @@
@import (once) '../../customize/src/less2/include/avatar.less';
+@_cp-toolbar-color-warn: @colortheme_friends-warn;;
.toolbar_main();
.fileupload_main();
diff --git a/www/drive/app-drive.less b/www/drive/app-drive.less
index cad82bc2f..17ae35fcb 100644
--- a/www/drive/app-drive.less
+++ b/www/drive/app-drive.less
@@ -8,6 +8,8 @@
@import (once) "../../customize/src/less2/include/limit-bar.less";
@import (once) "../../customize/src/less2/include/tokenfield.less";
+@_cp-toolbar-color-warn: @colortheme_drive-warn;
+
.toolbar_main();
.fileupload_main();
.alertify_main();
diff --git a/www/file/app-file.less b/www/file/app-file.less
index e2065d00f..7a990cb03 100644
--- a/www/file/app-file.less
+++ b/www/file/app-file.less
@@ -5,6 +5,8 @@
@import (once) '../../customize/src/less2/include/alertify.less';
@import (once) '../../customize/src/less2/include/tokenfield.less';
+@_cp-toolbar-color-warn: @colortheme_file-warn;
+
.toolbar_main();
.fileupload_main();
.alertify_main();
diff --git a/www/filepicker/app-filepicker.less b/www/filepicker/app-filepicker.less
index b148e5780..df1fec8fb 100644
--- a/www/filepicker/app-filepicker.less
+++ b/www/filepicker/app-filepicker.less
@@ -1,4 +1,4 @@
-@import (once) '../../customize/src/less2/include/colortheme.less';
+@import (once) '../../customize/src/less2/include/colortheme-all.less';
@import (once) '../../customize/src/less2/include/modal.less';
@import (once) '../../customize/src/less2/include/icon-colors.less';
@import (once) '../../customize/src/less2/include/fileupload.less';
diff --git a/www/pad/app-pad.less b/www/pad/app-pad.less
index 4bc6cac9d..6e34f473d 100644
--- a/www/pad/app-pad.less
+++ b/www/pad/app-pad.less
@@ -6,6 +6,8 @@
@import (once) '../../customize/src/less2/include/alertify.less';
@import (once) '../../customize/src/less2/include/tokenfield.less';
+@_cp-toolbar-color-warn: @colortheme_pad-warn;
+
.toolbar_main();
.alertify_main();
diff --git a/www/poll/app-poll.less b/www/poll/app-poll.less
index 08acd2b6b..f717a6f56 100644
--- a/www/poll/app-poll.less
+++ b/www/poll/app-poll.less
@@ -13,6 +13,8 @@
@import (once) '../../customize/src/less2/include/tools.less';
@import (once) '../../customize/src/less2/include/avatar.less';
+@_cp-toolbar-color-warn: @colortheme_poll-warn;
+
.toolbar_main();
.fileupload_main();
.alertify_main();
diff --git a/www/settings/app-settings.less b/www/settings/app-settings.less
index b3afcc257..b96384bc0 100644
--- a/www/settings/app-settings.less
+++ b/www/settings/app-settings.less
@@ -1,10 +1,12 @@
-@import (once) "../../customize/src/less2/include/colortheme.less";
+@import (once) "../../customize/src/less2/include/colortheme-all.less";
@import (once) "../../customize/src/less2/include/browser.less";
@import (once) "../../customize/src/less2/include/toolbar.less";
@import (once) "../../customize/src/less2/include/markdown.less";
@import (once) '../../customize/src/less2/include/alertify.less';
@import (once) '../../customize/src/less2/include/sidebar-layout.less';
-@import (once) "../../customize/src/less2/include/limit-bar.less";
+@import (once) "../../customize/src/less2/include/limit-bar.less";
+
+@_cp-toolbar-color-warn: @colortheme_settings-warn;
.toolbar_main();
.alertify_main();
diff --git a/www/slide/app-slide.less b/www/slide/app-slide.less
index 20c5a1830..32088eb64 100644
--- a/www/slide/app-slide.less
+++ b/www/slide/app-slide.less
@@ -6,6 +6,8 @@
@import (once) "../../customize/src/less2/include/mediatag.less";
@import (once) '../../customize/src/less2/include/tokenfield.less';
+@_cp-toolbar-color-warn: @colortheme_slide-warn;
+
.mediatag_base();
.toolbar_main();
.fileupload_main();
diff --git a/www/whiteboard/app-whiteboard.less b/www/whiteboard/app-whiteboard.less
index 9ec88d743..95fe016e9 100644
--- a/www/whiteboard/app-whiteboard.less
+++ b/www/whiteboard/app-whiteboard.less
@@ -6,6 +6,8 @@
@import (once) '../../customize/src/less2/include/tools.less';
@import (once) '../../customize/src/less2/include/tokenfield.less';
+@_cp-toolbar-color-warn: @colortheme_whiteboard-warn;
+
.toolbar_main();
.fileupload_main();
.alertify_main();
diff --git a/www/whiteboard/inner.js b/www/whiteboard/inner.js
index d65089a41..d19514b02 100644
--- a/www/whiteboard/inner.js
+++ b/www/whiteboard/inner.js
@@ -393,7 +393,16 @@ define([
Title = common.createTitle({});
var configTb = {
- displayed: ['title', 'useradmin', 'spinner', 'share', 'userlist', 'newpad', 'limit'],
+ displayed: [
+ 'userlist',
+ 'title',
+ 'useradmin',
+ 'spinner',
+ 'newpad',
+ 'share',
+ 'limit',
+ 'unpinnedWarning'
+ ],
title: Title.getTitleConfig(),
metadataMgr: metadataMgr,
readOnly: readOnly,