mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-31 19:02:59 +01:00
chat: Allow chatNewMessage
hook to modify more values
This commit is contained in:
parent
1ad134a538
commit
74554d36a5
2 changed files with 26 additions and 23 deletions
|
@ -294,6 +294,11 @@ Things in context:
|
||||||
|
|
||||||
This hook is called on the client side whenever a chat message is received from
|
This hook is called on the client side whenever a chat message is received from
|
||||||
the server. It can be used to create different notifications for chat messages.
|
the server. It can be used to create different notifications for chat messages.
|
||||||
|
Hoook functions can modify the `author`, `authorName`, `duration`, `sticky`,
|
||||||
|
`text`, and `timeStr` context properties to change how the message is processed.
|
||||||
|
The `text` and `timeStr` properties may contain HTML, but plugins should be
|
||||||
|
careful to sanitize any added user input to avoid introducing an XSS
|
||||||
|
vulnerability.
|
||||||
|
|
||||||
## collectContentPre
|
## collectContentPre
|
||||||
|
|
||||||
|
|
|
@ -109,14 +109,6 @@ exports.chat = (() => {
|
||||||
// correct the time
|
// correct the time
|
||||||
msg.time += this._pad.clientTimeOffset;
|
msg.time += this._pad.clientTimeOffset;
|
||||||
|
|
||||||
// create the time string
|
|
||||||
let minutes = `${new Date(msg.time).getMinutes()}`;
|
|
||||||
let hours = `${new Date(msg.time).getHours()}`;
|
|
||||||
if (minutes.length === 1) minutes = `0${minutes}`;
|
|
||||||
if (hours.length === 1) hours = `0${hours}`;
|
|
||||||
const timeStr = `${hours}:${minutes}`;
|
|
||||||
|
|
||||||
// create the authorclass
|
|
||||||
if (!msg.userId) {
|
if (!msg.userId) {
|
||||||
/*
|
/*
|
||||||
* If, for a bug or a database corruption, the message coming from the
|
* If, for a bug or a database corruption, the message coming from the
|
||||||
|
@ -129,25 +121,25 @@ exports.chat = (() => {
|
||||||
'Replacing with "unknown". This may be a bug or a database corruption.');
|
'Replacing with "unknown". This may be a bug or a database corruption.');
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.userId = padutils.escapeHtml(msg.userId);
|
const authorClass = (authorId) => `author-${authorId.replace(/[^a-y0-9]/g, (c) => {
|
||||||
const authorClass = `author-${msg.userId.replace(/[^a-y0-9]/g, (c) => {
|
|
||||||
if (c === '.') return '-';
|
if (c === '.') return '-';
|
||||||
return `z${c.charCodeAt(0)}z`;
|
return `z${c.charCodeAt(0)}z`;
|
||||||
})}`;
|
})}`;
|
||||||
|
|
||||||
const text = padutils.escapeHtmlWithClickableLinks(msg.text, '_blank');
|
|
||||||
|
|
||||||
const authorName = msg.userName == null ? html10n.get('pad.userlist.unnamed')
|
|
||||||
: padutils.escapeHtml(msg.userName);
|
|
||||||
|
|
||||||
// the hook args
|
// the hook args
|
||||||
const ctx = {
|
const ctx = {
|
||||||
authorName,
|
authorName: msg.userName != null ? msg.userName : html10n.get('pad.userlist.unnamed'),
|
||||||
author: msg.userId,
|
author: msg.userId,
|
||||||
text,
|
text: padutils.escapeHtmlWithClickableLinks(msg.text, '_blank'),
|
||||||
sticky: false,
|
sticky: false,
|
||||||
timestamp: msg.time,
|
timestamp: msg.time,
|
||||||
timeStr,
|
timeStr: (() => {
|
||||||
|
let minutes = `${new Date(msg.time).getMinutes()}`;
|
||||||
|
let hours = `${new Date(msg.time).getHours()}`;
|
||||||
|
if (minutes.length === 1) minutes = `0${minutes}`;
|
||||||
|
if (hours.length === 1) hours = `0${hours}`;
|
||||||
|
return `${hours}:${minutes}`;
|
||||||
|
})(),
|
||||||
duration: 4000,
|
duration: 4000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -160,7 +152,7 @@ exports.chat = (() => {
|
||||||
// does this message contain this user's name? (is the curretn user mentioned?)
|
// does this message contain this user's name? (is the curretn user mentioned?)
|
||||||
const myName = $('#myusernameedit').val();
|
const myName = $('#myusernameedit').val();
|
||||||
const wasMentioned =
|
const wasMentioned =
|
||||||
text.toLowerCase().indexOf(myName.toLowerCase()) !== -1 && myName !== 'undefined';
|
ctx.text.toLowerCase().indexOf(myName.toLowerCase()) !== -1 && myName !== 'undefined';
|
||||||
|
|
||||||
// If the user was mentioned, make the message sticky
|
// If the user was mentioned, make the message sticky
|
||||||
if (wasMentioned && !alreadyFocused && !isHistoryAdd && !chatOpen) {
|
if (wasMentioned && !alreadyFocused && !isHistoryAdd && !chatOpen) {
|
||||||
|
@ -171,9 +163,14 @@ exports.chat = (() => {
|
||||||
|
|
||||||
// Call chat message hook
|
// Call chat message hook
|
||||||
hooks.aCallAll('chatNewMessage', ctx, () => {
|
hooks.aCallAll('chatNewMessage', ctx, () => {
|
||||||
|
const cls = authorClass(ctx.author);
|
||||||
const html =
|
const html =
|
||||||
`<p data-authorId='${msg.userId}' class='${authorClass}'><b>${authorName}:</b>` +
|
`<p data-authorId='${padutils.escapeHtml(ctx.author)}' class='${cls}'>` +
|
||||||
`<span class='time ${authorClass}'>${ctx.timeStr}</span> ${ctx.text}</p>`;
|
`<b>${padutils.escapeHtml(ctx.authorName)}:</b>` +
|
||||||
|
// ctx.text was HTML-escaped before calling the hook, and ctx.timeStr couldn't have had
|
||||||
|
// any HTML. Hook functions are trusted to not introduce an XSS vulnerability by adding
|
||||||
|
// unescaped user input to either ctx.text or ctx.timeStr.
|
||||||
|
`<span class='time ${cls}'>${ctx.timeStr}</span> ${ctx.text}</p>`;
|
||||||
if (isHistoryAdd) $(html).insertAfter('#chatloadmessagesbutton');
|
if (isHistoryAdd) $(html).insertAfter('#chatloadmessagesbutton');
|
||||||
else $('#chattext').append(html);
|
else $('#chattext').append(html);
|
||||||
|
|
||||||
|
@ -186,9 +183,10 @@ exports.chat = (() => {
|
||||||
|
|
||||||
if (!chatOpen && ctx.duration > 0) {
|
if (!chatOpen && ctx.duration > 0) {
|
||||||
$.gritter.add({
|
$.gritter.add({
|
||||||
// Note: ctx.authorName and ctx.text are already HTML-escaped.
|
|
||||||
text: $('<p>')
|
text: $('<p>')
|
||||||
.append($('<span>').addClass('author-name').html(ctx.authorName))
|
.append($('<span>').addClass('author-name').text(ctx.authorName))
|
||||||
|
// ctx.text was HTML-escaped before calling the hook. Hook functions are trusted
|
||||||
|
// to not introduce an XSS vulnerability by adding unescaped user input.
|
||||||
.append(ctx.text),
|
.append(ctx.text),
|
||||||
sticky: ctx.sticky,
|
sticky: ctx.sticky,
|
||||||
time: 5000,
|
time: 5000,
|
||||||
|
|
Loading…
Reference in a new issue