sanitize html before placing into dom

This commit is contained in:
frost768 2023-03-11 05:39:06 +03:00
parent 315c3de3ab
commit 3bee46ff53
5 changed files with 3745 additions and 3587 deletions

View File

@ -6,8 +6,8 @@
"dependencies": {
"@formkit/auto-animate": "^1.0.0-beta.5",
"@headlessui/react": "^1.5.0",
"@types/react-helmet": "^6.1.6",
"crypto-js": "^4.1.1",
"dompurify": "^3.0.1",
"fscreen": "^1.2.0",
"fuse.js": "^6.4.6",
"hls.js": "^1.0.7",
@ -56,12 +56,14 @@
"@tailwindcss/line-clamp": "^0.4.2",
"@types/chromecast-caf-sender": "^1.0.5",
"@types/crypto-js": "^4.1.1",
"@types/dompurify": "^2.4.0",
"@types/fscreen": "^1.0.1",
"@types/lodash.throttle": "^4.1.7",
"@types/node": "^17.0.15",
"@types/pako": "^2.0.0",
"@types/react": "^17.0.39",
"@types/react-dom": "^17.0.11",
"@types/react-helmet": "^6.1.6",
"@types/react-router": "^5.1.18",
"@types/react-router-dom": "^5.3.3",
"@types/react-stickynode": "^4.0.0",

View File

@ -1,7 +1,9 @@
import { mwFetch, proxiedFetch } from "@/backend/helpers/fetch";
import { MWCaption, MWCaptionType } from "@/backend/helpers/streams";
import toWebVTT from "srt-webvtt";
import DOMPurify from "dompurify";
export const sanitize = DOMPurify.sanitize;
export const CUSTOM_CAPTION_ID = "customCaption";
export async function getCaptionUrl(caption: MWCaption): Promise<string> {
if (caption.type === MWCaptionType.SRT) {

View File

@ -1,3 +1,4 @@
import { sanitize } from "@/backend/helpers/captions";
import { useSettings } from "@/state/settings";
export function Caption({ text }: { text?: string }) {
@ -5,13 +6,18 @@ export function Caption({ text }: { text?: string }) {
return (
<span
className="pointer-events-none mb-1 select-none px-1 text-center"
/*
WebVTT files may have html elements (such as <i>, <b>) in them
but if we want full customization we will have to
remove tags with a regex from raw text
*/
dangerouslySetInnerHTML={{ __html: text ?? "" }}
dir="auto"
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{
__html: sanitize(text || "", {
// https://www.w3.org/TR/webvtt1/#dom-construction-rules
ALLOWED_TAGS: ["c", "b", "i", "u", "span", "ruby", "rt"],
ADD_TAGS: ["v", "lang"],
ALLOWED_ATTR: ["title", "lang"],
}),
}}
style={{
whiteSpace: "pre-wrap",
...captionSettings.style,
}}
/>

View File

@ -22,7 +22,9 @@ export function CaptionRenderer({
const url = source?.caption?.url;
if (url) {
// Is there a better way?
const text = await (await fetch(url)).text();
const result = await fetch(url);
// Uses UTF-8 by default
const text = await result.text();
captions.current = parse(text, { strict: false }).cues;
} else {
captions.current = [];
@ -43,7 +45,7 @@ export function CaptionRenderer({
{captions.current.map(
({ identifier, end, start, text }) =>
isVisible(start, end) && (
<Caption key={identifier ?? Math.random() * 9999999} text={text} />
<Caption key={identifier || `${start}-${end}`} text={text} />
)
)}
{isControlsShown ? (

7302
yarn.lock

File diff suppressed because it is too large Load Diff