Zone.Name, Event.Name, Event.Notes and Server.Name are persisted
user-controllable strings that were emitted without escaping, so a user
with edit rights on the object could store markup that runs in the
browser of anyone who later views the page, including an administrator.
Zone and Server save through getFormChanges + raw SQL, so they never
pass the object filter_regexp layer that strips markup elsewhere.
HTML and SVG sinks now use validHtmlStr():
- Zone::svg_polygon() escapes the <title>, covering every caller
(event view, montage and stream).
- views/zone.php and views/plugin.php headings.
- ajax/modals/server.php modal title.
The two inline-JS sinks in views/js/event.js.php are require_once'd
inside a <script nonce> block, so a </script> in Event.Name or Notes
broke out of the element and the nonce did not help. Notes was also
interpolated into a template literal, making backtick and ${} live.
Both now emit json_encode(..., JSON_HEX_TAG|JSON_HEX_APOS|
JSON_HEX_QUOT|JSON_HEX_AMP), which supplies its own double quotes.
Refs GHSA-72c3-g86w-f587.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When zone coordinates are stored as pixel values (e.g. from a missed DB
migration), the web layer now detects values > 100 and converts them to
percentages using the monitor's dimensions, mirroring the existing C++
detection logic in zm_zone.cpp. This prevents limitPoints() from clamping
pixel values to 0-100 and zones rendering incorrectly in SVG overlays.
- Add convertPixelPointsToPercent() helper in functions.php
- Call conversion before limitPoints() in zone.php and zones.php
- Update Zone::svg_polygon() to accept monitor dimensions and convert
- Pass ViewWidth/ViewHeight to svg_polygon() from Monitor::getStreamHTML()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Convert zone coordinates from absolute pixel values to percentages
(0.00-100.00) so zones automatically adapt when monitor resolution
changes. This eliminates the need to manually reconfigure zones after
resolution adjustments.
Changes:
- Add DB migration (zm_update-1.37.81.sql) to convert existing pixel
coords to percentages, recalculate area, and update Units default
- Add Zone::ParsePercentagePolygon() in C++ to parse percentage coords
and convert to pixels at runtime using monitor dimensions
- Backwards compat: C++ Zone::Load() checks Units column and uses old
pixel parser for legacy 'Pixels' zones
- Update PHP coordsToPoints/mapCoords/getPolyArea for float coords,
replace scanline area algorithm with shoelace formula
- Update JS zone editor to work in percentage coordinate space with
SVG viewBox "0 0 100 100" and non-scaling-stroke for consistent
line thickness
- Position zone SVG overlay inside imageFeed container via JS to align
with image only (not status bar)
- Support array of zone IDs in Monitor::getStreamHTML zones option
- Update monitor resize handler: percentage coords don't need rescaling,
only threshold pixel counts are adjusted
- Add 8 Catch2 unit tests for ParsePercentagePolygon
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>