Files
pedwfrontend/lib/security/contactus-email-links.js

82 lines
2.7 KiB
JavaScript

const LINK_REMOVED = "[web link removed]";
const OBFUSCATING_SPACE = "[\\s\\u0000-\\u001f\\u007f\\u200b-\\u200d\\ufeff]*";
const SCHEME = `h${OBFUSCATING_SPACE}t${OBFUSCATING_SPACE}t${OBFUSCATING_SPACE}p(?:${OBFUSCATING_SPACE}s)?${OBFUSCATING_SPACE}:${OBFUSCATING_SPACE}\\/${OBFUSCATING_SPACE}\\/`;
const DOMAIN = "(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,63}";
const URL_TAIL = "[^\\s<>\\\"']*";
const explicitUrlPattern = () => new RegExp(`${SCHEME}${DOMAIN}${URL_TAIL}`, "gi");
const wwwUrlPattern = () => new RegExp(`\\bwww\\.${DOMAIN}${URL_TAIL}`, "gi");
const bareDomainWithPathPattern = () =>
new RegExp(`(^|[^a-z0-9@._-])(${DOMAIN}\\/[^\\s<>\\\"']*)`, "gi");
const stripTrailingPunctuation = (value) => {
let destination = value;
let punctuation = "";
while (/[.,!;:]$/.test(destination)) {
punctuation = destination.slice(-1) + punctuation;
destination = destination.slice(0, -1);
}
while (/[)\]}]$/.test(destination)) {
punctuation = destination.slice(-1) + punctuation;
destination = destination.slice(0, -1);
}
return { destination, punctuation };
};
const replaceUrlMatch = (value) => {
const { destination, punctuation } = stripTrailingPunctuation(value);
return destination ? LINK_REMOVED + punctuation : value;
};
const containsWebDestination = (value) => {
explicitUrlPattern().lastIndex = 0;
wwwUrlPattern().lastIndex = 0;
bareDomainWithPathPattern().lastIndex = 0;
return (
explicitUrlPattern().test(value) ||
wwwUrlPattern().test(value) ||
bareDomainWithPathPattern().test(value)
);
};
export default function removeContactUsEmailLinks(message) {
if (typeof message !== "string") {
return message;
}
let transformed = message;
transformed = transformed.replace(
/<a\b[^>]*>([\s\S]*?)<\/a\s*>/gi,
(match, linkText) =>
containsWebDestination(match)
? `${linkText}${linkText ? " " : ""}${LINK_REMOVED}`
: match
);
transformed = transformed.replace(/<[^>]+>/gi, (tag) =>
containsWebDestination(tag) ? LINK_REMOVED : tag
);
transformed = transformed.replace(
/\[([^\]]*)\]\(([^)]*)\)/gi,
(match, linkText, destination) =>
containsWebDestination(destination)
? `${linkText}${linkText ? " " : ""}${LINK_REMOVED}`
: match
);
transformed = transformed.replace(explicitUrlPattern(), replaceUrlMatch);
transformed = transformed.replace(wwwUrlPattern(), replaceUrlMatch);
transformed = transformed.replace(
bareDomainWithPathPattern(),
(match, prefix, destination) => prefix + replaceUrlMatch(destination)
);
return transformed;
}