mirror of
https://github.com/ZoneMinder/zoneminder.git
synced 2026-05-08 14:43:37 -04:00
The previous implementation used `str_replace($range, '-', $range)` which is a no-op (wrong arg order, return value discarded), then cast the raw Range value (e.g. "12345-67890" or "-500") to int. The function then ignored the requested END entirely and always streamed from the parsed start to EOF. For a suffix range like `Range: bytes=-500` -- which Chrome's media stack sends to locate the moov atom in many HEVC mp4s -- (int)"-500" is -500, producing Content-Length = filesize + 500. fseek with SEEK_SET fails for negative offsets, so the body delivered was filesize bytes against an inflated Content-Length, triggering ERR_CONTENT_LENGTH_MISMATCH in the browser and blocking HEVC playback in the files view. Parse `bytes=start-end`, `bytes=start-`, and `bytes=-suffix` per RFC 7233, clamp the end to file size, return 416 for unsatisfiable ranges, set Content-Length to the actual byte count served, and stop reading once that many bytes have been emitted. Guard ob_flush() with ob_get_level() so it does not warn when no buffer is active. Verified on pseudo by loading an HEVC mp4 in Chrome -- the ERR_CONTENT_LENGTH_MISMATCH is gone, the browser parses metadata (duration, dimensions) and buffers playback data normally. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>