Commit Graph

121 Commits

Author SHA1 Message Date
Isaac Connor
fb0e5b780e feat: write static m3u8 manifest as DefaultVideo for segmented events
Write a static m3u8 file with relative segment paths to the event
directory on event close. Set DefaultVideo to the m3u8 filename
instead of the first segment.

This fixes all existing code that assumes DefaultVideo is a single
file spanning the entire event:
- Frame extraction (ffmpeg -ss $delta -i $DefaultVideo) works because
  ffmpeg reads m3u8 as input and handles cross-segment seeking
- file_exists() and file_size() work on the physical m3u8 file
- In-progress viewing still works (DefaultVideo is incomplete.mp4
  during recording, updated to m3u8 on close)

Web playback detects .m3u8 extension in DefaultVideo and routes to
the dynamic view_event_hls.php (which adds auth tokens to segment
URLs) instead of view_video.php.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 15:05:29 -04:00
Isaac Connor
d0611fec26 Merge branch 'master' into segment_recording 2026-03-17 14:09:58 -04:00
Isaac Connor
5c233bf2d2 feat: segmented video recording with HLS playback for instant browser start
Events now record as multiple ~10-second MP4 segments instead of one
monolithic file. Each segment is remuxed to non-fragmented faststart on
close, giving browsers a proper moov atom with full sample tables.

The problem: fragmented MP4s (empty_moov+frag_keyframe) have no seek
table in the moov. Chrome probes fragment boundaries with dozens of
small range requests, each going through the full PHP stack (auth, DB,
fopen). This causes multi-second delays before playback starts.

The fix: short segments with faststart moov + HLS manifest for seamless
playback across segments. Chrome gets a complete seek table per segment
from a single moov read.

C++ changes:
- Event::openSegment()/closeSegment() manage VideoStore lifecycle per segment
- AddPacket_() rotates at keyframe boundaries when segment exceeds 10s
- Each segment remuxed to faststart via new remux_to_faststart() utility
- Segment metadata written to Event_Video_Segments table on event close
- DefaultVideo set to first segment for backward compatibility

Database:
- New Event_Video_Segments table (EventId, SegmentIndex, Filename,
  StartDelta, Duration, Bytes) with cascade delete

Web playback:
- New view_event_hls.php generates VOD m3u8 manifest from segments table
- event.php detects segments, uses application/x-mpegURL source type
- VideoJS 8.23.4 handles HLS natively via built-in http-streaming
- view_video.php updated to serve individual segment files by name
- Old single-file events still play via direct MP4 (backward compatible)

Download/export:
- download_functions.php lists segment files in ffmpeg concat input
- Produces single merged MP4 with zero re-encoding (existing mechanism)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 11:43:53 -04:00
Isaac Connor
5561829450 fix: include username in auth relay and fix stale auth in stream restart
- Add user= parameter to get_auth_relay() so zms can use the indexed
  Username column instead of iterating all users to validate the hash
- Apply the same fix to Event.php getStreamSrc() and getThumbnailSrc()
- Tighten Monitor.php from isset() to !empty() for consistency
- In MonitorStream.js start(), check if the auth hash in the img src
  matches the current auth_hash before resuming via CMD_PLAY. If stale,
  fall through to rebuild the URL with fresh auth_relay. This prevents
  long-running montage pages from spawning zms with expired credentials.
- Downgrade zms auth failure from Error to Warning

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 10:01:47 -04:00
Isaac Connor
c8f352a095 Merge remote-tracking branch 'upstream/master' into ai_server 2026-03-09 10:11:12 -04:00
Isaac Connor
ffe6362dc3 fix: harden web interface against injection and SSRF vulnerabilities
FilterTerm.php:
- Replace eval() with safe compare() method for SystemLoad, DiskPercent,
  and DiskBlocks filter conditions (RCE via crafted op/val)
- Validate operator against allowlist in constructor
- Sanitize collate field to alphanumeric/underscore only (SQLi)

onvifprobe.php:
- Use escapeshellarg() on interface, device_ep, soapversion, username,
  and password arguments passed to execONVIF() (command injection)

Event.php:
- Use escapeshellarg() on all arguments to zmvideo.pl instead of
  escapeshellcmd() on the whole command (command injection via format)
- Anchor scale regex with ^ and $ to prevent partial matches

