This repository has been archived on 2026-08-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
melo-app/lib/utils/sanitize.dart
T
Dustin dfa19c999b v2.50.3 — sanitize.dart gehärtet: Windows-Namen + Traversal-Sequenzen
## lib/utils/sanitize.dart
- Windows-reservierte Namen (CON, NUL, PRN, AUX, COM1-9, LPT1-9) abgefangen — auch mit Endung (CON.txt) und case-insensitiv; COM10/LPT10 bleiben erlaubt
- Mehrfache ..-Sequenzen nach Sonderzeichen-Entfernung → unknown
- Trimmen VOR der Punkt-Prüfung (Regression: ' ..' ergab vorher '..' = Path-Traversal)
- Trailing Punkte/Leerzeichen entfernt (Windows-Dateisystem ignoriert sie)
- Umlaute bleiben erhalten (unicode:true + \p{L}/\p{N} statt ASCII-\w — 'Müller.mp3' wurde vorher zu 'Mller.mp3')

## test/sanitize_test.dart (18 Tests)
- Traversal: Slash/Backslash-Pfade, '..', ' ..', '..:..', versteckte Dateien
- Windows: alle reservierten Namen exakt/mit Endung/case-insensitiv, COM10-Freigabe, Prefix-Fälle (console, LPT1 - Drucker)
- Normalisierung: NULL-Bytes, Steuerzeichen, Sonderzeichen, trailing Dots, leer, 200-Limit, Umlaute
2026-08-04 20:48:31 +02:00

51 lines
2.1 KiB
Dart

/// Zentrale Sanitize-Funktion für Dateinamen.
/// Verhindert Path-Traversal (../), Null-Bytes, Windows-reservierte Namen
/// (CON, NUL, PRN, AUX, COM1-9, LPT1-9) und andere gefährliche Zeichen.
String sanitizeDateiname(String name) {
// 1. Extrahiere nur den Dateinamen (keine Pfad-Komponenten)
var safe = name.split('/').last.split('\\').last;
// 2. Entferne NULL-Bytes und andere gefährliche Steuerzeichen
safe = safe.replaceAll(RegExp(r'[\x00-\x1F\x7F]'), '');
// 3. Entferne alles außer Wort-Zeichen, Leerzeichen und Bindestrichen
// (unicode: true + \p{L}/\p{N} → auch Umlaute wie ü/ä/ö bleiben,
// sonst würden deutsche Dateinamen wie "Müller.mp3" → "Mller.mp3")
safe = safe.replaceAll(RegExp(r'[^\p{L}\p{N}_\s.-]', unicode: true), '');
// 4. Trimmen VOR der Punkt-Prüfung — sonst umgeht " .." (Leerzeichen vor
// den Punkten) die Entfernung führender Punkte und ergäbe ".." als Namen.
safe = safe.trim();
// 5. Entferne führende Punkte (versteckte Dateien)
safe = safe.replaceAll(RegExp(r'^\.+'), '');
// 6. Nach Sonderzeichen-Entfernung können Punkt-Sequenzen übrig bleiben:
// ".." / "..." als kompletter Name (oder führende "..") wäre
// Pfad-Traversal → verwerfen.
if (safe == '..' || safe == '...' || safe.startsWith('..')) {
safe = 'unknown';
}
// 7. Windows-reservierte Namen abfangen (CON, NUL, PRN, AUX, COM1-9,
// LPT1-9) — auch mit Endung (z.B. "CON.txt") und case-insensitiv.
// Windows behandelt diese Namen unabhängig von der Endung als Geräte.
final basis = safe.split('.').first.toUpperCase();
if (RegExp(r'^(CON|NUL|PRN|AUX|COM[1-9]|LPT[1-9])$').hasMatch(basis)) {
safe = 'unknown';
}
// 8. Windows: Punkte/Leerzeichen am Ende entfernen (werden vom
// Dateisystem ignoriert und erzeugen sonst Kollisionen)
safe = safe.replaceAll(RegExp(r'[. ]+$'), '');
// 9. Trimmen und Default-Name falls leer
safe = safe.trim();
if (safe.isEmpty) safe = 'unknown';
// 10. Auf sinnvolle Länge kürzen (255 Zeichen ist typisches Dateisystem-Limit)
if (safe.length > 200) safe = safe.substring(0, 200);
return safe;
}