Files
zoneminder/web/includes
Isaac Connor 9233d5cc2b fix: parse HTTP Range header correctly in output_file() fixes #4777
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>
2026-05-01 16:00:59 -04:00
..
2026-01-31 21:01:00 -05:00