mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-02-13 18:17:42 +01:00
refactor: emoji replacement code into helper function, remove use of regex on untrusted user input
This commit is contained in:
@@ -543,3 +543,41 @@ Helpers.addressed = (id, activity) => {
|
||||
|
||||
return combined.has(id);
|
||||
};
|
||||
|
||||
Helpers.renderEmoji = (text, tags, strip = false) => {
|
||||
if (!text || !tags) {
|
||||
return text;
|
||||
}
|
||||
|
||||
tags = Array.isArray(tags) ? tags : [tags];
|
||||
let result = text;
|
||||
|
||||
tags.forEach((tag) => {
|
||||
const isEmoji = tag.type === 'Emoji';
|
||||
const hasUrl = tag.icon && tag.icon.url;
|
||||
const isImage = !tag.icon?.mediaType || tag.icon.mediaType.startsWith('image/');
|
||||
|
||||
if (isEmoji && (strip || (hasUrl && isImage))) {
|
||||
let { name } = tag;
|
||||
|
||||
if (!name.startsWith(':')) {
|
||||
name = `:${name}`;
|
||||
}
|
||||
if (!name.endsWith(':')) {
|
||||
name = `${name}:`;
|
||||
}
|
||||
|
||||
const imgTag = strip ?
|
||||
'' :
|
||||
`<img class="not-responsive emoji" src="${tag.icon.url}" title="${name}" />`;
|
||||
|
||||
let index = result.indexOf(name);
|
||||
while (index !== -1) {
|
||||
result = result.substring(0, index) + imgTag + result.substring(index + name.length);
|
||||
index = result.indexOf(name, index + imgTag.length);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -195,17 +195,7 @@ Mocks.profile = async (actors) => {
|
||||
const iconBackgrounds = await user.getIconBackgrounds();
|
||||
let bgColor = Array.prototype.reduce.call(preferredUsername, (cur, next) => cur + next.charCodeAt(), 0);
|
||||
bgColor = iconBackgrounds[bgColor % iconBackgrounds.length];
|
||||
summary = summary || '';
|
||||
// Replace emoji in summary
|
||||
if (tag && Array.isArray(tag)) {
|
||||
tag
|
||||
.filter(tag => tag.type === 'Emoji' &&
|
||||
isEmojiShortcode.test(tag.name) &&
|
||||
tag.icon && tag.icon.mediaType && tag.icon.mediaType.startsWith('image/'))
|
||||
.forEach((tag) => {
|
||||
summary = summary.replace(new RegExp(tag.name, 'g'), `<img class="not-responsive emoji" src="${tag.icon.url}" title="${tag.name}" />`);
|
||||
});
|
||||
}
|
||||
summary = activitypub.helpers.renderEmoji(summary || '', tag);
|
||||
|
||||
// Add custom fields into user hash
|
||||
const customFields = actor.attachment && Array.isArray(actor.attachment) && actor.attachment.length ?
|
||||
@@ -308,24 +298,13 @@ Mocks.category = async (actors) => {
|
||||
|
||||
const backgroundImage = !icon || typeof icon === 'string' ? icon : icon.url;
|
||||
|
||||
// Replace emoji in summary
|
||||
if (tag && Array.isArray(tag)) {
|
||||
tag
|
||||
.filter(tag => tag.type === 'Emoji' &&
|
||||
isEmojiShortcode.test(tag.name) &&
|
||||
tag.icon && tag.icon.mediaType && tag.icon.mediaType.startsWith('image/'))
|
||||
.forEach((tag) => {
|
||||
summary = summary.replace(new RegExp(tag.name, 'g'), `<img class="not-responsive emoji" src="${tag.icon.url}" title="${tag.name}" />`);
|
||||
});
|
||||
}
|
||||
|
||||
const payload = {
|
||||
cid,
|
||||
name,
|
||||
handle: `${preferredUsername}@${hostname}`,
|
||||
slug: `${preferredUsername}@${hostname}`,
|
||||
description: summary,
|
||||
descriptionParsed: posts.sanitize(summary),
|
||||
descriptionParsed: posts.sanitize(activitypub.helpers.renderEmoji(summary || '', tag)),
|
||||
icon: backgroundImage ? 'fa-none' : 'fa-comments',
|
||||
color: '#fff',
|
||||
bgColor,
|
||||
|
||||
@@ -189,13 +189,7 @@ Notes.assert = async (uid, input, options = { skipChecks: false }) => {
|
||||
}
|
||||
|
||||
// Remove any custom emoji from title
|
||||
if (_activitypub && _activitypub.tag && Array.isArray(_activitypub.tag)) {
|
||||
_activitypub.tag
|
||||
.filter(tag => tag.type === 'Emoji')
|
||||
.forEach((tag) => {
|
||||
title = title.replace(new RegExp(tag.name, 'g'), '');
|
||||
});
|
||||
}
|
||||
title = activitypub.helpers.renderEmoji(title, _activitypub.tag, true);
|
||||
}
|
||||
mainPid = utils.isNumber(mainPid) ? parseInt(mainPid, 10) : mainPid;
|
||||
|
||||
|
||||
@@ -48,22 +48,8 @@ module.exports = function (Posts) {
|
||||
}
|
||||
|
||||
// Rewrite emoji references to inline image assets
|
||||
if (_activitypub && _activitypub.tag && Array.isArray(_activitypub.tag)) {
|
||||
_activitypub.tag
|
||||
.filter(tag => tag.type === 'Emoji' &&
|
||||
tag.icon && tag.icon.type === 'Image')
|
||||
.forEach((tag) => {
|
||||
if (!tag.name.startsWith(':')) {
|
||||
tag.name = `:${tag.name}`;
|
||||
}
|
||||
if (!tag.name.endsWith(':')) {
|
||||
tag.name = `${tag.name}:`;
|
||||
}
|
||||
|
||||
const property = postData.sourceContent && !postData.content ? 'sourceContent' : 'content';
|
||||
postData[property] = postData[property].replace(new RegExp(tag.name, 'g'), `<img class="not-responsive emoji" src="${tag.icon.url}" title="${tag.name}" />`);
|
||||
});
|
||||
}
|
||||
const property = postData.sourceContent && !postData.content ? 'sourceContent' : 'content';
|
||||
postData[property] = activitypub.helpers.renderEmoji(postData[property], _activitypub.tag);
|
||||
|
||||
hasAttachment = _activitypub && _activitypub.attachment && _activitypub.attachment.length;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user