You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Implement separate icon and background image libraries - #303
Replace the image-manager placeholder with separate icon and background uploaders and existing-image libraries. Show previews, dimensions and map references; allow confirmed physical deletion of unreferenced managed images. Accept PNG, JPG/JPEG and GIF (first frame), subject to upload size and pixel limits. Preserve unmanaged current icon selections and accept case-insensitive raster extensions after saving and reloading.
Protect reference scans and deletion with the config-directory mutex. Configuration saves and repairs use checked atomic replacement with revision comparison, so stale data cannot overwrite concurrent edits. Create-only cloning reserves the file before creating map/auth/settings records or invoking the runner, so failed writes leave no broken registrations. Management creation also checks create-only writes. Loaded page revisions reject stale editor submissions. Controls and initial JavaScript metadata share one WeatherMap snapshot; saves reload the full editor state through a clean view URL rather than updating a token beside stale controls. A deletion race producing a null loaded revision returns HTTP 404. INCLUDE reference scanning follows literal renderer paths, including filenames with brackets; the symlink regression uses a temporary library root without renaming shared checkout assets. Clone registration binds both source and destination IDs in prepared statements. Clones retain the mutex through registration and clean their own reservation and partial records on false returns or exceptions. Raw config saves no longer report false post-save conflicts, and request CAS races return HTTP 409. Repair copies legacy assets without removing originals. Initial reference discovery scans .conf maps only, while literal INCLUDE files remain supported. All editor save actions propagate write failures to AJAX callers; stale move/delete targets return errors. The Close control is keyboard-focusable, and upgrade test stubs run in isolated processes.
Snapshot tokens include all loaded INCLUDE dependencies, and their hashes are rechecked at commit time under the appropriate directory mutexes. A newly selected managed image must still exist when the configuration is committed; a deletion-winning race returns HTTP 409 and leaves the configuration unchanged. Existing missing legacy references remain editable for repair. New-map failures retain their save status and show retry guidance, and registration supports readable read-only config directories.
Image validation inspects the proposed serialized ICON/BACKGROUND directives, including raw node overrides. Deletion locks logical and physical configuration sources and rescans references after acquiring those locks, protecting alias/direct writers together.
New map copies validate every inherited managed image reference at commit time. Legacy repair confines sources to the plugin tree and verifies raster decoding. Save and Enter submission restore the active dialog action.
Preserve tokenized icon paths during copy/raw editing, validate concrete inherited references in management cloning before registration, and reject corrupt or symlinked existing repair destinations.
Uploads publish only complete encoded images after flush, close and permission setup; staging files stay outside selectable library names. Create-only copies and management cloning validate effective image references inherited through INCLUDE files, with snapshot dependencies checked under their directory locks. Legacy sized raster icon repair preserves width and height.
Mutation routes require loaded revisions. Clone failures and cleanup errors log internal diagnostics server-side and show generic retry guidance.
New-destination copies bind the loaded source root revision and target identity at commit time. Cleanup attempts run independently and retain the complete config if map-row removal is uncertain; failed unlink is logged. Canonical destination identity preserves CAS across aliases, and logical/physical INCLUDE snapshots detect retargeting.
Validation: affected branch PHP 8.3 and browser regressions pass in isolated Cacti fixtures. The combined changes pass 292 PHP tests (5859 assertions) and 16 browser regression programs. Changed-line coverage passes at 100% of measured production lines; existing controller/entry-point exemptions remain. Syntax, whitespace, translation and manifest checks pass. These revisions have not been deployed to the live installation.
Based on current develop, including the merged icon picker and gallery resize. Shared editor files overlap with the other feature PRs.
Build reference index before committing uploaded image
lib/editor.actions.php:1151
Build the reference index before persisting the upload. As written, wm_asset_store_image() commits the file first, then wm_asset_image_list() can throw while scanning an unreadable configuration or when the 1,000-file limit is exceeded. The endpoint then reports a failed upload even though the image remains on disk, and retries create duplicates.
Document new asset functions with complete PHPDoc
lib/editor.actions.php:1143
Both newly added functions need the repository-required PHPDoc blocks, including descriptions, parameters, and return values.
Add required PHPDoc structure to asset helpers
lib/editor.assets.php:26
The new asset helpers do not follow the repository-required PHPDoc shape. Add a description, blank separator, @param entries, another blank separator, and @return to each function in this file; the one-line block here also lacks the parameters and return type.
The dimensions string hard-codes both the ordering and px, so translators cannot localize it, contrary to the PR's stated requirement that dimensions remain localizable. Add a translated dimensions format to wmEditorText, render through that format here, and regenerate cacti.pot.
This newly introduced helper lacks the PHPDoc block required for every non-vendored function. Document its purpose, parameters, and return value using the repository's standard shape.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Create-only copies can commit stale source data because the source root revision is not checked at commit time.
0 open findings
Previously missed (1)
In code that hasn't changed since last review
Create-only copies omit source config from dependency checks
lib/WeatherMap.class.php:3909
Create-only copies do not include the loaded source root in the commit-time dependency check. When WriteConfig($destination, true) is called by either copy entry point, $sameFile is false, so expectedRevision is null and only INCLUDE hashes are passed here. A source edit or deletion after ReadConfig() but before this write can therefore produce a successful clone of stale source data. Add the source config path and config_revision to the dependency set for new-destination/create-only writes, as map_duplicate() already does explicitly.
Addressed in ac27769. The additional source-snapshot finding is addressed. New-destination/create-only engine writes add the loaded source root path and revision to the commit-time dependency set, including logical symlink identity where applicable. Source directories share the same mutex protocol and snapshot checks as includes. Regressions verify changed and deleted sources cannot produce a destination, while an unchanged source alias copies successfully. Shared alias identity and INCLUDE-retarget safeguards are included too. Validation: 292 PHP tests (5845 assertions), 16 browser regression programs; measured coverage, syntax, translation, manifest and whitespace checks pass. The live installation is unchanged.
Canonicalize directive paths before managed-image detection
lib/WeatherMap.class.php:2457
Managed-image detection is based on the directive’s raw text, while the deletion scanner normalizes renderer paths. Consequently, renderer-equivalent references such as ./images/objects/foo.png, absolute plugin paths, or Windows separators are protected from deletion when present, but are omitted from commit-time validation here. A raw edit or clone can therefore reintroduce one after the file was deleted and commit a broken reference. Canonicalize each directive path against the plugin root and classify it by containment in the two managed library directories.
The reason will be displayed to describe this comment to others. Learn more.
Reviewed all production hunks plus the new infrastructure. lib/WeatherMap.config.php adds a real directory-mutex (WeathermapConfig\acquire handles unwritable dirs read-only, releases cleanly, dependency locks are non-blocking and sorted to prevent opposing-include deadlock), and atomicWrite does tempnam→full bytes→fflush→fclose→chgrp/chmod→rename with revision CAS (hash_file against sha256 snapshot), INCLUDE-snapshot dependency matching, alias (logical vs physical path) identity checks, and create-only reserves. Uploads are validated by true getimagesize type allowlist (PNG/JPEG/GIF), 5 MB byte and 4 M pixel caps, re-encoded via GD under a random 60-char stem name with 0644 hardlink-reserve-then-unlink staging; managed libraries reject symlinks. Reference scans protect dynamic {token} paths conservatively (regex .* over literal segments) and the deletion path locks the configs directory plus every covered include directory before unlinking, rejecting referenced images. Editor/mgmt mutation paths require loaded-revision tokens (hash_equals) and now return 404/409/500/422 semantics; repair-maps keeps behavior with atomic staged copies and raster validation instead of blind rename/copy. WriteConfig's locale decimal-point bug is fixed (%f→%F plus explicit '.' for bandwidth strings) — configs written under comma-decimal locales were corrupt before. eval() is confined to test-harness files; no eval in production code. I approved the previously action_required workflow runs: Plugin Integration Tests and CodeQL now pass on this head (PHP 8.2/8.3/8.4 integration green). Note for merge order: branch is DIRTY against develop (overlaps #301/#302 shared files) — conflicts must be resolved and re-verified before landing. Approving the changes as reviewed.
Resolve conflicts between the image-library feature and develop's map-notes feature as unions: keep both CHANGELOG bullets; add develop's 'Could not lock map configurations.' pot string; register set_note_properties alongside the image_data/upload_image/delete_image editor actions and the note switch case; keep develop's richer AJAX error handler (409 + note errors); keep both the image (wmAssetRequest/wmAssetImages/wmOpenImages) and note (add_note/show_note) editor JS; retain the PR's asset-conflict/validation WriteConfig path and config_managed_assets/config_asset_conflict members plus develop's WMNotes payload and setNoteProperties; union the atomic-write regression assertions. php -l clean on all changed PHP.
Follow-up audit fixed the initial selector path as well as the AJAX library listing in f07f47a. get_imagelist now rejects non-files, symlinks, unreadable images, invalid image bytes and detected formats outside PNG/JPEG/GIF. Regression tests check that invalid data and BMP contents disguised as PNG are omitted from both the library list and initial selectors, in both icon and background categories.
Validation: 289 PHP tests and all browser regression programs pass. Syntax, whitespace, manifest and translation checks pass. Measured changed production PHP coverage is 100% (648/648 lines), with existing entry-point/controller exemptions.
Normalize managed-image paths before existence checks
lib/WeatherMap.class.php:2459
Both managed-image collectors recognize only literal images/objects/ and images/backgrounds/ prefixes. Renderer-valid paths such as ./images/objects/router.png, images/./objects/router.png, or absolute library paths therefore bypass commit-time existence checks. Raw edits can save a deleted image, and copies or management clones can inherit missing images through INCLUDE files. Normalize path identities consistently in both collectors and the loaded-reference baseline, including missing files, while preserving the original serialized paths and renderer tokens.
Preserve symlink semantics when resolving relative INCLUDE paths
lib/editor.assets.php:113
Lexically collapsing .. before resolving an INCLUDE changes its meaning when a preceding directory is a symlink. For INCLUDE linked/../include.conf, the renderer reads from the symlink target's parent, but this scan may check a different, nonexistent file and skip it. Images referenced only by that include can then be deleted. Make relative INCLUDE paths absolute without collapsing their components, leaving resolution to the filesystem.
if (is_readable($realfile) && (preg_match('/\.(gif|jpg|png)$/i', $file))) {
if (is_file($realfile) && !is_link($realfile) && is_readable($realfile) && (preg_match('/\.(gif|jpe?g|png)$/i', $file))) {
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replace the image-manager placeholder with separate icon and background uploaders and existing-image libraries. Show previews, dimensions and map references; allow confirmed physical deletion of unreferenced managed images. Accept PNG, JPG/JPEG and GIF (first frame), subject to upload size and pixel limits. Preserve unmanaged current icon selections and accept case-insensitive raster extensions after saving and reloading.
Protect reference scans and deletion with the config-directory mutex. Configuration saves and repairs use checked atomic replacement with revision comparison, so stale data cannot overwrite concurrent edits. Create-only cloning reserves the file before creating map/auth/settings records or invoking the runner, so failed writes leave no broken registrations. Management creation also checks create-only writes. Loaded page revisions reject stale editor submissions. Controls and initial JavaScript metadata share one WeatherMap snapshot; saves reload the full editor state through a clean view URL rather than updating a token beside stale controls. A deletion race producing a null loaded revision returns HTTP 404. INCLUDE reference scanning follows literal renderer paths, including filenames with brackets; the symlink regression uses a temporary library root without renaming shared checkout assets. Clone registration binds both source and destination IDs in prepared statements. Clones retain the mutex through registration and clean their own reservation and partial records on false returns or exceptions. Raw config saves no longer report false post-save conflicts, and request CAS races return HTTP 409. Repair copies legacy assets without removing originals. Initial reference discovery scans .conf maps only, while literal INCLUDE files remain supported. All editor save actions propagate write failures to AJAX callers; stale move/delete targets return errors. The Close control is keyboard-focusable, and upgrade test stubs run in isolated processes.
Snapshot tokens include all loaded INCLUDE dependencies, and their hashes are rechecked at commit time under the appropriate directory mutexes. A newly selected managed image must still exist when the configuration is committed; a deletion-winning race returns HTTP 409 and leaves the configuration unchanged. Existing missing legacy references remain editable for repair. New-map failures retain their save status and show retry guidance, and registration supports readable read-only config directories.
Image validation inspects the proposed serialized ICON/BACKGROUND directives, including raw node overrides. Deletion locks logical and physical configuration sources and rescans references after acquiring those locks, protecting alias/direct writers together.
New map copies validate every inherited managed image reference at commit time. Legacy repair confines sources to the plugin tree and verifies raster decoding. Save and Enter submission restore the active dialog action.
Preserve tokenized icon paths during copy/raw editing, validate concrete inherited references in management cloning before registration, and reject corrupt or symlinked existing repair destinations.
Uploads publish only complete encoded images after flush, close and permission setup; staging files stay outside selectable library names. Create-only copies and management cloning validate effective image references inherited through INCLUDE files, with snapshot dependencies checked under their directory locks. Legacy sized raster icon repair preserves width and height.
Mutation routes require loaded revisions. Clone failures and cleanup errors log internal diagnostics server-side and show generic retry guidance.
New-destination copies bind the loaded source root revision and target identity at commit time. Cleanup attempts run independently and retain the complete config if map-row removal is uncertain; failed unlink is logged. Canonical destination identity preserves CAS across aliases, and logical/physical INCLUDE snapshots detect retargeting.
Validation: affected branch PHP 8.3 and browser regressions pass in isolated Cacti fixtures. The combined changes pass 292 PHP tests (5859 assertions) and 16 browser regression programs. Changed-line coverage passes at 100% of measured production lines; existing controller/entry-point exemptions remain. Syntax, whitespace, translation and manifest checks pass. These revisions have not been deployed to the live installation.
Based on current develop, including the merged icon picker and gallery resize. Shared editor files overlap with the other feature PRs.