alert_words: Fix alert words with HTML special characters.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2022-03-01 20:25:18 -08:00 committed by Tim Abbott
parent ef706e51c3
commit baa11303ff
2 changed files with 34 additions and 3 deletions

View File

@ -10,7 +10,18 @@ set_global("page_params", {
});
const params = {
alert_words: ["alertone", "alerttwo", "alertthree", "al*rt.*s", ".+", "emoji"],
alert_words: [
"alertone",
"alerttwo",
"alertthree",
"al*rt.*s",
".+",
"emoji",
"FD&C",
"<3",
">8",
"5'11\"",
],
};
const people = zrequire("people");
@ -161,6 +172,15 @@ run_test("munging", () => {
message_with_emoji,
'<p>I <img alt=":heart:" class="emoji" src="/static/generated/emoji/images/emoji/unicode/2764.png" title="heart"> <span class=\'alert-word\'>emoji</span>!</p>',
);
assert_transform(
{
sender_email: "another@zulip.com",
content: `<p>FD&amp;C &lt;3 &gt;8 5'11" 5&#39;11&quot;</p>`,
alerted: true,
},
`<p><span class='alert-word'>FD&amp;C</span> <span class='alert-word'>&lt;3</span> <span class='alert-word'>&gt;8</span> <span class='alert-word'>5'11"</span> <span class='alert-word'>5&#39;11&quot;</span></p>`,
);
});
run_test("basic get/set operations", () => {

View File

@ -24,6 +24,15 @@ export function has_alert_word(word) {
return my_alert_words.includes(word);
}
const alert_regex_replacements = new Map([
["&", "&amp;"],
["<", "&lt;"],
[">", "&gt;"],
// Accept quotes with or without HTML escaping
['"', '(?:"|&quot;)'],
["'", "(?:'|&#39;)"],
]);
export function process_message(message) {
// Parsing for alert words is expensive, so we rely on the host
// to tell us there any alert words to even look for.
@ -32,7 +41,9 @@ export function process_message(message) {
}
for (const word of my_alert_words) {
const clean = _.escapeRegExp(word);
const clean = _.escapeRegExp(word).replace(/["&'<>]/g, (c) =>
alert_regex_replacements.get(c),
);
const before_punctuation = "\\s|^|>|[\\(\\\".,';\\[]";
const after_punctuation = "(?=\\s)|$|<|[\\)\\\"\\?!:.,';\\]!]";
@ -49,7 +60,7 @@ export function process_message(message) {
const check_string = pre_match + match.slice(0, -1);
const in_tag = check_string.lastIndexOf("<") > check_string.lastIndexOf(">");
// Matched word is inside a HTML tag so don't perform any highlighting.
if (in_tag === true) {
if (in_tag) {
return before + word + after;
}
return before + "<span class='alert-word'>" + word + "</span>" + after;