28004 Commits

Author SHA1 Message Date
Isaac Connor
19b977141b Merge branch 'master' of github.com:ZoneMinder/zoneminder 2026-05-08 10:18:02 -04:00
Isaac Connor
0950131b2a fix: urlToApi falls back to location.host in single-server case
When ZM_SERVER_ID is unset, Servers[0] is a synthetic default whose
Hostname/Port come from PHP fallbacks (HTTP_HOST, HTTP_X_FORWARDED_PORT,
ZM_BASE_URL) which can disagree with the host:port the browser is
actually using. That caused montagereview XHR to land on the wrong
physical server (e.g. default :443 of a hostname where ZM lives on :81).

For Servers without an Id, derive host:port from location.host so XHR
follows the same connection as the UI. Multi-server entries with a real
Id keep using their configured Hostname/Port.
2026-05-08 10:10:20 -04:00
Isaac Connor
753a2923b1 Merge pull request #4798 from IgorA100/patch-84371
Fix: Download incomplete.mp4 event file (view_video.php)
2026-05-06 19:42:09 -04:00
Isaac Connor
c4073c964c feat: encoder parameter templates with editor + REST API closes #4778 closes #4802
Adds a curated, per-encoder parameter-template library to ZoneMinder:

- Monitor edit page: a new Template row above the EncoderParameters
  textarea offers per-encoder templates (Balanced / Archival / Low
  Power / Low CPU). Apply merges the template's params into the
  textarea, preserving user-only keys. Advisory lint flags option
  keys that aren't recognised for the selected encoder. Switching
  encoders offers a same-name template on the new encoder via a
  native confirm.

- Options page: a new Encoder Templates tab with full CRUD —
  list / edit / copy / delete — backed by a new CakePHP REST API
  at /api/encoder_templates.

- Storage: a new EncoderTemplates DB table seeded with 14 shipped
  defaults across libx264 / libx265 / h264_nvenc / hevc_nvenc /
  h264_vaapi / hevc_vaapi. The table is mutable; ZM upgrades do not
  re-seed user-edited rows.

- valid_keys (the lint allow-list) stays in PHP code as ffmpeg
  vocabulary, not user data.

- Default params explicitly include pix_fmt to avoid the yuvj420p
  HEVC HW-decode rejection issue we hit earlier.

No C++ change. The textarea content is parsed by the existing
av_dict_parse_string call in src/zm_videostore.cpp.

version.txt -> 1.39.6.

