fix(logs): rebuild legacy HTML safely
This commit is contained in:
@@ -1,39 +1,3 @@
|
||||
export const convertLog = (value: string, type = 1): string => {
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
let result = value;
|
||||
if (type > 0) {
|
||||
result = result.replaceAll('<1>', '<font size=1>');
|
||||
result = result.replaceAll('<Y1>', '<font size=1 color=yellow>');
|
||||
result = result.replaceAll('<R>', '<font color=red>');
|
||||
result = result.replaceAll('<B>', '<font color=blue>');
|
||||
result = result.replaceAll('<G>', '<font color=green>');
|
||||
result = result.replaceAll('<M>', '<font color=magenta>');
|
||||
result = result.replaceAll('<C>', '<font color=cyan>');
|
||||
result = result.replaceAll('<L>', '<font color=limegreen>');
|
||||
result = result.replaceAll('<S>', '<font color=skyblue>');
|
||||
result = result.replaceAll('<O>', '<font color=orangered>');
|
||||
result = result.replaceAll('<D>', '<font color=orangered>');
|
||||
result = result.replaceAll('<Y>', '<font color=yellow>');
|
||||
result = result.replaceAll('<W>', '<font color=white>');
|
||||
result = result.replaceAll('</>', '</font>');
|
||||
return result;
|
||||
}
|
||||
import { formatLegacyLogHtml } from '@sammo-ts/common';
|
||||
|
||||
result = result.replaceAll('<1>', '');
|
||||
result = result.replaceAll('<Y1>', '');
|
||||
result = result.replaceAll('<R>', '');
|
||||
result = result.replaceAll('<B>', '');
|
||||
result = result.replaceAll('<G>', '');
|
||||
result = result.replaceAll('<M>', '');
|
||||
result = result.replaceAll('<C>', '');
|
||||
result = result.replaceAll('<L>', '');
|
||||
result = result.replaceAll('<S>', '');
|
||||
result = result.replaceAll('<O>', '');
|
||||
result = result.replaceAll('<D>', '');
|
||||
result = result.replaceAll('<Y>', '');
|
||||
result = result.replaceAll('<W>', '');
|
||||
result = result.replaceAll('</>', '');
|
||||
return result;
|
||||
};
|
||||
export const convertLog = (value: string, type = 1): string => formatLegacyLogHtml(value, { colorize: type > 0 });
|
||||
|
||||
@@ -333,6 +333,21 @@ describe('battle sim processor', () => {
|
||||
expect(() => processBattleSimJob(payload)).toThrow('Unknown scenario effect: event_Missing');
|
||||
});
|
||||
|
||||
it('escapes executable markup from simulator display names while preserving legacy log structure', () => {
|
||||
const payload = buildPayload('battle');
|
||||
payload.attackerGeneral.name = '<img src=x onerror="globalThis.__battleLogXss=1">';
|
||||
payload.defenderGenerals[0]!.name = '<script>globalThis.__battleLogXss=2</script>';
|
||||
payload.attackerNation.name = '<svg onload="globalThis.__battleLogXss=3">국가</svg>';
|
||||
|
||||
const result = processBattleSimJob(payload);
|
||||
const html = JSON.stringify(result.lastWarLog);
|
||||
|
||||
expect(html).toContain('<img src=x onerror=');
|
||||
expect(html).toContain('<script>globalThis.__battleLogXss=2</script>');
|
||||
expect(html).toContain('<div class=\\"small_war_log\\">');
|
||||
expect(html).not.toMatch(/<img|<script|<svg/i);
|
||||
});
|
||||
|
||||
it('runs the advance trigger when a progressed attacker meets the next fresh defender', () => {
|
||||
const payload = buildPayload('battle');
|
||||
payload.scenarioEffect = 'event_StrongAttacker';
|
||||
@@ -346,7 +361,7 @@ describe('battle sim processor', () => {
|
||||
|
||||
const result = processBattleSimJob(payload);
|
||||
expect(result.lastWarLog?.generalBattleDetailLog).toContain(
|
||||
'적군의 전멸에 <font color=cyan>진격</font>이 이어집니다!'
|
||||
'적군의 전멸에 <span style="color: cyan;">진격</span>이 이어집니다!'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user