Commit Graph
16 Commits
Author SHA1 Message Date
SteveGilvarryandClaude Opus 4.8 186d31ed23 fix: write scratch temp files under ZoneMinder's temp dir, not system tmp
Two spots wrote temp files outside ZoneMinder's controlled temp tree:

- zmvideo.pl concat mode built its ffmpeg concat list at a predictable
  path, /tmp/<concat_name>.concat.lst, in world-writable /tmp. A
  predictable name there is open to a symlink/race and leaks monitor and
  event names. Create it instead with File::Temp (randomized name, atomic
  O_EXCL) inside ZM_TMPDIR. The list entries are absolute paths, so its
  location does not affect ffmpeg's resolution.

- web/ajax/training.php created its detection scratch image with
  tempnam(sys_get_temp_dir(), ...), escaping ZM's temp tree and its
  cleanup. Use tempnam(ZM_DIR_TEMP, ...) so it stays under the configured
  temp dir.

Both now resolve to the per-distro temp dir (e.g. /var/lib/zoneminder/temp
on RedHat, /var/tmp/zm on Debian), keeping scratch files inside the tree
that packaging and systemd hardening already cover.

refs #2915

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 18:10:19 +10:00
Pliable PixelsandClaude Opus 4.6 2a319adead fix: support arguments in ZM_TRAINING_DETECT_SCRIPT config
Split the config value on the first whitespace so the executable path
is validated separately and extra arguments (e.g. -c config.yml) are
passed through to the command line.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 04:43:16 -05:00
Pliable PixelsandClaude Opus 4.6 af0a0694d7 fix: rebuild data.yaml on annotation delete, code cleanup across training files
- Rebuild data.yaml when deleting annotations (delete and browse_delete
  actions) so unused class names are removed and IDs re-indexed
- Extract rebuildDataYaml() helper, replacing duplicated inline rebuild
  logic in browse_delete
- Make sidebar trash button always visible for recovery from inconsistent
  states; _deleteAllTrainingData now also clears editor annotations
- Consolidate permission/POST checks into arrays before switch statement
- Extract helper functions: resolveTrainingPath, getFrameStem,
  getFramePaths, _loadEventData, _confirmDiscardIfDirty,
  _resetAnnotationState, _applyEventData, _getNormalizedRect
- Extract 8 pure browse utility functions to module level
- Add floatval() validation on bbox coordinates in save action
- Add LOCK_EX to writeDataYaml, add .fail(logAjaxFail) to AJAX calls
- Replace var with let/const, add 'use strict', remove IIFEs
- CSS custom properties for repeated values, requestAnimationFrame
  throttle for canvas mousemove
- Align with ZM conventions: error messages include username/action,
  trailing ajaxError after switch, "use strict" at line 1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 04:28:14 -05:00
Pliable PixelsandClaude Opus 4.6 e50f14466d feat: add virtual Objects folder to training data browser
Add browse_objects PHP action that groups annotated images by class
label and collects background images separately. Inject a virtual
"Objects" folder at the top of the browse tree with fa-tags icon.
Expanding it shows per-class sub-items with count badges and a
background images category. Clicking a class displays a thumbnail
grid; clicking a thumbnail navigates to the annotation editor for
that event/frame.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:50:48 -05:00
Pliable PixelsandClaude Opus 4.6 72370d8af9 feat: load saved annotations when editing from browse panel
Add load_saved PHP action that reads YOLO label files and converts
normalized coordinates back to pixels. When navigating to an event
via the browse edit button, saved annotations are loaded into the
editor so users can review and modify previous work.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:31:46 -05:00
Pliable PixelsandClaude Opus 4.6 1189011060 fix: use content directory for training data fallback path
Change default training data directory from @ZM_CACHEDIR@/training to
@ZM_CONTENTDIR@/training so it lives alongside events storage instead
of inside the web cache folder. Update PHP fallback to use
dirname(ZM_DIR_EVENTS) accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:24:44 -05:00
Pliable PixelsandClaude Opus 4.6 62678b24f8 fix: address Copilot review — path traversal, temp leak, double undo, help text
- Fix path traversal via directory prefix matching: append
  DIRECTORY_SEPARATOR to base path before strpos containment check
  (2 locations in training.php)
- Fix temp file leak: rename tempnam() base file to .jpg instead of
  creating a second file, leaving the original orphaned
- Remove raw_output from detect response (information disclosure)
- Fix double _pushUndo on Delete key (keydown handler + deleteAnnotation)
- Fix help text: "alongside events storage" → "inside the ZoneMinder
  cache directory" to match actual ZM_DIR_CACHE default (2 locations)
- Add missing .frame-total span element in event.php

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:25:07 -05:00
Pliable PixelsandClaude Opus 4.6 1ea70c715c fix: nav guard for unsaved annotations, pending box warnings, UX polish
- Replace beforeunload with click-capture nav guard to avoid blank
  screen caused by ZM's global beforeunload content-hide animation
- Wrap streamPrev/streamNext to prompt before stream teardown
- Warn when saving with unaccepted (orange) detection boxes
- Add PHP fallback for empty TRAINING_DATA_DIR using ZM_DIR_CACHE
- Show spinning loader overlay with blur while frame images load
- Change detection running status to blue (info) color
- Fix label picker uppercase caused by ZM global button CSS
- Add TrainingPendingOnly, TrainingPendingDiscard translation keys

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 11:09:03 -05:00
Pliable PixelsandClaude Opus 4.6 eaaa8f4016 fix: code review fixes, version bump to 1.39.1, remove non-repo files
- Rename migration to zm_update-1.39.1.sql, add DEALLOCATE PREPARE,
  fix Requires format to 'ZM_OPT_TRAINING=1'