Specs: docs/superpowers/specs/2026-05-0{1,2}-*.md
Plans: docs/superpowers/plans/2026-05-0{1,2}-*.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:24:17 -04:00
IgorA100
cf23c07913 Update view_video.php 2026-05-06 17:44:58 +03:00
IgorA100
08f7afe6a4 More correct assignment of the $path_info value (view_video.php) 2026-05-06 17:33:04 +03:00
IgorA100
fc9a8c593e Update ru_ru.php 2026-05-06 12:38:14 +03:00
IgorA100
1ddc78734b Instead of "MP4" we will specify "video" (event.php) 2026-05-06 12:29:58 +03:00
IgorA100
3a2f49a6e6 Potential fix for pull request finding
OK, let's simplify this.
Let's hope that either there won't be any national characters in the file name, or that basename() will handle them correctly.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-06 12:22:29 +03:00
Isaac Connor
f223c9e770 Merge pull request #4773 from IgorA100/patch-974485
Feat: Merge an array from a custom language file and en_gb.php
2026-05-05 21:34:44 -04:00
Isaac Connor
21c68cc839 Merge pull request #4794 from ZoneMinder/copilot/fix-triggered-events-issue
fix: triggered events only fire ~1/3 of the time due to hash iteration ordering race
2026-05-05 21:30:07 -04:00
Isaac Connor
2630d55ffb feat: add Report::canEdit() and CreatedBy column
Add a CreatedBy column to the Reports table and a canEdit() method on
the Report class so $report->canEdit() (already called from
web/ajax/reports.php) resolves to a real check. canEdit() permits the
report owner (CreatedBy == user) or any user/role with System=Edit.
Wire actions/report.php to stamp CreatedBy on first save and refuse
save/delete on existing reports the current user cannot edit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 20:24:15 -04:00
Isaac Connor
b8d93989ad ci: skip CodeQL on changes that contain no scanned languages
Adds paths-ignore for db/, docs/, distros/, misc/, onvif/, scripts/
and *.md/*.sql/*.in files. CodeQL analyses cpp and javascript only,
so changes confined to these paths produce no new findings and don't
need to spend Actions minutes or generate ~610 MB of cache.

Verified the ignored directories contain no .c/.cpp/.h/.js files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 20:24:15 -04:00
Isaac Connor
8af2ed4678 ci: add scheduled workflow to prune old Actions caches
Runs daily at 03:00 UTC and via workflow_dispatch. Groups caches by
key prefix (stripping trailing run/sha suffixes) and keeps the N
newest per prefix, deleting the rest. Defaults to keeping 2.

Without this, CodeQL builds left ~10 GB of per-commit caches behind,
exhausting the org Actions storage quota.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 20:24:15 -04:00
Isaac Connor
aa59b9aa7e Merge pull request #4796 from IgorA100/patch-409967
Analyzing "space" and "," key presses for positioning in the tag input field on Event page
2026-05-05 18:58:24 -04:00
Isaac Connor
a10ad1eb5f Merge pull request #4795 from ZoneMinder/copilot/fix-auth-hash-ips-issue
fix: AUTH_HASH_IPS auth failure when behind reverse proxy
2026-05-05 18:57:39 -04:00
Isaac Connor
936e377fa7 Merge pull request #4791 from IgorA100/patch-452396
Prevent the scrollbar from appearing when displaying table column visibility settings (options.css)
2026-05-05 18:43:55 -04:00
IgorA100
ab09205cbd Avoid PHP Notice (view_video.php) 2026-05-05 19:08:56 +03:00
IgorA100
6ce9171b38 Fix: Pop-up file name on download button (event.php) 2026-05-05 17:36:44 +03:00
IgorA100
5589476cba Fix: Loading incomplete.mp4 event file (view_video.php)
Issue closure: #4774
2026-05-05 17:26:08 +03:00
Isaac Connor
e6161a9465 Merge pull request #4797 from IgorA100/patch-724861
Fix: Display snapshot for incomplete event file (Update image.php)
2026-05-05 09:02:19 -04:00
IgorA100
bcdaae1d4a Fix: Display snapshot for incomplete event file (Update image.php) 2026-05-05 15:54:09 +03:00
Isaac Connor
51b89ac6d3 Fix a2enmod cgi => a2enmod rewrite causing install to fail. 2026-05-04 22:08:17 -04:00
Isaac Connor
f32e455bce Add depenencies for resolute raccoon 2026-05-04 21:49:52 -04:00
IgorA100
b7a9026855 Analyzing "space" and "," key presses for positioning in the tag input field (event.js)
Supplement to #4783
2026-05-04 20:18:28 +03:00
copilot-swe-agent[bot]
5b51d086e1 fix: use HTTP_X_FORWARDED_FOR in auth hash validation to fix AUTH_HASH_IPS with reverse proxy
When AUTH_HASH_IPS is enabled and ZoneMinder is behind a reverse proxy
(e.g. Nginx in front of Apache), the hash is generated using
HTTP_X_FORWARDED_FOR (the real client IP) but was validated using only
REMOTE_ADDR (the proxy's IP), causing all authentication to fail.

Fix by consistently using HTTP_X_FORWARDED_FOR (first IP only, to guard
against spoofed multi-value headers) with REMOTE_ADDR as fallback in
all three places:
- web/includes/session.php: where remoteAddr is stored for hash generation
- web/includes/auth.php: getAuthUser() validation (PHP, also used by zms CGI)
- src/zm_user.cpp: zmLoadAuthUser() validation (C++ zms binary)

refs #4758

Agent-Logs-Url: https://github.com/ZoneMinder/zoneminder/sessions/959dfe9d-edea-4de5-a3a0-f90b758e5628

Co-authored-by: connortechnology <925519+connortechnology@users.noreply.github.com>
2026-05-04 14:53:38 +00:00
copilot-swe-agent[bot]
bd7685a683 Initial plan 2026-05-04 14:40:01 +00:00
copilot-swe-agent[bot]
b799962e2a fix: ensure trigger_state written last in zmTriggerEventOn to fix 1/3 event trigger rate
Agent-Logs-Url: https://github.com/ZoneMinder/zoneminder/sessions/68794b2b-7137-4888-b66e-20c629112a57

Co-authored-by: connortechnology <925519+connortechnology@users.noreply.github.com>
2026-05-04 13:22:13 +00:00
copilot-swe-agent[bot]
9abd20dd15 Initial plan 2026-05-04 13:18:02 +00:00
Isaac Connor
7d19da131e Merge pull request #4781 from IgorA100/patch-873418
Fix: .tags-container on Event page if screen is narrow and there are many tags
2026-05-03 22:14:56 -04:00
IgorA100
2264741fe1 Prevent the scrollbar from appearing when displaying table column visibility settings (options.css)
For example, on the Servers page when there are only a few servers in the table.
2026-05-04 01:19:00 +03:00
IgorA100
3166cb58c4 Merge branch 'master' into patch-974485 2026-05-03 23:59:59 +03:00
IgorA100
0cf64c9ae4 Added $CLANG (lang.php) 2026-05-03 23:52:58 +03:00
IgorA100
a18f142318 Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-03 23:43:36 +03:00
Isaac Connor
adf35aaeb0 Merge pull request #4790 from ZoneMinder/copilot/clarify-onvif-options-documentation
docs: document all ONVIF_Options key=value pairs
2026-05-03 16:26:04 -04:00
copilot-swe-agent[bot]
04aa0a7781 docs: document all ONVIF_Options key=value pairs
Replaces the uninformative "Any ONVIF options required. This is an
optional field." with a full reference covering:
- key=value,key=value format with an example
- pull_timeout, subscription_timeout, max_retries,
  timestamp_validity, soap_log, renewal_enabled, expire_alarms,
  closes_event — including defaults, valid ranges, and when to use each

Also fixes pre-existing typo: "alam" → "alarm".

Agent-Logs-Url: https://github.com/ZoneMinder/zoneminder/sessions/149f7873-ca12-424f-85d4-4bdc179d2488

Co-authored-by: connortechnology <925519+connortechnology@users.noreply.github.com>
2026-05-03 20:21:49 +00:00
copilot-swe-agent[bot]
320e52feb1 Initial plan 2026-05-03 20:18:15 +00:00
Isaac Connor
cfdcc1d907 Merge pull request #4786 from ZoneMinder/revert-4742-fix/deprecate-zm-colour-use-avpixelformat
Revert "fix: replace ZM_COLOUR system with AVPixelFormat for format dispatch"
2026-05-02 18:27:03 -04:00
Isaac Connor
60b6b37c60 Revert "fix: replace ZM_COLOUR system with AVPixelFormat for format dispatch" 2026-05-02 18:26:48 -04:00
Isaac Connor
4701ff2650 Merge pull request #4780 from IgorA100/patch-162247
Fix: ESLint (audioMotionAnalyzer.js)
2026-05-02 18:25:01 -04:00
Isaac Connor
81519fb2f1 Merge pull request #4742 from ZoneMinder/fix/deprecate-zm-colour-use-avpixelformat
fix: replace ZM_COLOUR system with AVPixelFormat for format dispatch
2026-05-02 18:24:37 -04:00
Isaac Connor
11544d86e3 fix: PR #4742 round 2 review feedback
Eight Copilot comments from the second review pass:

1. monitor.php (#3): "Deprecated - will be auto-detected..." note next
   to TargetColorspace bypassed translate(). Added DeprecatedColoursSetting
   key to en_gb and routed the deprecation note through translate() so it
   localises with the rest of the form.

2. tests/zm_pixformat.cpp (#4): zm_colours_from_pixformat / round-trip
   tests didn't cover the new YUV422P/YUVJ422P entries (added by
   02e6be6b4). Added explicit assertions in both test cases — bumps
   pixformat coverage from 105 to 115 assertions.

3. zm_image.cpp WriteBuffer (#5): linesize and size were derived from
   p_width * p_colours, which undercounts planar YUV* (where p_colours=1
   via the GRAY8 alias collision but actual buffer needs ~1.5x/2x for
   chroma). Use av_image_get_buffer_size and av_image_get_linesize for
   the AVPixelFormat instead, with bail-out on either failing.

4. zm_image.cpp AssignDirect (#6, #7): av_image_get_buffer_size returns
   int and can be negative; assigning that into unsigned size/allocation
   wrapped to a huge value. Check the return first, treat negative as the
   same "unsupported format" failure as zm_colours_from_pixformat
   returning false, and reset size/allocation/linesize/pixels to 0
   (alongside imagePixFormat=NONE/colours=0/subpixelorder=0) so the
   Image is left in a single coherent invalid state instead of partially
   stale.

5. zm_image.cpp Assign (#8): av_get_pix_fmt_name(format) can return
   nullptr (e.g. AV_PIX_FMT_NONE / unknown); passing that into
   Debug(..., "%s", ...) would segfault. Capture once with a fallback
   string before logging.

6. zm_monitor.cpp Capture path (#9): same nullptr issue with two Debug
   calls — capture native_fmt_name once with fallback.

7. zm_monitor.cpp can_passthrough comment (#10): comment claimed
   YUVJ422P would be converted to YUV420P because Image drops chroma,
   but can_passthrough now allows YUV422P/YUVJ422P passthrough since
   02e6be6b4 added 4:2:2 support. Updated the comment to describe the
   current behavior (full 4:2:0 + 4:2:2 planar passthrough plus GRAY8
   and RGB24/32) so the code and the rationale agree.

Tests: 76 cases, 788 assertions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 17:59:51 -04:00
Isaac Connor
f2fc00bce2 Merge pull request #4782 from IgorA100/patch-73438
Chore: Minor improvements to Files page
2026-05-02 14:55:56 -04:00
Isaac Connor
b1dac9caed Merge pull request #4783 from IgorA100/patch-790352
Feat: Tag Management Optimization on Event page
2026-05-02 14:55:22 -04:00
Isaac Connor
0eb36d0c52 fix: silence spurious Overlay subpixel-order warning post-AVPixelFormat
Image::Overlay() warned when (colours == image.colours &&
subpixelorder != image.subpixelorder), which made sense when
(colours, subpixelorder) was the canonical format identifier.

Now that imagePixFormat is canonical, the check produces false
positives in a normal code path: zm_monitor.cpp's analysis pass calls
analysis_image->Overlay(*(zone.AlarmImage())) where the destination is
YUV420P (colours=1 via the GRAY8/YUV420P=1 alias collision in
zm_rgb.h, subpixelorder=ZM_SUBPIX_ORDER_YUV420P=11) and the source is
the zone's GRAY8 alarm mask (colours=1, subpixelorder=NONE=2). The
overlay dispatch below already handles this correctly via
zm_bytes_per_pixel(imagePixFormat) == 1 on both sides — only the Y
plane of the dest is touched, leaving chroma untouched, which is
exactly the intent. The warning was just noise.

Reframe the check around imagePixFormat: warn only when the
AVPixelFormat actually matches but the ZM (colours, subpixelorder)
metadata diverges, which would indicate a real format-tracking bug.
The new message also names the AVPixelFormat for context, instead of
two opaque integers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 14:33:20 -04:00
Isaac Connor
e74916ad0e fix: PR #4742 review feedback + drop stray u_buffer assignments
Two issues flagged by Copilot review on the AVPixelFormat-migration PR,
plus one build fix that was needed to land them:

1. zm_local_camera.cpp set subpixelorder to BGR for V4L2_PIX_FMT_RGB24
   captures. V4L2_PIX_FMT_RGB24 is byte-order R,G,B in memory and is
   mapped to AV_PIX_FMT_RGB24 by getFfPixFormatFromV4lPalette earlier
   in the same file, so the matching ZM subpixel order is RGB. Setting
   BGR meant red and blue were swapped in the captured image whenever
   a V4L2 camera was configured with the RGB24 palette. Long-standing
   bug — preserved unchanged through the AVPixelFormat migration —
   now fixed to ZM_SUBPIX_ORDER_RGB.

2. Image::AssignDirect(const AVFrame*) called zm_colours_from_pixformat
   without checking the return value, leaving colours/subpixelorder at
   their previous values for any unsupported AVPixelFormat. Wrap the
   call and on failure put the Image into an explicit invalid state
   (AV_PIX_FMT_NONE plus zeroed colours/subpixelorder) so the
   inconsistency surfaces immediately instead of producing wrong-format
   reads downstream.

3. Drop the u_buffer = ... / v_buffer = ... assignments inside
   Image::Assign()'s identity-copy path. Those members exist on the
   ai_server lineage but not on master, so the PR branch did not
   compile against master as-is. av_image_copy reads the planes
   directly out of temp_frame->data, so the assignments were not
   load-bearing — they look like leftover state-tracking that didn't
   survive the upstreaming. Comment notes why the lines were removed.

Tests pass: 76 cases, 778 assertions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 13:36:43 -04:00
IgorA100
ab4050cbfb Tag Management Optimization (event.js)
After entering a tag name and pressing "Enter," focus will be moved to "#tagInput." This allows you to enter multiple tags without manually positioning the cursor.
When the cursor is in "#tagInput" and the "Ctrl" + "Left" or "Ctrl" + "Right" key combination is pressed, a new tag (or an existing one attached to an event) entered in "#tagInput" will be added and the previous or next event will be navigated to. This eliminates unnecessary mouse movements for pressing the "tagPrevBtn" and "tagNextBtn" buttons.
2026-05-02 16:59:49 +03:00
IgorA100
8552404159 Update files.php 2026-05-02 15:58:48 +03:00
IgorA100
a14f59e34c Added table styles (files.css) 2026-05-02 15:53:22 +03:00
IgorA100
0adda15ffd Fix: .tags-container on Event page if screen is narrow and there are many tags (skin.css) 2026-05-02 13:37:03 +03:00