image.php:
- Restrict proxy URL scheme to http/https only (SSRF via file:// etc)

filterdebug.php:
- Use already-sanitized $fid instead of raw $_REQUEST['fid'] (XSS)

MonitorsController.php:
- Use escapeshellarg() on token, username, password, and monitor id
  in zmu shell command instead of escapeshellcmd() on whole command

HostController.php:
- Use escapeshellarg() on path in du command (command injection via mid)
- Remove space from daemon name allowlist (argument injection)

EventsController.php:
- Remove single quotes from interval expression regex (SQLi)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 23:30:49 -04:00
Isaac Connor
c056f3fb70 Merge remote-tracking branch 'upstream/master' into ai_server 2026-02-26 19:20:47 -05:00
Isaac Connor
b036408a5b Fix RCE vulnerability via API config edit privilege escalation
Add RBAC checks to ConfigsController edit() and delete() requiring
System=Edit permission, matching the pattern used by other controllers.
Harden System/Readonly column checks with !empty() to handle missing
columns gracefully. Fix command injection in Event.php by using
ZM_PATH_FFMPEG constant with escapeshellarg() instead of hardcoded
unsanitized ffmpeg call. Add is_executable() validation at all exec()
sites using ZM_PATH_FFMPEG as defense-in-depth against poisoned config
values.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 13:51:30 -05:00
Isaac Connor
76fae7d78e Handle event having no width or height 2026-02-25 17:36:16 -05:00
Isaac Connor
aeff647f90 Apply intval to scale calculations 2025-10-10 13:26:30 -04:00
Isaac Connor
2ba42345a7 Don't commit updated DiskSpace to the db. If we want to do that, we can call Save. This prevents UI from hanging waiting for this update to happen 2025-08-07 11:29:46 -04:00
IgorA100
f2aed5fc21 Chore: Adjust spaces, tabs, newlines 2024-04-03 22:58:21 +03:00
IgorA100
70de139e77 Feat: Ability to download videos on the "Event" page with a multiport configuration 2024-03-28 19:47:53 +03:00
Simpler1
992b729329 chore(lint): $ locations 2024-03-28 09:59:58 -04:00
Isaac Connor
be61184faf Add defaults to GenerateVideo, don't chdir, fix other code 2023-12-01 13:05:36 -05:00
Isaac Connor
49af487746 port over generateVideo from perl side and stick into Event. 2023-12-01 12:46:26 -05:00
adhamiamirhossein
27977acdd4 fix: php 8.3 deprecated get_class method call without argument 2023-11-22 10:48:04 +03:30
Isaac Connor
092f8df115 Handle scale=0 in getImageSrc 2023-11-20 17:23:51 -05:00
Isaac Connor
c287b7f645 Add Tags() and Event_Tags() functions to Event 2023-10-20 14:02:25 -04:00
Isaac Connor
feb3d91e8b Remove Tags from Event Data defaults. I don't think it is meant to be there 2023-10-06 14:54:17 -04:00
Isaac Connor
82aeac076d Fix incorrect var name frameid=>fid in find_virtual_frame 2023-09-26 12:10:36 -04:00
Isaac Connor
f8c89a0405 Merge branch 'master' into tags 2023-09-14 16:42:06 -04:00
Isaac Connor
82e972943e Add frame loading including virtual frames 2023-09-08 14:18:11 -04:00
Simpler1
18d74ed7ac (feat): Tags
fix(tag): Create tags on mobile

chore(tags): Change TagName to Name

chore(tags): eslint

chore(tags): dbFetchAll to dbQuery for removetag

chore(events): eslint (attempt 2)

feat(tags): Better handling of keyboard

fix(tags): Enter key for creating new tag

fix(tags): Don't allow space as a tag name

feat(tags): Delete tag if last assignment removed

fix(tags): Increase height of dropdown

in progress

fix(Tags): Use T.Id on the events page dropdown

fix(Tags): Remove $availableTags from events.php

chore(sql): Formatting sql statements

feat(Tags): Working OR on filters and events pages

fix(filter): Populate availableTags

chore(Tags): code formatting

fix(tag): Add tag on create tag

Fix(tags): Remove tag from available if last

feat(tags): Add zm_update.sql

fix(chosen): Undo css width

fix(chosen): tags dropdown width

fix(tags): dropdown over timeline

fix(tags): Full width input

fix(events): Refresh table on page show

chore(filter): Clean up availableTags

chore(event): Clean up available & selected Tags

fix(event): Update available tags on remove

fix(event): Remove hack for selected tags

feat(tags): Blur input after adding tag

doc(tags): Initial tags documentation

fix(tags): Dark theme dropdown

fix(tags): Dark theme for tags on input

fix(tags): Dark theme for highlight in dropdown

fix(tags): Populate filter tags droplist

chore(): Bump zm_update to 1.37.42

chore(tags): Move mobile check to skin.js

chore(tags): Comment debug statements

fix(tags): Enter key to create tag on mobile Chome

chore(tags): Space in 'All Tags' for translation

Temporary commit to handle cookie expiration times

chore(tags): Remove unnecessary Tag(s) from en_gb

chore(): Cleanup unnecessary Error and Debug

chore(): Resolve merge conflicts

chore(): Address merge conflicts with master
2023-08-31 15:50:08 -04:00
Isaac Connor
4b417b8937 Fix other cases of user as an array 2023-04-23 15:35:26 -04:00
Isaac Connor
d9f5d3c357 Implement StartDateTimeSecs 2023-04-22 10:48:41 -04:00
Isaac Connor
312d0ba841 Use objdetect as thumbnail if it exists. 2023-04-22 10:47:33 -04:00
Isaac Connor
44c7582003 Don't shorten analysis 2023-02-20 17:30:48 -05:00
Martin Tiernan
68283c01eb Added length and frames getters 2022-11-21 09:06:38 -06:00
Isaac Connor
a891b528d1 Use Monitor::canView in Event::canView 2022-11-02 13:25:44 -04:00
Isaac Connor
3079438038 Move createVideo from functions to Event 2022-09-06 13:46:41 -04:00
Isaac Connor
b611a4fc08 Use y instead of Y for path generation when using Deep scheme. Fixes #3583 2022-09-04 13:53:19 -04:00
Isaac Connor
907cdcd952 convert from strftime() to date() when forming the event path 2022-06-01 15:46:53 -04:00
Isaac Connor
1314295020 Don't update DiskSpace with a 0 value when listing events. This generally happens with missing events and causes too much contention on the Events and summaries tables 2022-05-30 10:26:04 -04:00
Isaac Connor
7515711eb8 Implement Server function which figures out which Server likely has the video. Use it to remove duplicate logic 2022-02-03 14:45:17 -05:00
Isaac Connor
193f349e38 implement Event::canEdit 2021-11-12 13:37:01 -05:00
Isaac Connor
b9efe627f3 implement Event->canView 2021-08-18 10:53:59 -04:00
Isaac Connor
973533c809 Use method to handle case where Event wasn't found 2021-01-25 18:39:57 -05:00
Isaac Connor
2d33dd5386 Rename StartTime, EndTime in Events to StartDateTime and EndDateTime 2020-11-04 13:52:32 -05:00
Isaac Connor
10c0a6617c Return Debug to a regular function to match other logging functions. Since we switched to using namespaces we no longer clash with cake_php. 2020-10-14 10:39:25 -04:00
Isaac Connor
c934dee233 Do not allow the deleting of Archived Events 2020-09-03 17:02:48 -04:00
Isaac Connor
d0f6f8755c Implement a remove_from_cache function so we can free mem for objects we are not interested in 2020-08-27 17:14:47 -04:00
Isaac Connor
d2b7aa3e90 Populate Scheme of default Storage Area when event Storage is not valid 2020-08-17 16:55:29 -04:00
Isaac Connor
da757d075b Only save the DiskSpace on completed events. Fixes #3007 2020-08-07 09:53:35 -04:00
Isaac Connor
7fd038d99b spacing and quotes 2020-07-22 17:28:12 -04:00
Isaac Connor
54a6dfff66 API on remote server requires RELAY not be none. Log an error. Fix url being ruined by auth credentials 2020-02-25 17:12:48 -05:00
Isaac Connor
6cf448c74e remove debug and spacing 2020-02-25 11:08:23 -05:00
Isaac Connor
9036b6db77 fix typo 2020-01-13 16:17:39 -05:00
Isaac Connor
f7e2359818 Implement a clear_cache function so that we can free up cached objects 2020-01-13 10:57:56 -05:00
Isaac Connor
4632bbd124 Apply relevant changes to deal with php7,4 deprecations 2019-12-07 11:45:32 -05:00