fix(downloads): cap the media filename by BYTES, not characters

/code-review (S1, finding 1): sanitize truncated the title at 120 CHARACTERS, but a
path component's hard limit is 255 BYTES and rel_path packs channel + date + id + ext
into that same component — so a long accented/multi-byte title (Hungarian titles are
common here) could already overflow to ENAMETOOLONG, and the new _a{id} suffix shrank
the margin further. sanitize now truncates on a UTF-8 boundary by byte length, so the
title (≤120B) + channel (≤80B) + fixed parts stay comfortably under 255B. Two tests:
byte-cap on accented input, and every rel_path component ≤255B for a pathological
long-accented channel+title+asset_id.
This commit is contained in:
2026-07-22 00:00:44 +02:00
parent 04b002b2b0
commit cb4d06bb3d
2 changed files with 27 additions and 2 deletions
+21
View File
@@ -29,6 +29,14 @@ class TestSanitize:
def test_length_is_capped(self):
assert len(sanitize("x" * 500, limit=10)) <= 10
def test_cap_is_by_bytes_not_characters(self):
# Accented (2-byte UTF-8) letters must not blow past the byte limit — the FS component cap
# is 255 BYTES, so a char-only cap would overflow for multi-byte titles.
out = sanitize("á" * 500, limit=10)
assert len(out.encode("utf-8")) <= 10
# And it never splits a character (would raise otherwise / leave a replacement char).
out.encode("utf-8").decode("utf-8")
def test_empty_or_all_junk_falls_back_to_untitled(self):
assert sanitize("") == "untitled"
assert sanitize("🔥🔥") == "untitled"
@@ -64,6 +72,19 @@ class TestRelPath:
assert rel_path(self.meta, "mp4", layout="flat") == "Cool_Clip_[abc123].mp4"
assert rel_path(self.meta, "mp4", layout="flat", asset_id=7) == "Cool_Clip_[abc123]_a7.mp4"
def test_every_component_stays_within_the_255_byte_fs_limit(self):
# A long accented channel AND title, plus the asset-id suffix, must not overflow any path
# component (the byte cap in sanitize is what guarantees this).
meta = MediaMeta(
video_id="abcdefghijk",
title="Á" * 300,
uploader="Ö" * 300,
upload_date=date(2024, 5, 2),
)
out = rel_path(meta, "webm", asset_id=999999)
for component in out.split("/"):
assert len(component.encode("utf-8")) <= 255, component
class TestDownloadFilename:
def test_appends_the_container_extension(self):