- Bump version.txt to 1.39.1
- Remove docs/plans/ and utils/deploy-training.sh from repo
- training.php: remove PHP fallback path, add validFrameId() helper,
  move buildTree() to top-level with symlink skip and depth limit,
  split canView/canEdit permissions, require POST for destructive ops,
  remove path disclosure, sanitize log output, add is_executable check
- training.js: remove console.log calls, fix _setStatus boolean to
  string type, fix double undo push, switch delete ops to POST,
  replace hardcoded English strings with translation keys
- event.js.php: remove window.annotationEditor global, add new
  translation keys to trainingTranslations
- event.php: add frame skip and browse buttons, break up long HTML
- en_gb.php: add missing translation keys in alphabetical order
- training.css: add frame browse overlay and pagination styles

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 10:25:46 -05:00
Pliable PixelsandClaude Opus 4.6 948667c7d6 feat: two-panel training data file browser with preview and inline delete
- Rewrite browse overlay as two-panel layout: directory tree (left) + file listing/preview (right)
- Add browse_file PHP action to serve images and text files from training dir
- Add browse_delete PHP action with class ID remapping to keep data.yaml consistent
- Overlay bounding boxes on image previews from corresponding label files
- Add per-file delete button (trash icon) that removes both image and label pair
- Move delete-all trash icon to sidebar header, status messages below sidebar
- Use existing ZM utilities: human_filesize() for file sizes, detaintPath() for path security
- Add SelectBoxFirst translation for delete-without-selection feedback
- Fix orphaned class ID bug: remap IDs in all label files when classes are removed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 07:53:47 -05:00
Pliable PixelsandClaude Opus 4.6 6978d4d6ac feat: add annotate button to objdetect modal, compact stats, delete-all, UI polish
- Add Annotate button to objdetect modal (events list) with auto-open
  via ?annotate=1 URL parameter
- Compact stats layout: label and value on same row, trash icon to
  delete all training data with typed confirmation prompt
- Add delete_all AJAX action to training.php
- Reduce all annotation panel font sizes to 0.8rem to match ZM base
- Fix label picker white-on-white by setting explicit colors
- Add beforeunload guard for unsaved annotations
- Switch detect action from shell_exec to exec for better error handling
- Show "no objects detected" as info status, not error
- Increase status message display time to 10 seconds
- Add i18n strings: ConfirmDeleteTrainingData, DeleteAllTrainingData,
  TrainingDataDeleted

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 00:03:35 -05:00
Pliable PixelsandClaude Opus 4.6 99ae8d38ca fix: allow saving background images and delete pending boxes
- Remove empty annotations rejection from PHP save action
- Empty label file = background/negative image in YOLO format
- JS prompts user when saving with no objects: "Save as background
  image? Background images help reduce false positives."
- Stats now show background image count separately
- Delete Box button already works on selected pending boxes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:24:30 -05:00
Pliable PixelsandClaude Opus 4.6 567e3d395b fix: use ZM_EVENT_IMAGE_DIGITS for frame filename padding
Was hardcoded to %06d but the actual padding depends on the
ZM_EVENT_IMAGE_DIGITS config (typically 5).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:11:57 -05:00
Pliable PixelsandClaude Opus 4.6 a2ff391eb1 feat: add Detect button to run object detection on current frame
Add ZM_TRAINING_DETECT_SCRIPT config option for specifying the path
to an external detection script (e.g. zm_detect.py). When configured,
a Detect button appears in the annotation editor that:
- Runs the script with -f <image> -m <monitor_id>
- Parses the --SPLIT-- JSON output for labels, boxes, confidences
- Displays results as orange (pending) bounding boxes
- Users can accept (checkmark) or reject (x) each detection
- Only accepted annotations are saved to the training set

Also adds accept/reject UI in the sidebar object list, with orange
color for pending detections and normal colors for accepted ones.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:55:00 -05:00
Pliable PixelsandClaude Opus 4.6 32b6e736de fix: annotation UI improvements and remove objdetect frame
- Remove objdetect from frame selector and fid validation
- Fix 500 error: replace non-existent ZM\AuditAction() with ZM\Info()
- Scale canvas text/borders/handles relative to canvas width for readability
- Change annotate button icon from fa-pencil-square-o to fa-crosshairs
- Bump CSS font sizes from 0.75-0.9rem to 0.95-1rem
- Use orange (#ff8c00) stroke for in-progress bounding box drawing
- Flash save button green (btn-saved class) on successful save
- Hide #eventVideo when annotation panel is open
- Skip empty label files in getTrainingStats() count
- Reject save with empty annotations array
- Add undo support for delete and AJAX delete when all boxes removed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 22:24:31 -05:00
Pliable PixelsandClaude Opus 4.6 a8c9c180b6 feat: add custom model training annotation UI
Add canvas-based bounding box annotation editor to the event view for
correcting object detection results and building YOLO training datasets.

- Two new config options: ZM_OPT_TRAINING (toggle) and ZM_TRAINING_DATA_DIR
- AJAX backend (training.php) with load/save/delete/status actions
- Canvas annotation editor (training.js) with draw/resize/relabel/undo
- Frame navigation (alarm/snapshot/objdetect/numbered frames)
- Roboflow-compatible YOLO output (images/all/, labels/all/, data.yaml)
- Training data statistics with per-class image counts and guidance
- Full i18n support via en_gb.php SLANG/OLANG entries
- Label validation, YOLO coordinate clamping, audit logging
- DB migration for existing installs (zm_update-1.39.2.sql)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:35:55 -05:00