Use recursive stylesheet sanitation

62a1919402faa555c3d670d517fa8872be60a898

Cohee <18619528+Cohee1207@users.noreply.github.com>

1 files changed, +42 -32Ignore whitespace
public/scripts/chats.js+42 -32
@@ -465,42 +465,52 @@ export function decodeStyleTags(text) {
465465 const styleDecodeRegex = /<custom-style>(.+?)<\/custom-style>/gms;
466466 const mediaAllowed = isExternalMediaAllowed();
467467
468+ function sanitizeRule(rule) {
469+ if (rule.selectors) {
470+ for (let i = 0; i < rule.selectors.length; i++) {
471+ let selector = rule.selectors[i];
472+ if (selector) {
473+ let selectors = (selector.split(' ') ?? []).map((v) => {
474+ if (v.startsWith('.')) {
475+ return '.custom-' + v.substring(1);
476+ }
477+ return v;
478+ }).join(' ');
479+
480+ rule.selectors[i] = '.mes_text ' + selectors;
481+ }
482+ }
483+ }
484+ if (!mediaAllowed && Array.isArray(rule.declarations) && rule.declarations.length > 0) {
485+ for (const declaration of rule.declarations) {
486+ if (declaration.value.includes('://')) {
487+ rule.declarations.splice(rule.declarations.indexOf(declaration), 1);
488+ }
489+ }
490+ }
491+ }
492+
493+ function sanitizeRuleSet(ruleSet) {
494+ if (ruleSet.type === 'rule') {
495+ sanitizeRule(ruleSet);
496+ }
497+
498+ if (Array.isArray(ruleSet.rules)) {
499+ ruleSet.rules = ruleSet.rules.filter(rule => rule.type !== 'import');
500+
501+ for (const mediaRule of ruleSet.rules) {
502+ sanitizeRuleSet(mediaRule);
503+ }
504+ }
505+ }
506+
468507 return text.replaceAll(styleDecodeRegex, (_, style) => {
469508 try {
470509 let styleCleaned = unescape(style).replaceAll(/<br\/>/g, '');
471510 const ast = css.parse(styleCleaned);
472511 const rulessheet = ast?.stylesheet?.rules;
473512 if (rulessheet) {
474- for (const rule of rules) {
513+ sanitizeRuleSet(ast.stylesheet);
475- if (rule.type === 'import') {
476- rules.splice(rules.indexOf(rule), 1);
477- }
478-
479- if (rule.type === 'rule') {
480- if (rule.selectors) {
481- for (let i = 0; i < rule.selectors.length; i++) {
482- let selector = rule.selectors[i];
483- if (selector) {
484- let selectors = (selector.split(' ') ?? []).map((v) => {
485- if (v.startsWith('.')) {
486- return '.custom-' + v.substring(1);
487- }
488- return v;
489- }).join(' ');
490-
491- rule.selectors[i] = '.mes_text ' + selectors;
492- }
493- }
494- }
495- if (!mediaAllowed && Array.isArray(rule.declarations) && rule.declarations.length > 0) {
496- for (const declaration of rule.declarations) {
497- if (declaration.value.includes('://')) {
498- rule.declarations.splice(rule.declarations.indexOf(declaration), 1);
499- }
500- }
501- }
502- }
503- }
504514 }
505515 return `<style>${css.stringify(ast)}</style>`;
506516 } catch (error) {