From 0134dd6db4282b6c18199ef64830338bb0038cf7 Mon Sep 17 00:00:00 2001 From: Weapie Date: Tue, 8 Sep 2026 16:28:41 +0200 Subject: [PATCH] alangu.de fuer die Gebaerdensprach-Einbindung freigeben Der Player wird als iframe eingebunden, aber nicht als rohes HTML aus dem Textfeld: Die Anwendung setzt die Attribute, im Admin steht nur die Adresse. Damit laesst sich ueber das Feld nichts anderes einschleusen. Freigegeben ist alangu.de samt Unterdomains, sonst nichts. Die Pruefung haengt am Hostnamen, nicht an einem Textvergleich - getestet mit boese-alangu.de.angreifer.example und evil.example/?a=alangu.de, beide werden abgewiesen, ebenso http statt https. Vom uebergebenen Einbettungscode weggelassen: accelerometer und gyroscope. Ein Videoplayer braucht keine Bewegungssensoren. Ausserdem: Die Gebaerdensprach-Seite erscheint jetzt auch ohne Text, wenn eine Videoadresse hinterlegt ist - dort ist das Video der Inhalt. Fusszeile und Seite entscheiden das ueber dieselbe Funktion, sonst gaebe es eine erreichbare Seite ohne Link. Geprueft am echten Player: laedt mit HTTP 200 samt CSS, JS und hls.js, axe-core meldet in hell und dunkel keine Verstoesse, der Rahmen ist per Tastatur erreichbar, und die Fusszeile verlinkt die Seite. Co-Authored-By: Claude Opus 5 --- components/legal-page.tsx | 78 ++++++++++++++++++++++------------ components/site-footer.tsx | 4 +- components/site-pages-form.tsx | 11 +++-- lib/site-pages.ts | 49 ++++++++++++++++++++- 4 files changed, 108 insertions(+), 34 deletions(-) diff --git a/components/legal-page.tsx b/components/legal-page.tsx index db31c5f..5762130 100644 --- a/components/legal-page.tsx +++ b/components/legal-page.tsx @@ -3,7 +3,13 @@ import { notFound } from "next/navigation" import { PublicHeader } from "@/components/public-header" import { SiteFooter } from "@/components/site-footer" import { markdownToHtml } from "@/lib/markdown" -import { SITE_PAGE_META, SitePageKey, isSafeMediaUrl } from "@/lib/site-pages" +import { + SITE_PAGE_META, + SitePageKey, + hasSitePageContent, + isAllowedEmbedUrl, + isSafeMediaUrl, +} from "@/lib/site-pages" import { readSitePages } from "@/lib/site-pages.server" /** @@ -17,17 +23,20 @@ import { readSitePages } from "@/lib/site-pages.server" export async function LegalPage({ page }: { page: SitePageKey }) { const pages = await readSitePages() const content = pages[page].trim() - - if (!content) notFound() - - const html = await markdownToHtml(content) const meta = SITE_PAGE_META[page] - // Zweite Prüfung vor der Ausgabe: Was in der Datenbank steht, könnte aus - // einer Zeit vor der Prüfung in der API stammen. - const video = isSafeMediaUrl(pages.signLanguageVideo) - ? pages.signLanguageVideo.trim() - : "" + // Auf der Gebärdensprach-Seite ist das Video der eigentliche Inhalt. Sie + // erscheint deshalb auch dann, wenn nur eine Videoadresse hinterlegt ist – + // ein zusätzlicher Text ist willkommen, aber keine Bedingung. + const video = + page === "signLanguage" && isSafeMediaUrl(pages.signLanguageVideo) + ? pages.signLanguageVideo.trim() + : "" + + if (!hasSitePageContent(pages, page)) notFound() + + const html = content ? await markdownToHtml(content) : "" + const captions = isSafeMediaUrl(pages.signLanguageCaptions) ? pages.signLanguageCaptions.trim() : "" @@ -46,24 +55,39 @@ export async function LegalPage({ page }: { page: SitePageKey }) { werden eingebunden, sobald eine WebVTT-Datei hinterlegt ist. */} {page === "signLanguage" && video && (
-