Commit Graph

591 Commits

Author SHA1 Message Date
Isaac Connor
17630b5609 fix: polyfill str_starts_with/str_ends_with/str_contains for PHP 7
These functions are PHP 8.0+ but ZoneMinder is called from views on
PHP 7 installs (event.php uses str_ends_with at file scope, triggering
a fatal "Call to undefined function" before the page can render).

Add function_exists-guarded polyfills at the top of functions.php so
PHP 8+ keeps the native implementations and PHP 7.x picks up the
fallbacks. functions.php is required by index.php before any view, so
all four call sites (functions.php, event.php, views/image.php) are
covered.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 12:34:54 -04:00
Isaac Connor
f179798b19 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-24 12:32:59 -04:00
Isaac Connor
9a83357e40 fix: add missing dash separator in Content-Range header
The HTTP Content-Range header for partial content must use the form
"bytes start-end/total". output_file() was emitting "bytes startend/total"
with no separator, producing an invalid header that breaks range requests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-24 12:32:59 -04:00
Isaac Connor
2de2ae44a1 fix: close SQL injection, command injection, and shell escaping gaps
FilterTerm.php:
- Use intval() on AlarmedZoneId value in SQL subquery to prevent
  injection via crafted filter val

report_event_audit.php, montagereview.php:
- Cast $selected_monitor_ids through array_map('intval') before
  interpolating into SQL IN clause (values come from $_REQUEST)

download_functions.php:
- Replace manual single-quoting with escapeshellarg() for merged
  file name in ffmpeg, tar, and zip commands (monitor names can
  contain shell metacharacters including single quotes)
- Same fix for export list file path

export_functions.php:
- Use escapeshellarg() on source and destination paths in cp -as
  commands during event export

functions.php:
- Validate column keys in getFormChanges() against /^[a-zA-Z0-9_]+$/
  to prevent SQL injection via crafted array keys from $_REQUEST
- Use dbEscape() and intval() for image/document MIME type and size
  fields instead of raw string interpolation
- Replace escapeshellcmd() with escapeshellarg() in deletePath()
  rm -rf command

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-23 19:34:05 -04:00
Isaac Connor
65bb4ad6dc fix: sanitize monitor Device path to prevent command injection (GHSA-g66m-77fq-79v9)
The Device field from the Monitors table was interpolated directly into
shell commands (qx(), backticks, exec()) without sanitization, allowing
authenticated users with monitor-edit permissions to execute arbitrary
commands as www-data via the Device Path field.

Defense in depth:
- Input validation: reject Device values not matching /^\/dev\/[\w\/.\-]+$/
  at save time in both web UI and REST API
- Output sanitization: use escapeshellarg() in PHP and quote validated
  values in Perl at every shell execution point

Affected locations:
- scripts/ZoneMinder/lib/ZoneMinder/Monitor.pm (control, zmcControl)
- scripts/zmpkg.pl.in (system startup)
- web/includes/Monitor.php (zmcControl)
- web/includes/functions.php (zmcStatus, zmcCheck, validDevicePath)
- web/includes/actions/monitor.php (save action)
- web/api/app/Model/Monitor.php (daemonControl, validation rules)
- web/api/app/Controller/MonitorsController.php (daemonStatus)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-23 19:34:05 -04:00
Isaac Connor
8864d5759d Merge pull request #4510 from SteveGilvarry/videojs_update
Videojs update
2026-01-10 10:21:50 -05:00
Claude
639bb6821e Fix ONVIF password URL encoding in camera configuration
When adding cameras via ONVIF probe, passwords containing special
characters (like parentheses, slashes, etc.) were being stored in the
database in URL-encoded form instead of plain text. This caused
authentication failures when the encoded password was used.

The issue was in extract_auth_values_from_url() which extracted
credentials from the stream URI but didn't decode them. Since the ONVIF
probe process double-encodes passwords (to survive POST encoding), and
monitor.php decodes once, the extracted password still remained
URL-encoded.

The fix adds urldecode() to both username and password after extraction,
ensuring they're stored in their original form in the database.

