diff --git a/apps/web/src/app/(portal)/modules/cert-manager/components/SplitTab.tsx b/apps/web/src/app/(portal)/modules/cert-manager/components/SplitTab.tsx index 0d3e9b3..16ccce9 100644 --- a/apps/web/src/app/(portal)/modules/cert-manager/components/SplitTab.tsx +++ b/apps/web/src/app/(portal)/modules/cert-manager/components/SplitTab.tsx @@ -4,6 +4,7 @@ import { useState } from 'react'; import { useTranslations } from 'next-intl'; import { zipSync } from 'fflate'; import { type SplitResponse, type CertRole, splitCertsAction, downloadBase64 } from '../actions'; +import { sanitizeZipFilename } from '../zip-filename'; interface SplitTabProps { file: File | null; @@ -17,7 +18,11 @@ const ROLE_STYLES: Record = { 'end-entity': 'bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300', }; -function downloadAllAsZip(certs: SplitResponse['certs']) { +// `downloadAllAsZip` liegt ausserhalb der Komponente und kann den +// Uebersetzungs-Hook nicht selbst aufrufen — der uebersetzte Name kommt +// deshalb als Parameter herein (Restposten 1, quick-260921-jt4). Die +// einzelnen Dateinamen IM Archiv stammen weiterhin unveraendert aus der API. +function downloadAllAsZip(certs: SplitResponse['certs'], zipFilename: string) { const files: Record = {}; for (const cert of certs) { const bytes = Uint8Array.from(atob(cert.content), (c) => c.charCodeAt(0)); @@ -35,7 +40,11 @@ function downloadAllAsZip(certs: SplitResponse['certs']) { const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; - a.download = 'certificates.zip'; + // T-JT4-05: der uebersetzte Name kann Zeichen tragen, die Windows + // verbietet (Umlaute, Sonderzeichen) — sanitizeZipFilename schneidet ihn + // auf das fuer eine Windows-Freigabe Zulaessige zurueck, unabhaengig davon, + // ob der aktuelle Katalogwert zufaellig schon harmlos ist. + a.download = sanitizeZipFilename(zipFilename); a.click(); URL.revokeObjectURL(url); } @@ -81,7 +90,7 @@ export function SplitTab({ file, pemText: _pemText, password: _password }: Split {result && result.certs.length > 1 && (