Merge branch 'staging' into ooPassword

This commit is contained in:
yflory
2019-12-09 16:05:24 +01:00
29 changed files with 589 additions and 151 deletions

View File

@@ -1,12 +1,17 @@
define([
'jquery',
'/common/cryptpad-common.js',
'/common/cryptget.js',
'/common/pinpad.js',
'/common/common-constants.js',
'/common/outer/local-store.js',
'/common/outer/login-block.js',
'/common/outer/network-config.js',
'/customize/login.js',
'/common/test.js',
'/bower_components/nthen/index.js',
'/bower_components/netflux-websocket/netflux-client.js',
'/bower_components/tweetnacl/nacl-fast.min.js'
], function ($, Cryptpad, Constants, LocalStore, Test, nThen) {
], function ($, Crypt, Pinpad, Constants, LocalStore, Block, NetConfig, Login, Test, nThen, Netflux) {
var Nacl = window.nacl;
var signMsg = function (msg, privKey) {
@@ -27,9 +32,57 @@ define([
sessionStorage[Constants.userHashKey];
var proxy;
var rpc;
var network;
var rpcError;
var loadProxy = function (hash) {
nThen(function (waitFor) {
var wsUrl = NetConfig.getWebsocketURL();
var w = waitFor();
Netflux.connect(wsUrl).then(function (_network) {
network = _network;
w();
}, function (err) {
rpcError = err;
console.error(err);
});
}).nThen(function (waitFor) {
Crypt.get(hash, waitFor(function (err, val) {
if (err) {
waitFor.abort();
console.error(err);
return;
}
try {
var parsed = JSON.parse(val);
proxy = parsed;
} catch (e) {
console.log("Can't parse user drive", e);
}
}), {
network: network
});
}).nThen(function (waitFor) {
if (!network) { return void waitFor.abort(); }
Pinpad.create(network, proxy, waitFor(function (e, call) {
if (e) {
rpcError = e;
return void waitFor.abort();
}
rpc = call;
}));
}).nThen(function () {
Test(function () {
// This is only here to maybe trigger an error.
window.drive = proxy['drive'];
Test.passed();
});
});
};
var whenReady = function (cb) {
if (proxy) { return void cb(); }
if (proxy && (rpc || rpcError)) { return void cb(); }
console.log('CryptPad not ready...');
setTimeout(function () {
whenReady(cb);
@@ -45,6 +98,17 @@ define([
console.log('CP receiving', data);
if (data.cmd === 'PING') {
ret.res = 'PONG';
} else if (data.cmd === 'LOGIN') {
Login.loginOrRegister(data.data.name, data.data.password, false, false, function (err) {
if (err) {
ret.error = 'LOGIN_ERROR';
srcWindow.postMessage(JSON.stringify(ret), domain);
return;
}
loadProxy(LocalStore.getUserHash());
srcWindow.postMessage(JSON.stringify(ret), domain);
});
return;
} else if (data.cmd === 'SIGN') {
if (!AUTHORIZED_DOMAINS.filter(function (x) { return x.test(domain); }).length) {
ret.error = "UNAUTH_DOMAIN";
@@ -63,7 +127,16 @@ define([
}
} else if (data.cmd === 'UPDATE_LIMIT') {
return void whenReady(function () {
Cryptpad.updatePinLimit(function (e, limit, plan, note) {
if (rpcError) {
// Tell the user on accounts that there was an issue and they need to wait maximum 24h or contact an admin
ret.warning = true;
srcWindow.postMessage(JSON.stringify(ret), domain);
return;
}
rpc.updatePinLimits(function (e, limit, plan, note) {
if (e) {
ret.warning = true;
}
ret.res = [limit, plan, note];
srcWindow.postMessage(JSON.stringify(ret), domain);
});
@@ -74,18 +147,8 @@ define([
srcWindow.postMessage(JSON.stringify(ret), domain);
});
nThen(function (waitFor) {
Cryptpad.ready(waitFor());
}).nThen(function (waitFor) {
Cryptpad.getUserObject(null, waitFor(function (obj) {
proxy = obj;
}));
}).nThen(function () {
console.log('IFRAME READY');
Test(function () {
// This is only here to maybe trigger an error.
window.drive = proxy['drive'];
Test.passed();
});
});
var userHash = LocalStore.getUserHash();
if (userHash) {
loadProxy(userHash);
}
});

View File

@@ -131,7 +131,7 @@ define([
if (['markdown', 'gfm'].indexOf(CodeMirror.highlightMode) === -1) { return; }
if (!$previewButton.is('.cp-toolbar-button-active')) { return; }
forceDrawPreview();
}, 150);
}, 400);
var previewTo;
$previewButton.click(function () {

View File

@@ -121,6 +121,10 @@ text.actor {
font-size: 11px;
text-height: 14px;
}
.sectionTitle, .titleText {
font-weight: bold;
}
/* Grid and axis */
.grid .tick {
stroke: lightgrey;

View File

@@ -6,22 +6,24 @@ define([
CodeMirror.defineSimpleMode("orgmode", {
start: [
{regex: /^(^\*{1,6}\s)(TODO|DOING|WAITING|NEXT){0,1}(CANCELLED|CANCEL|DEFERRED|DONE|REJECTED|STOP|STOPPED){0,1}(.*)$/, token: ["header org-level-star", "header org-todo", "header org-done", "header"]},
{regex: /(\*\s)(TODO|DOING|WAITING|NEXT|PENDING|)(CANCELLED|CANCELED|CANCEL|DONE|REJECTED|STOP|STOPPED|)(\s+\[\#[A-C]\]\s+|)(.*?)(?:(\s{10,}|))(\:[\S]+\:|)$/, sol: true, token: ["header level1 org-level-star","header level1 org-todo","header level1 org-done", "header level1 org-priority", "header level1", "header level1 void", "header level1 comment"]},
{regex: /(\*{1,}\s)(TODO|DOING|WAITING|NEXT|PENDING|)(CANCELLED|CANCELED|CANCEL|DEFERRED|DONE|REJECTED|STOP|STOPPED|)(\s+\[\#[A-C]\]\s+|)(.*?)(?:(\s{10,}|))(\:[\S]+\:|)$/, sol: true, token: ["header org-level-star","header org-todo","header org-done", "header org-priority", "header", "header void", "header comment"]},
{regex: /(\+[^\+]+\+)/, token: ["strikethrough"]},
{regex: /(\*[^\*]+\*)/, token: ["strong"]},
{regex: /(\/[^\/]+\/)/, token: ["em"]},
{regex: /(\_[^\_]+\_)/, token: ["link"]},
{regex: /(\~[^\~]+\~)/, token: ["comment"]},
{regex: /(\=[^\=]+\=)/, token: ["comment"]},
{regex: /\[\[[^\[\]]*\]\[[^\[\]]*\]\]/, token: "url"}, // links
{regex: /\[[xX\s]?\]/, token: 'qualifier'}, // checkbox
{regex: /\#\+BEGIN_[A-Z]*/, token: "comment", next: "env"}, // comments
{regex: /:?[A-Z_]+\:.*/, token: "comment"}, // property drawers
{regex: /(\#\+[A-Z_]*)(\:.*)/, token: ["keyword", 'qualifier']}, // environments
{regex: /(CLOCK\:|SHEDULED\:)(\s.+)/, token: ["comment", "keyword"]}
{regex: /\[\[[^\[\]]+\]\[[^\[\]]+\]\]/, token: "org-url"}, // links
{regex: /\[\[[^\[\]]+\]\]/, token: "org-image"}, // image
{regex: /\[[xX\s\-\_]\]/, token: 'qualifier org-toggle'}, // checkbox
{regex: /\#\+(?:(BEGIN|begin))_[a-zA-Z]*/, token: "comment", next: "env", sol: true}, // comments
{regex: /:?[A-Z_]+\:.*/, token: "comment", sol: true}, // property drawers
{regex: /(\#\+[a-zA-Z_]*)(\:.*)/, token: ["keyword", 'qualifier'], sol: true}, // environments
{regex: /(CLOCK\:|SHEDULED\:|DEADLINE\:)(\s.+)/, token: ["comment", "keyword"]}
],
env: [
{regex: /.*?\#\+END_[A-Z]*/, token: "comment", next: "start"},
{regex: /\#\+(?:(END|end))_[a-zA-Z]*/, token: "comment", next: "start", sol: true},
{regex: /.*/, token: "comment"}
]
});

View File

@@ -127,6 +127,18 @@ define([
return input;
};
dialog.selectableArea = function (value, opt) {
var attrs = merge({
readonly: 'readonly',
}, opt);
var input = h('textarea', attrs);
$(input).val(value).click(function () {
input.select();
});
return input;
};
dialog.okButton = function (content, classString) {
var sel = typeof(classString) === 'string'? 'button.ok.' + classString:'button.ok.primary';
return h(sel, { tabindex: '2', }, content || Messages.okButton);
@@ -187,7 +199,8 @@ define([
dialog.tabs = function (tabs) {
var contents = [];
var titles = [];
tabs.forEach(function (tab) {
var active = 0;
tabs.forEach(function (tab, i) {
if (!tab.content || !tab.title) { return; }
var content = h('div.alertify-tabs-content', tab.content);
var title = h('span.alertify-tabs-title', tab.title);
@@ -203,10 +216,11 @@ define([
});
titles.push(title);
contents.push(content);
if (tab.active) { active = i; }
});
if (contents.length) {
$(contents[0]).addClass('alertify-tabs-content-active');
$(titles[0]).addClass('alertify-tabs-active');
$(contents[active]).addClass('alertify-tabs-content-active');
$(titles[active]).addClass('alertify-tabs-active');
}
return h('div.alertify-tabs', [
h('div.alertify-tabs-titles', titles),

View File

@@ -147,6 +147,7 @@ define([
: Messages.owner_removeText;
var removeCol = UIElements.getUserGrid(msg, {
common: common,
large: true,
data: _owners,
noFilter: true
}, function () {
@@ -238,6 +239,7 @@ define([
});
var addCol = UIElements.getUserGrid(Messages.owner_addText, {
common: common,
large: true,
data: _friends
}, function () {
//console.log(arguments);
@@ -254,6 +256,7 @@ define([
});
var teamsList = UIElements.getUserGrid(Messages.owner_addTeamText, {
common: common,
large: true,
noFilter: true,
data: teamsData
}, function () {});
@@ -739,12 +742,22 @@ define([
UIElements.getProperties = function (common, data, cb) {
var c1;
var c2;
var button = [{
className: 'primary',
name: Messages.okButton,
onClick: function () {},
keys: [13]
}];
NThen(function (waitFor) {
getPadProperties(common, data, waitFor(function (e, c) {
c1 = c[0];
c1 = UI.dialog.customModal(c[0], {
buttons: button
});
}));
getRightsProperties(common, data, waitFor(function (e, c) {
c2 = c[0];
c2 = UI.dialog.customModal(c[0], {
buttons: button
});
}));
}).nThen(function () {
var tabs = UI.dialog.tabs([{
@@ -784,8 +797,6 @@ define([
var noOthers = icons.length === 0 ? '.cp-usergrid-empty' : '';
var buttonSelect = h('button', Messages.share_selectAll);
var buttonDeselect = h('button', Messages.share_deselectAll);
var inputFilter = h('input', {
placeholder: Messages.share_filterFriend
});
@@ -793,9 +804,7 @@ define([
var div = h('div.cp-usergrid-container' + noOthers + (config.large?'.large':''), [
label ? h('label', label) : undefined,
h('div.cp-usergrid-filter', (config.noFilter || config.noSelect) ? undefined : [
inputFilter,
buttonSelect,
buttonDeselect
inputFilter
]),
]);
var $div = $(div);
@@ -808,23 +817,8 @@ define([
$div.find('.cp-usergrid-user:not(.cp-selected):not([data-name*="'+name+'"])').hide();
}
};
$(inputFilter).on('keydown keyup change', redraw);
$(buttonSelect).click(function () {
$div.find('.cp-usergrid-user:not(.cp-selected):visible').addClass('cp-selected');
onSelect();
});
$(buttonDeselect).click(function () {
$div.find('.cp-usergrid-user.cp-selected').removeClass('cp-selected').each(function (i, el) {
var order = $(el).attr('data-order');
if (!order) { return; }
$(el).attr('style', 'order:'+order);
});
redraw();
onSelect();
});
$(div).append(h('div.cp-usergrid-grid', icons));
if (!config.noSelect) {
$div.on('click', '.cp-usergrid-user', function () {
@@ -885,7 +879,8 @@ define([
var friendsList = UIElements.getUserGrid(null, {
common: common,
data: friends,
noFilter: false
noFilter: false,
large: true
}, refreshButtons);
var friendDiv = friendsList.div;
$div.append(friendDiv);
@@ -911,6 +906,7 @@ define([
var teamsList = UIElements.getUserGrid(Messages.share_linkTeam, {
common: common,
noFilter: true,
large: true,
data: teams
}, refreshButtons);
$div.append(teamsList.div);
@@ -1016,12 +1012,29 @@ define([
if (!hashes || (!hashes.editHash && !hashes.viewHash)) { return; }
// check if the pad is password protected
var hash = hashes.editHash || hashes.viewHash;
var href = origin + pathname + '#' + hash;
var parsedHref = Hash.parsePadUrl(href);
var hasPassword = parsedHref.hashData.password;
var makeFaqLink = function () {
var link = h('span', [
h('i.fa.fa-question-circle'),
h('a', {href: '#'}, Messages.passwordFaqLink)
]);
$(link).click(function () {
common.openURL(config.origin + "/faq.html#security-pad_password");
});
return link;
};
var parsed = Hash.parsePadUrl(pathname);
var canPresent = ['code', 'slide'].indexOf(parsed.type) !== -1;
var rights = h('div.msg.cp-inline-radio-group', [
h('label', Messages.share_linkAccess),
h('br'),
h('div.radio-group',[
UI.createRadio('accessRights', 'cp-share-editable-false',
Messages.share_linkView, true, { mark: {tabindex:1} }),
@@ -1068,9 +1081,42 @@ define([
h('br'),
] : [
UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }),
h('br'),
];
linkContent.push(UI.dialog.selectable('', { id: 'cp-share-link-preview', tabindex: 1 }));
linkContent.push(h('div.cp-spacer'));
linkContent.push(UI.dialog.selectableArea('', { id: 'cp-share-link-preview', tabindex: 1, rows:3}));
// Show alert if the pad is password protected
if (hasPassword) {
linkContent.push(h('div.alert.alert-primary', [
h('i.fa.fa-lock'),
Messages.share_linkPasswordAlert, h('br'),
makeFaqLink()
]));
}
// warning about sharing links
var localStore = window.cryptpadStore;
var dismissButton = h('span.fa.fa-times');
var shareLinkWarning = h('div.alert.alert-warning.dismissable',
{ style: 'display: none;' },
[
h('span.cp-inline-alert-text', Messages.share_linkWarning),
dismissButton
]);
linkContent.push(shareLinkWarning);
localStore.get('hide-alert-shareLinkWarning', function (val) {
if (val === '1') { return; }
$(shareLinkWarning).show();
$(dismissButton).on('click', function () {
localStore.put('hide-alert-shareLinkWarning', '1');
$(shareLinkWarning).remove();
});
});
var link = h('div.cp-share-modal', linkContent);
var $link = $(link);
@@ -1137,7 +1183,19 @@ define([
// XXX Don't display access rights if no contacts
var contactsContent = h('div.cp-share-modal');
$(contactsContent).append(friendsList);
var $contactsContent = $(contactsContent);
$contactsContent.append(friendsList);
// Show alert if the pad is password protected
if (hasPassword) {
$contactsContent.append(h('div.alert.alert-primary', [
h('i.fa.fa-unlock'),
Messages.share_contactPasswordAlert, h('br'),
makeFaqLink()
]));
}
var contactButtons = [makeCancelButton(),
friendsObject.button];
@@ -1156,9 +1214,18 @@ define([
};
var embedContent = [
h('p', Messages.viewEmbedTag),
h('br'),
UI.dialog.selectable(getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 1 })
UI.dialog.selectableArea(getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 1, rows: 3})
];
// Show alert if the pad is password protected
if (hasPassword) {
embedContent.push(h('div.alert.alert-primary', [
h('i.fa.fa-lock'), ' ',
Messages.share_embedPasswordAlert, h('br'),
makeFaqLink()
]));
}
var embedButtons = [
makeCancelButton(), {
className: 'primary',
@@ -1187,13 +1254,15 @@ define([
// Create modal
var tabs = [{
title: Messages.share_linkCategory,
icon: "fa fa-link",
content: frameLink
}, {
title: Messages.share_contactCategory,
icon: "fa fa-address-book",
content: frameContacts
content: frameContacts,
active: hasFriends
}, {
title: Messages.share_linkCategory,
icon: "fa fa-link",
content: frameLink,
active: !hasFriends
}, {
title: Messages.share_embedCategory,
icon: "fa fa-code",
@@ -1261,6 +1330,21 @@ define([
if (!hashes.fileHash) { throw new Error("You must provide a file hash"); }
var url = origin + pathname + '#' + hashes.fileHash;
// check if the file is password protected
var parsedHref = Hash.parsePadUrl(url);
var hasPassword = parsedHref.hashData.password;
var makeFaqLink = function () {
var link = h('span', [
h('i.fa.fa-question-circle'),
h('a', {href: '#'}, Messages.passwordFaqLink)
]);
$(link).click(function () {
common.openURL(config.origin + "/faq.html#security-pad_password");
});
return link;
};
var getLinkValue = function () { return url; };
var makeCancelButton = function() {
@@ -1272,9 +1356,40 @@ define([
// Share link tab
var linkContent = [
UI.dialog.selectable(getLinkValue(), { id: 'cp-share-link-preview', tabindex: 1 })
UI.dialog.selectableArea(getLinkValue(), { id: 'cp-share-link-preview', tabindex: 1, rows:2 })
];
// Show alert if the pad is password protected
if (hasPassword) {
linkContent.push(h('div.alert.alert-primary', [
h('i.fa.fa-lock'),
Messages.share_linkPasswordAlert, h('br'),
makeFaqLink()
]));
}
// warning about sharing links
var localStore = window.cryptpadStore;
var dismissButton = h('span.fa.fa-times');
var shareLinkWarning = h('div.alert.alert-warning.dismissable',
{ style: 'display: none;' },
[
h('span.cp-inline-alert-text', Messages.share_linkWarning),
dismissButton
]);
linkContent.push(shareLinkWarning);
localStore.get('hide-alert-shareLinkWarning', function (val) {
if (val === '1') { return; }
$(shareLinkWarning).show();
$(dismissButton).on('click', function () {
localStore.put('hide-alert-shareLinkWarning', '1');
$(shareLinkWarning).remove();
});
});
var link = h('div.cp-share-modal', linkContent);
var linkButtons = [
@@ -1307,7 +1422,17 @@ define([
var friendsList = friendsObject.content;
var contactsContent = h('div.cp-share-modal');
$(contactsContent).append(friendsList);
var $contactsContent = $(contactsContent);
$contactsContent.append(friendsList);
// Show alert if the pad is password protected
if (hasPassword) {
$contactsContent.append(h('div.alert.alert-primary', [
h('i.fa.fa-unlock'),
Messages.share_contactPasswordAlert, h('br'),
makeFaqLink()
]));
}
var contactButtons = [makeCancelButton(),
friendsObject.button];
@@ -1321,12 +1446,20 @@ define([
// Embed tab
var embed = h('div.cp-share-modal', [
h('p', Messages.fileEmbedScript),
h('br'),
UI.dialog.selectable(common.getMediatagScript()),
h('p', Messages.fileEmbedTag),
h('br'),
UI.dialog.selectable(common.getMediatagFromHref(fileData)),
]);
// Show alert if the pad is password protected
if (hasPassword) {
embed.append(h('div.alert.alert-primary', [
h('i.fa.fa-lock'), ' ',
Messages.share_embedPasswordAlert, h('br'),
makeFaqLink()
]));
}
var embedButtons = [{
className: 'cancel',
name: Messages.cancel,
@@ -1349,13 +1482,15 @@ define([
// Create modal
var tabs = [{
title: Messages.share_linkCategory,
icon: "fa fa-link",
content: frameLink
}, {
title: Messages.share_contactCategory,
icon: "fa fa-address-book",
content: frameContacts
content: frameContacts,
active: hasFriends,
}, {
title: Messages.share_linkCategory,
icon: "fa fa-link",
content: frameLink,
active: !hasFriends
}, {
title: Messages.share_embedCategory,
icon: "fa fa-code",
@@ -1759,7 +1894,7 @@ define([
if (e) { return void console.error(e); }
UIElements.getProperties(common, data, function (e, $prop) {
if (e) { return void console.error(e); }
UI.alert($prop[0], undefined, true);
UI.openCustomModal($prop[0]);
});
});
});

View File

@@ -84,7 +84,7 @@ define([
var defaultCode = renderer.code;
renderer.code = function (code, language) {
if (language === 'mermaid' && (code.match(/^sequenceDiagram/) || code.match(/^graph/))) {
if (language === 'mermaid' && code.match(/^(graph|pie|gantt|sequenceDiagram|classDiagram|gitGraph)/)) {
return '<pre class="mermaid">'+code+'</pre>';
} else {
return defaultCode.apply(renderer, arguments);
@@ -197,7 +197,6 @@ define([
'APPLET',
'VIDEO', // privacy implications of videos are the same as images
'AUDIO', // same with audio
'SVG'
];
var unsafeTag = function (info) {
/*if (info.node && $(info.node).parents('media-tag').length) {
@@ -307,8 +306,39 @@ define([
var Dom = domFromHTML($('<div>').append($div).html());
$content[0].normalize();
$content.find('pre.mermaid[data-processed="true"]').remove();
var mermaid_source = [];
var mermaid_cache = {};
// iterate over the unrendered mermaid inputs, caching their source as you go
$(newDomFixed).find('pre.mermaid').each(function (index, el) {
if (el.childNodes.length === 1 && el.childNodes[0].nodeType === 3) {
var src = el.childNodes[0].wholeText;
el.setAttribute('mermaid-source', src);
mermaid_source[index] = src;
}
});
// iterate over rendered mermaid charts
$content.find('pre.mermaid:not([processed="true"])').each(function (index, el) {
// retrieve the attached source code which it was drawn
var src = el.getAttribute('mermaid-source');
// check if that source exists in the set of charts which are about to be rendered
if (mermaid_source.indexOf(src) === -1) {
// if it's not, then you can remove it
if (el.parentNode && el.parentNode.children.length) {
el.parentNode.removeChild(el);
}
} else if (el.childNodes.length === 1 && el.childNodes[0].nodeType !== 3) {
// otherwise, confirm that the content of the rendered chart is not a text node
// and keep a copy of it
mermaid_cache[src] = el.childNodes[0];
}
});
var oldDom = domFromHTML($content[0].outerHTML);
var patch = makeDiff(oldDom, Dom, id);
if (typeof(patch) === 'string') {
throw new Error(patch);
@@ -348,8 +378,32 @@ define([
var target = document.getElementById($a.attr('data-href'));
if (target) { target.scrollIntoView(); }
});
// loop over mermaid elements in the rendered content
$content.find('pre.mermaid').each(function (index, el) {
// since you've simply drawn the content that was supplied via markdown
// you can assume that the index of your rendered charts matches that
// of those in the markdown source.
var src = mermaid_source[index];
el.setAttribute('mermaid-source', src);
var cached = mermaid_cache[src];
// check if you had cached a pre-rendered instance of the supplied source
if (typeof(cached) !== 'object') { return; }
// if there's a cached rendering, empty out the contained source code
// which would otherwise be drawn again.
// apparently this is the fastest way to empty out an element
while (el.firstChild) { el.removeChild(el.firstChild); } //el.innerHTML = '';
// insert the cached graph
el.appendChild(cached);
// and set a flag indicating that this graph need not be reprocessed
el.setAttribute('data-processed', true);
});
try {
Mermaid.init();
// finally, draw any graphs which have changed and were thus not cached
Mermaid.init(undefined, $content.find('pre.mermaid:not([data-processed="true"])'));
} catch (e) { console.error(e); }
}
};

View File

@@ -79,7 +79,7 @@ define([
var faColor = 'cptools-palette';
var faTrash = 'fa-trash';
var faDelete = 'fa-eraser';
var faProperties = 'fa-database';
var faProperties = 'fa-info-circle';
var faTags = 'fa-hashtag';
var faUploadFiles = 'cptools-file-upload';
var faUploadFolder = 'cptools-folder-upload';
@@ -4187,7 +4187,7 @@ define([
}
getProperties(el, function (e, $prop) {
if (e) { return void logError(e); }
UI.alert($prop[0], undefined, true);
UI.openCustomModal($prop[0]);
});
}
else if ($this.hasClass("cp-app-drive-context-hashtag")) {

View File

@@ -43,7 +43,7 @@ define([
MessengerUI.create = function ($container, common, toolbar) {
var metadataMgr = common.getMetadataMgr();
var origin = metadataMgr.getPrivateData().origin;
var readOnly = metadataMgr.getPrivateData().readOnly || toolbar.readOnly;
var readOnly = metadataMgr.getPrivateData().readOnly || (toolbar && toolbar.readOnly);
var isApp = typeof(toolbar) !== "undefined";

View File

@@ -769,18 +769,18 @@ define([
continue;
}
var href;
var decryptedHref;
try {
href = el.href && ((el.href.indexOf('#') !== -1) ? el.href : exp.cryptor.decrypt(el.href));
decryptedHref = el.href && ((el.href.indexOf('#') !== -1) ? el.href : exp.cryptor.decrypt(el.href));
} catch (e) {}
if (href && href.indexOf('#') === -1) {
if (decryptedHref && decryptedHref.indexOf('#') === -1) {
// If we can't decrypt the href, it means we don't have the correct secondaryKey and we're in readOnly mode:
// abort now, we won't be able to fix anything anyway
continue;
}
var parsed = Hash.parsePadUrl(href || el.roHref);
var parsed = Hash.parsePadUrl(decryptedHref || el.roHref);
var secret;
// Clean invalid hash
@@ -797,9 +797,9 @@ define([
}
// If we have an edit link, check the view link
if (href && parsed.hashData.type === "pad" && parsed.hashData.version) {
if (decryptedHref && parsed.hashData.type === "pad" && parsed.hashData.version) {
if (parsed.hashData.mode === "view") {
el.roHref = href;
el.roHref = decryptedHref;
delete el.href;
} else if (!el.roHref) {
secret = Hash.getSecrets(parsed.type, parsed.hash, el.password);
@@ -818,7 +818,9 @@ define([
}
// Fix href
if (href && href.slice(0,1) !== '/') { el.href = exp.cryptor.encrypt(Hash.getRelativeHref(el.href)); }
if (decryptedHref && decryptedHref.slice(0,1) !== '/') {
el.href = exp.cryptor.encrypt(Hash.getRelativeHref(decryptedHref));
}
// Fix creation time
if (!el.ctime) { el.ctime = el.atime; }
// Fix title

View File

@@ -488,6 +488,20 @@ define([
Cryptpad.storeInTeam(data, cb);
});
sframeChan.on('EV_GOTO_URL', function (url) {
if (url) {
window.location.href = url;
} else {
window.location.reload();
}
});
sframeChan.on('EV_OPEN_URL', function (url) {
if (url) {
window.open(url);
}
});
};
addCommonRpc(sframeChan);
@@ -956,20 +970,6 @@ define([
});
});
sframeChan.on('EV_GOTO_URL', function (url) {
if (url) {
window.location.href = url;
} else {
window.location.reload();
}
});
sframeChan.on('EV_OPEN_URL', function (url) {
if (url) {
window.open(url);
}
});
sframeChan.on('Q_PIN_GET_USAGE', function (teamId, cb) {
Cryptpad.isOverPinLimit(teamId, function (err, overLimit, data) {
cb({

View File

@@ -533,7 +533,7 @@ MessengerUI, Messages) {
Common.getSframeChannel().event('EV_SHARE_OPEN', {
hidden: true
});
$shareBlock.click(function () {
$shareBlock.click(function () {
var title = (config.title && config.title.getTitle && config.title.getTitle())
|| (config.title && config.title.defaultName)
|| "";

View File

@@ -0,0 +1,2 @@
{
}

View File

@@ -54,6 +54,7 @@
.kanban-item-text {
cursor: text;
overflow-wrap: anywhere;
flex: 1;
}
}
@@ -67,7 +68,7 @@
margin-right: 10px;
min-width: 0;
overflow: hidden;
white-space: nowrap;
//white-space: nowrap;
text-overflow: ellipsis;
}
#kanban-edit {

View File

@@ -286,7 +286,7 @@ define([
kanban.inEditMode = true;
// create a form to enter element
var boardId = $(el.parentNode.parentNode).attr("data-id");
var $item = $('<div>', {'class': 'kanban-item'});
var $item = $('<div>', {'class': 'kanban-item new-item'});
var $input = getInput().val(name).appendTo($item);
kanban.addForm(boardId, $item[0]);
$input.focus();

View File

@@ -147,9 +147,13 @@
self.drake = self.dragula(self.boardContainer, {
moves: function (el, source, handle, sibling) {
if (self.options.readOnly) { return false; }
if (el.classList.contains('new-item')) { return false; }
return handle.classList.contains('kanban-item');
},
accepts: function (el, target, source, sibling) {
if (sibling === null) {
return false;
}
if (self.options.readOnly) { return false; }
return true;
},
@@ -349,7 +353,7 @@
titleBoard = document.createElement('div');
titleBoard.classList.add('kanban-title-board');
titleBoard.innerHTML = board.title;
titleBoard.setAttribute('title', board.title);
//titleBoard.setAttribute('title', board.title);
titleBoard.clickfn = board.boardTitleClick;
__onboardTitleClickHandler(titleBoard);
headerBoard.appendChild(titleBoard);

View File

@@ -51,6 +51,7 @@ define([
'cp-settings-info-block',
'cp-settings-displayname',
'cp-settings-language-selector',
'cp-settings-resettips',
'cp-settings-logout-everywhere',
'cp-settings-autostore',
'cp-settings-userfeedback',
@@ -67,7 +68,6 @@ define([
],
'drive': [
'cp-settings-drive-duplicate',
'cp-settings-resettips',
'cp-settings-thumbnails',
'cp-settings-drive-backup',
'cp-settings-drive-import-local',
@@ -835,7 +835,7 @@ define([
var localStore = window.cryptpadStore;
$button.click(function () {
Object.keys(localStore.store).forEach(function (k) {
if(k.slice(0, 9) === "hide-info") {
if(/^(hide-(info|alert))/.test(k)) {
localStore.put(k, null);
}
});