mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-22 12:13:43 +08:00
fix: harden M3U8 ad filtering
Reject unsafe dynamic filter execution, reduce heuristic false positives, add regression coverage, bump the app to 4.9.17, and update Next.js to the latest stable security patch.
This commit is contained in:
@@ -22,7 +22,7 @@ export function useHlsPlayer({
|
||||
onError
|
||||
}: UseHlsPlayerProps) {
|
||||
const hlsRef = useRef<Hls | null>(null);
|
||||
const { adFilterMode, adKeywords, customAdFilterCode } = usePlayerSettings(isPremium);
|
||||
const { adFilterMode, adKeywords } = usePlayerSettings(isPremium);
|
||||
const { mediaProxyEnabled } = useRuntimeFeatures();
|
||||
const isAdFilterEnabled = adFilterMode !== 'off';
|
||||
|
||||
@@ -59,7 +59,7 @@ export function useHlsPlayer({
|
||||
if (typeof response.data === 'string') {
|
||||
try {
|
||||
// Filter the content
|
||||
response.data = filterM3u8Ad(response.data, context.url, adFilterMode, adKeywords, customAdFilterCode);
|
||||
response.data = filterM3u8Ad(response.data, context.url, adFilterMode, adKeywords);
|
||||
} catch (e) {
|
||||
console.warn('[HLS] Ad filter error:', e);
|
||||
}
|
||||
@@ -255,7 +255,7 @@ export function useHlsPlayer({
|
||||
|
||||
// If it's a simple playlist (no variants), just filter and play
|
||||
if (!masterContent.includes('#EXT-X-STREAM-INF')) {
|
||||
const filtered = filterM3u8Ad(masterContent, absoluteMasterSrc, adFilterMode, adKeywords, customAdFilterCode);
|
||||
const filtered = filterM3u8Ad(masterContent, absoluteMasterSrc, adFilterMode, adKeywords);
|
||||
const blob = new Blob([filtered], { type: 'application/vnd.apple.mpegurl' });
|
||||
const blobUrl = URL.createObjectURL(blob);
|
||||
createdBlobs.push(blobUrl);
|
||||
@@ -283,7 +283,7 @@ export function useHlsPlayer({
|
||||
try {
|
||||
const absoluteUrl = isRelative ? new URL(uri, absoluteMasterSrc).toString() : uri;
|
||||
const subContent = await fetchWithFallback(absoluteUrl);
|
||||
const filteredSub = filterM3u8Ad(subContent, absoluteUrl, adFilterMode, adKeywords, customAdFilterCode);
|
||||
const filteredSub = filterM3u8Ad(subContent, absoluteUrl, adFilterMode, adKeywords);
|
||||
const subBlob = new Blob([filteredSub], { type: 'application/vnd.apple.mpegurl' });
|
||||
const subBlobUrl = URL.createObjectURL(subBlob);
|
||||
createdBlobs.push(subBlobUrl);
|
||||
@@ -306,7 +306,7 @@ export function useHlsPlayer({
|
||||
try {
|
||||
const absoluteUrl = isRelative ? new URL(trimmedLine, absoluteMasterSrc).toString() : trimmedLine;
|
||||
const subContent = await fetchWithFallback(absoluteUrl);
|
||||
const filteredSub = filterM3u8Ad(subContent, absoluteUrl, adFilterMode, adKeywords, customAdFilterCode);
|
||||
const filteredSub = filterM3u8Ad(subContent, absoluteUrl, adFilterMode, adKeywords);
|
||||
const subBlob = new Blob([filteredSub], { type: 'application/vnd.apple.mpegurl' });
|
||||
const subBlobUrl = URL.createObjectURL(subBlob);
|
||||
createdBlobs.push(subBlobUrl);
|
||||
@@ -424,5 +424,5 @@ export function useHlsPlayer({
|
||||
}
|
||||
extraBlobs.forEach(url => URL.revokeObjectURL(url));
|
||||
};
|
||||
}, [src, videoRef, autoPlay, onAutoPlayPrevented, onError, isAdFilterEnabled, adFilterMode, adKeywords, customAdFilterCode, mediaProxyEnabled]);
|
||||
}, [src, videoRef, autoPlay, onAutoPlayPrevented, onError, isAdFilterEnabled, adFilterMode, adKeywords, mediaProxyEnabled]);
|
||||
}
|
||||
|
||||
@@ -22,8 +22,6 @@ interface PlayerSettingsSnapshot {
|
||||
adFilter: boolean;
|
||||
adFilterMode: AdFilterMode;
|
||||
adKeywords: string[];
|
||||
customAdFilterCode: string;
|
||||
customAdFilterVersion: number;
|
||||
fullscreenType: 'auto' | 'native' | 'window';
|
||||
proxyMode: 'retry' | 'none' | 'always';
|
||||
danmakuEnabled: boolean;
|
||||
@@ -47,8 +45,6 @@ function getPlayerSettingsSnapshot(isPremium: boolean, mediaProxyEnabled: boolea
|
||||
adFilter: globalSettings.adFilter,
|
||||
adFilterMode: modeSettings.adFilterMode,
|
||||
adKeywords: globalSettings.adKeywords,
|
||||
customAdFilterCode: globalSettings.customAdFilterCode || '',
|
||||
customAdFilterVersion: globalSettings.customAdFilterVersion || 0,
|
||||
fullscreenType: modeSettings.fullscreenType,
|
||||
proxyMode: mediaProxyEnabled ? modeSettings.proxyMode : 'none',
|
||||
danmakuEnabled: modeSettings.danmakuEnabled,
|
||||
@@ -70,8 +66,6 @@ function playerSettingsEqual(a: PlayerSettingsSnapshot, b: PlayerSettingsSnapsho
|
||||
a.adFilter === b.adFilter &&
|
||||
a.adFilterMode === b.adFilterMode &&
|
||||
a.adKeywords === b.adKeywords &&
|
||||
a.customAdFilterCode === b.customAdFilterCode &&
|
||||
a.customAdFilterVersion === b.customAdFilterVersion &&
|
||||
a.fullscreenType === b.fullscreenType &&
|
||||
a.proxyMode === b.proxyMode &&
|
||||
a.danmakuEnabled === b.danmakuEnabled &&
|
||||
@@ -171,13 +165,6 @@ export function usePlayerSettings(isPremium: boolean = false) {
|
||||
updateGlobalSettings({ adKeywords: value });
|
||||
}, [updateGlobalSettings]);
|
||||
|
||||
const setCustomAdFilterCode = useCallback((code: string, version?: number) => {
|
||||
updateGlobalSettings({
|
||||
customAdFilterCode: code,
|
||||
...(version !== undefined ? { customAdFilterVersion: version } : {})
|
||||
});
|
||||
}, [updateGlobalSettings]);
|
||||
|
||||
const setFullscreenType = useCallback((value: 'auto' | 'native' | 'window') => {
|
||||
updateModeSettings({ fullscreenType: value });
|
||||
}, [updateModeSettings]);
|
||||
@@ -217,7 +204,6 @@ export function usePlayerSettings(isPremium: boolean = false) {
|
||||
setAdFilter,
|
||||
setAdFilterMode,
|
||||
setAdKeywords,
|
||||
setCustomAdFilterCode,
|
||||
setFullscreenType,
|
||||
setProxyMode,
|
||||
setDanmakuEnabled,
|
||||
|
||||
Reference in New Issue
Block a user