fix(v5): MakeMKV-Installer aus dem Internet Archive nur nach Rückfrage, mit Größe und SHA-256

WAS: makemkvInstallerHolen fragt vor der Archiv-Quelle über eine
Freigabe-Funktion; ohne Freigabe wird das Archiv übersprungen und im
Bericht genannt. Der Kern stellt die Frage ans Fenster (beschaffung-status
mit `frage`), die MakeMKV-Karte zeigt sie mit „Archiv-Kopie laden" /
„Lieber nicht" (beschaffung-antwort); ohne Antwort in zehn Minuten gilt
Nein. Die geladene Datei wird mit Größe und SHA-256 gemeldet.
WARUM: Durchsicht 12.09.2026, Fund F16 (Commander-Entscheid: Archiv nur
nach Rückfrage) — eine unsignierte EXE von fremder Hand, die mit
Adminrechten läuft, entscheidet der Nutzer, nicht Rippy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-09-12 21:43:13 +02:00
co-authored by Claude Opus 5
parent 3dacd7cb4f
commit ae82d8c0fd
7 changed files with 140 additions and 9 deletions
+30 -2
View File
@@ -22,7 +22,8 @@
// 3. NIE eine gute Datei durch eine halbe ersetzen: Geladen wird in
// `.neu`, geprüft, erst dann getauscht.
import { spawnSync } from 'node:child_process'
import { createWriteStream, openSync, readSync, closeSync, mkdirSync, renameSync, rmSync, statSync } from 'node:fs'
import { createHash } from 'node:crypto'
import { createWriteStream, openSync, readFileSync, readSync, closeSync, mkdirSync, renameSync, rmSync, statSync } from 'node:fs'
import { win32 as pfad } from 'node:path'
import { werkzeugOrdner } from './katalog'
@@ -285,6 +286,22 @@ export interface BeschaffungErgebnis {
pfad: string
quelle: string
version: string
/** 5.7.0 (F16): Größe und SHA-256 der geladenen Datei — damit man sie
* gegen die Herstellerangabe halten kann, sobald die Seite wieder da ist. */
bytes: number
sha256: string
}
/** SHA-256 einer Datei als Hex — für die Anzeige neben dem Installer. */
export function pruefsumme(dateiPfad: string): string {
return createHash('sha256').update(readFileSync(dateiPfad)).digest('hex')
}
/** Welche Quelle ein Rückfrage braucht: alles außer Hersteller und eigener
* Basis. Das Internet Archive liefert eine unsignierte EXE, die mit
* Adminrechten läuft — das entscheidet der Nutzer, nicht Rippy (F16). */
export function brauchtFreigabe(quellenName: string): boolean {
return quellenName === 'Internet Archive'
}
/** Lädt den MakeMKV-Installer über die Quellenkette in Rippys
@@ -297,6 +314,9 @@ export async function makemkvInstallerHolen(
holen: typeof fetch = fetch,
ordner: string = pfad.join(werkzeugOrdner(), 'downloads'),
pruefen: typeof dateiPruefen = dateiPruefen,
/** 5.7.0 (F16): Darf eine Quelle mit Rückfrage benutzt werden? Ohne
* diese Funktion wird sie übersprungen — nie still geladen. */
freigabe?: (quellenName: string, url: string) => Promise<boolean>,
): Promise<BeschaffungErgebnis> {
mkdirSync(ordner, { recursive: true })
const ziel = pfad.join(ordner, `Setup_MakeMKV_v${version}.exe`)
@@ -304,6 +324,14 @@ export async function makemkvInstallerHolen(
const fehlschlaege: string[] = []
for (const [name, url] of makemkvQuellen(version, basis)) {
if (brauchtFreigabe(name)) {
const erlaubt = freigabe !== undefined && (await freigabe(name, url))
if (!erlaubt) {
fehlschlaege.push(`${name}: nicht freigegeben`)
melden(`${name} wurde nicht freigegeben.`, null)
continue
}
}
melden(`MakeMKV ${version} wird geladen (${name}) …`, 0)
try {
await dateiLaden(url, vorlaeufig, melden, holen)
@@ -312,7 +340,7 @@ export async function makemkvInstallerHolen(
// Erst tauschen, wenn geprüft — ein halber Download darf eine gute
// Datei nicht ersetzen.
renameSync(vorlaeufig, ziel)
return { pfad: ziel, quelle: name, version }
return { pfad: ziel, quelle: name, version, bytes: statSync(ziel).size, sha256: pruefsumme(ziel) }
} catch (fehler) {
fehlschlaege.push(`${name}: ${fehler instanceof Error ? fehler.message : String(fehler)}`)
melden(`${name} hat nicht geliefert.`, null)