Example: Password "pass)word" was being stored as "pass%29word"
2026-01-09 11:00:59 +11:00
Steve Gilvarry
e389eed485 Final cleanup of videojs update 2025-12-31 19:33:54 +11:00
Steve Gilvarry
819da45ecc Fix double rotation 2025-12-31 19:33:54 +11:00
Steve Gilvarry
12450b390f Removing object tags as plugins are dead. I think this page still has reasons to exist but none of this code works in modern browsers. Well that is my opinion. 2025-12-31 19:33:54 +11:00
Steve Gilvarry
7abf180a27 Revert "Update getVideoStreamHtml to use videojs for mp4, I suspect this whole section including ZM_WEB_USE_OBJECT_TAGS can be deprecated. But minimal changes to upgrade videojs is all I am going for here"
This reverts commit ed64f084af.
2025-12-31 19:33:53 +11:00
Steve Gilvarry
caab1cc6ee Update getVideoStreamHtml to use videojs for mp4, I suspect this whole section including ZM_WEB_USE_OBJECT_TAGS can be deprecated. But minimal changes to upgrade videojs is all I am going for here 2025-12-31 19:33:53 +11:00
Steve Gilvarry
1d5498270a Fix nonce 2025-12-31 19:33:53 +11:00
Steve Gilvarry
4463f5dcf7 Videojs not loaded when inline script called. 2025-12-31 19:33:53 +11:00
Steve Gilvarry
277cf15518 Fix Nonce and attempt text tracks fixes 2025-12-31 19:33:53 +11:00
Steve Gilvarry
a71d5d9c3c Update Videojs to v8 2025-12-31 19:33:53 +11:00
Isaac Connor
6c2ad8d906 Use the same code for ImageStill and for ImageStream. Use ImageStream when mode == paused. Fixes #4491 2025-12-19 11:10:32 -05:00
Isaac Connor
cd2bd508ff Test for is_object(user) 2025-10-23 15:09:11 -04:00
Isaac Connor
cc76c723d2 Handle objects as well as arrays in array_to_hash 2025-10-23 15:07:57 -04:00
Isaac Connor
fdfe87be38 Fixup deletePath. Handle links, and report failures. Fix escaping the filename and put it in quotes in case it has spaces. Fixes #4446 2025-10-03 16:11:55 -04:00
Isaac Connor
80e46948c1 Add blob for hls.js 2025-06-26 14:57:50 -04:00
Isaac Connor
9125b8e6f9 Add support for sorting by Notes. Warn when the sort_field is unsupported 2024-11-27 13:56:35 -05:00
Isaac Connor
3b379e99c0 Introduce detaintPathAllowAbsolute. Use it to protect against Path Traversal in files view. Fixes GHSA-8fw2-wh82-vv4h 2024-09-30 06:42:10 -04:00
Isaac Connor
c45a2af08b Revert lack of src tag on event image 2024-09-05 09:18:41 -04:00
Isaac Connor
08d2f44613 Allow further query parameters after view in HomeView 2024-09-04 16:52:59 -04:00
Isaac Connor
b64461d518 Merge branch 'master' into only_stream_visible 2024-09-03 14:51:36 -04:00
Isaac Connor
f81d6fb823 Sanitise filter[Id] 2024-05-30 12:12:02 -04:00
Isaac Connor
b3c90c3216 Merge branch 'master' into only_stream_visible 2024-05-23 14:18:47 -04:00
Isaac Connor
c8d9cd02d7 Fix use of int as a function instead of a cast 2024-03-28 09:02:53 -04:00
Isaac Connor
b7bc7cef7e Only load non deleted Monitors 2024-01-28 16:52:36 -05:00
Isaac Connor
c138984fc9 XSS prevent on sort_asc and eid. Still need to protect filter 2024-01-25 18:48:39 -05:00
Isaac Connor
63def6b82e Add a function to_string that handles nulls, arrays, etc 2024-01-11 10:30:36 -05:00
Isaac Connor
2cc47557df Remove bogus adding RTSP2WEB to CSP and CORS 2024-01-02 16:44:05 -05:00
Isaac Connor
f064887451 Add ZM_RTSP2WEB_PATH to CSP_Headers 2024-01-02 16:25:28 -05:00
Isaac Connor
f9b82ca037 Always append username to zmu command line so that auth is more efficient 2023-12-12 11:14:29 -05:00
Isaac Connor
afb594aa19 Don't load Servers, they are loaded globally in config. Enforce int instead of string for range because fseek can't handle strings 2023-11-16 10:34:44 -05:00
Isaac Connor
2d46fc350a Spacing, test for setting of ZM_PATH_IP 2023-09-29 12:07:50 -04:00
Isaac Connor
7060945e97 Use new ZM_PATH_IP and ZM_PATH_IFCONFIG instead of hard coded paths. Fixes #3670 2023-09-28 13:32:42 -04:00
Isaac Connor
45bcb13045 Add backtrace to errors in json 2023-09-25 16:32:20 -04:00
Charlie Root
c4302c27ac Add code to test for existence of ip and support ifconfig 2023-09-13 10:14:21 -07:00
Isaac Connor
b7ed7a4bd8 in detaintPath also strip :// because php:// is a way to inject code 2023-09-11 12:34:31 -04:00
Isaac Connor
bc4d625ca4 Add systemd_isactive 2023-05-30 20:47:05 -04:00
Isaac Connor
969baa3891 Convert user from an array to a User object 2023-04-23 12:57:29 -04:00
Isaac Connor
593c7ac902 Handle HomeView not being set, and default it so that it is set 2023-03-24 12:53:49 -04:00
Isaac Connor
01ba5f59f9 Use dirname(__FILE__) instead of DOCUMENT_ROOT. Apparently many people have something wrong in DOCUMENT_ROOT. I don't understand it, but it seems like dirname(__FILE__) is a better solution anyways. 2023-03-21 18:22:53 -04:00
Isaac Connor
3e86454fc6 implement getHomeView function 2023-03-05 10:21:18 -05:00
Isaac Connor
6867b0c841 Correct the syntax of the CSP 2023-02-23 09:47:49 -05:00
Isaac Connor
d6dc1d3e30 Add object-src CSP directive 2023-02-20 18:15:16 -05:00
Isaac Connor
4f66ab3503 Introduce check_datetime function to validate dates 2023-02-20 11:53:53 -05:00
Isaac Connor
3268f95282 Fix detaintPath not stripping sequences like ..././ 2023-02-20 09:18:51 -05:00