The script targeted Windows in two ways that would have broken or, worse, run
silently wrong under pwsh on Linux/macOS:
- The default output path was the literal 'Configuration\ip-blocklist.txt'. On
Windows Join-Path happens to produce the right thing; on Linux it produces a
single file whose name contains backslashes, in the wrong directory. Now
joined one segment at a time (the multi-argument Join-Path is PowerShell 6+,
so this stays 5.1-compatible).
- The -MinInterval parse used the current culture. Under a comma-decimal locale
[double]::TryParse('2.5') does not fail -- it treats '.' as a group separator
and SUCCEEDS with 25, so `-MinInterval 2.5h` would silently become a 25 hour
cooldown. Parsed with InvariantCulture now, which is also the only reason the
bad-input throw is reachable at all.
Also: the generated= header timestamp is formatted with InvariantCulture, since
':' is the culture-defined time separator in a custom format string and the
shard compares that marker verbatim to detect a new list. Token matching is
ordinal.
The atomic swap picks File.Move(src, dst, overwrite) where it exists -- one
rename on every platform, MoveFileEx on Windows and rename(2) on Unix -- and
falls back to File.Replace on Windows PowerShell 5.1, which has no 3-argument
Move. ServicePointManager is only touched on the Desktop edition that needs it.
Verified end to end under de-DE: correct cooldown, invariant header, atomic
replace, no leftover .tmp.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>