* security: validate local_graph_id before the aggregate graph item sequence query (GHSA-6mjm-5vwr-3fr2)
* security: bind local_graph_id via array filter and add regression test (GHSA-6mjm-5vwr-3fr2)
* Resolving issue #8063: Support searching by graph ID on Graphs and Aggregate Graphs pages
* Restrict graph-ID matching to all-digit search values to avoid MySQL leading-digit coercion
* Fix PHP CS Fixer coding-standards violations flagged by CI
* test(cdef): enforce resolver coverage
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci(cdef): pin cache action correctly
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test: isolate CDEF coverage bootstrap
* fix(cdef): fail closed on invalid recursive definitions
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): log corrupt resolver records
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): bound and isolate recursive resolution
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): preserve resolver failure state
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): isolate invalid graph expressions
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): abort unsafe consumer operations
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): close consumer failure paths
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): make aggregate updates atomic
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): keep repair queries auditable
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): bind bulk deletes and escape item types
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(cdef): guard corrupt types and repair reporting
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(aggregate): propagate push-out failures
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(aggregate): document mutable message checks
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
* fix(aggregate): restore item-override saves and bulk-action input names
The form_save() gate dropped save_component_item during the develop
refactor, so item-override saves redirected away unsaved, and the
migrate/combine confirmation dialogs posted their input as
title_format while the handlers read aggregate_template_id and
aggregate_name.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test: relax aggregate form-wiring regex assertions
Match the gate and extra-array checks without pinning term order or sub-array key position.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(aggregate): surface error when aggregate template is missing
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(aggregate): catch title_format extra input in any key position
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test: add space before return-type colon
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(aggregate): validate request input on convert and combine paths
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: refresh security baselines
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(aggregate): verify convert-template guard writes nothing on bad template
tests/Unit/AggregateFormFieldNamesTest.php only regex-matches the guard
clause in source; this runs api_aggregate_convert_template() against a
real sqlite-backed connection and confirms a missing/unmatched
aggregate_template_id leaves aggregate_graphs and aggregate_graphs_items
untouched.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci(hardening): allow test-fixture superglobal writes in aggregate guard test
tests/integration/AggregateConvertTemplateGuardIntegrationTest.php sets
$_REQUEST directly to simulate request state before calling the real
api_aggregate_convert_template(), which reads aggregate_template_id via
gnrv(). Same pattern already used in tests/HandOff/CactiDispatchHandOffTest.php
and tests/HandOff/CactiSettingsHandOffTest.php.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(aggregate): restore db globals after convert-template guard test
issue7338_wire_default_connection() overwrote $database_hostname/
$database_port/$database_default and added a fake PDO to
$database_sessions without ever resetting them, so any later test in the
same Pest process that hit a db_* helper resolved against the stale
sqlite handle instead of its own fixture -- which crashed the whole
suite before the HandOff tests ran.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* Change function to retrieve aggregate template ID
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
* security(aggregate): parameterise form_actions and purge_old_graphs IN() lists
The template-migration queries in form_actions() and the purge_old_graphs()
DELETE queries built IN() lists with implode(','); they now use db_*_prepared()
with placeholder arrays. aggregate_items() rfilter and aggregate_graph_id
parameterisation already landed on develop via the #7254/#7260 filter refactor,
so this keeps only the remaining unique fixes plus the gfrv()/rawurlencode() URL
hardening.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test: use whitespace-tolerant regex for grv/gfrv assertion
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(security): verify purge_old_graphs' parameterized deletes against real SQL
tests/Unit/InClausePlaceholderTest.php only checks the placeholder-count
arithmetic; it never runs a prepared statement, so it can't catch a
mismatched id list feeding the wrong query. This extracts the real
purge_old_graphs() from aggregate_graphs.php and runs it against a
sqlite-backed connection across five joined tables.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: refresh SQL interpolation ratchet baseline for aggregate_graphs parameterization
Rebasing onto develop pulled in prior parameterization work (#7262,
with; aggregate_graphs.php now drops out entirely after this branch's
own db_* parameterization.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(aggregate): restore db globals after purge_old_graphs integration test
issue7261_wire_default_connection() overwrote $database_hostname/
$database_port/$database_default and added a fake PDO to
$database_sessions without ever resetting them, so any later test in the
same Pest process that hit a db_* helper resolved against the stale
sqlite handle instead of its own fixture -- which crashed the whole
suite before the HandOff tests ran.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* docs: add changelog entry
* docs: fix changelog entry format
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* hardening(aggregate): centralize items filter state
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* hardening(aggregate): bind item regex filter
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(style): normalize aggregate filter assignment
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(aggregate): avoid full bootstrap in filter test
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix: HTML-escape aggregate items rfilter attribute
Prevents attribute breakout when the search box echoes request text.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* refactor(aggregate): render items filter via CactiTableFilter, drop bespoke value object
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* hardening(aggregate): use db_in_clause for item ids, restrict matching filter
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* hardening(aggregate): match regex branch on validate_is_regex === true
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* Apply suggestions from code review
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* hardening(forms): render input attributes safely
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* hardening(import): keep package selections server side
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(forms): address attribute review feedback
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* style package import state token
* style(test): use line comments so pre-commit php-cs-fixer passes
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix(package): bind import parameters to stored state token
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* ci: refresh sink and hotspot baselines for line shifts
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
* fix: clear eleven PHPStan Level 6 errors blocking develop CI
Four form_save() branches (aggregate_graphs, color_templates, graph_templates,
graphs) consumed empty($X_template_item_id) in the error-redirect URL while
the variable was only assigned inside a foreach + !is_error_message branch.
Initialise to 0 at the top of the save_component_item branch so the redirect
fallback to gnrv()/gfrv() is reachable on the static-analysis path too.
lib/html.php right-tab block had isset($tab['image']) guards that PHPStan
flagged as dead. The $tabs_right constructor sets 'image' on every entry,
so drop the isset() and keep only the != '' check.
Closes#7137
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(mutation): pin Level 6 fixes against init removal and isset reintroduction
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test(smoke): cheap structural smoke for #7137 PHPStan baseline fixes
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* test: drop Pest-incompatible 2nd-arg messages from expect() chains
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
* cleanup: remove unreachable defensive error logs in aggregate graph item validation
* fix: replace strtolower/strtoupper with locale-independent wrappers
PHP 8.5 deprecates locale-sensitive strtolower() and strtoupper().
Add cacti_strtolower() and cacti_strtoupper() wrappers that use
mb_strtolower/mb_strtoupper with explicit UTF-8 encoding, then
replace all 185 call sites across 65 files.
Existing mb_strtolower() calls (email normalization) are left as-is
since they already specify encoding explicitly.
Includes 18 Pest tests covering ASCII, UTF-8, protocol names, config
values, hex strings, NaN detection, and file extension patterns.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* fix: correct docblock references and month_shift() strpos check
Fix docblocks to reference strtolower()/strtoupper() (the deprecated
PHP builtins) instead of the wrapper names. Fix month_shift() to use
strpos() !== false instead of > 0 so 'month' at position 0 is matched.
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
* chore: drop unrelated lib/api_aggregate changes
Keep PR scope focused on the issue for this branch.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
---------
Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: TheWitness <thewitness@cacti.net>
* Fix#6539 - Allow Standard Cacti Log Files to be Rotated on Demand from the Cacti UI
* QA: php-cs-fixer updates and documentation for lib/database.php
* QA: Update .gitignore for composer files
* QA: Update .gitignore for composer files
* QA: Back off .gitignore change its duplicated
* QA: Fix typing of db_has_permissions
* QA: Fixing typing issue in db_format_index_create
* Update lib/clog_webapi.php
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* QA: Fix additional code issues
* QA: Applying more defaults to add device
* QA: Fix at the database layer
* QA: Fixes based upon automated testing
* QA: Fix at the database layer
* QA: After new SQL checking
* QA: Skip MacTrack oui database download warnings
* QA: Fixing type issue
* QA: Recommendation from Copilot
* QA: Recommendation from Copilot
* QA: Recommendation from Copilot
* QA: Recommendation from Copilot
* QA: Some minor changes to avoid errors in testing
* QA: Unused variable
* QA: Recommendation from Copilot
* QA: Recommendation from Copilot
* QA: Recommendation from Copilot
* QA: Minor introduced code defect
* QA: Adding some unifying space around concatination
* QA: Consistent comments and new function alias'
* QA: Multi-line comment corrections
* QA: Fix SQL Style
* QA: Missed one function alias
* QA: PHPStan Level 2 and PHPDoc fixes
* QA: PHPStan Level 2 and PHPDoc Fixes
* QA: PHPStan Level 6 Fixes
* QA: Fix lib/xml.php to PHPStan Level 6
* QA: Wrong grep -v
* PHPStan Level 6 for lib/vdef.php
* PHPStan Level 8 for lib/time.php
* QA: Raise PHPStan to Level 6 for lib/database.php
* QA: Remove @deprecated tag from grv()
* QA: Switch to htmle() alias over html_escape()
* QA: More addressing PHPStan issues at Level 6
* QA: Change recommended by Copilot for Readability
* QA: More PHPStan fixes
* QA: More PHPStan fixes
* QA: More PHPStan fixes for lib/utility.php
* QA: More PHPStan fixes at Level 6
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: More PHPStan fixes at Level 6
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: More PHPStan fixes at Level 6
* QA: More PHPStan fixes at Level 6
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: More PHPStan fixes at Level 6
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: More PHPStan fixes at Level 6
* QA: Raise PHPStan to Level 6 More Functions
* QA: Raise PHPStan to Level 6 More Functions
* QA: More PHPStan fixes at Level 6
* QA: More PHPStan fixes at Level 6
* QA: More PHPStan fixes at Level 6
* QA: Raise PHPStan to Level 6 More Functions
* QA: More PHPStan fixes at Level 6
* QA: Some phpseclib3 fixups to update to latest
* QA: More fixups for graphing for magic strings
* QA: More PHPStan fixes at Level 6
* QA: Fixing order string type on get_allowed_graphs()
* QA: Fixing improper use of print
* QA: Optimization of color_templates
* QA: Copilot recommendation
* QA: Copilot recommendation
* QA: Copilot recommendation
* QA: Copilot recommendation
* QA: Copilot recommendation
* QA: Copilot recommendation
* QA: Copilot recommendation
* QA: Copilot recommendation
* QA: Raise PHPStan to Level 6 More Functions
* QA: Issues insalling Cacti
* QA: Issues insalling Cacti
* QA: Issues insalling Cacti
* QA: Issues insalling Cacti
* QA: Issues insalling Cacti
* QA: Issues testing Cacti
* QA: Copilot recommendation
* QA: More PHPStan fixes at Level 6
* QA: More PHPStan fixes at Level 6
* QA: More PHPStan fixes at Level 6
* QA: More PHPStan fixes at Level 6
* QA: More PHPStan fixes at Level 6
* QA: Installer failing
* Undo ownership changes to remove tar errors
* QA: Updates after php-cs-fixer
* QA: Adding code checks to syntax checking
* QA Change syntax flow language
* QA: Reduce the number of cures
* QA: Use sequentional option
* Change runner to self-hosted for check job
* Fix typo in OS version in workflow file
* Add Git installation step in workflow
Added step to install Git if not already installed.
* Add '-y' flag to apt-get install and update commands
Updated apt-get commands to include '-y' for automatic confirmation.
* Change workflow OS version to 'ubuntu-latest'
Updated the workflow to use 'ubuntu-latest' instead of 'ubuntu:latest' and modified the 'runs-on' configuration.
* Remove sequential option from phpcsfixer script
* Remove PHPCS fixer step from workflow
Removed PHP coding standards check from workflow.
* Move code checks to before plugins
Moving these core checks to before the plugins are installed as we really want to check only the base Cacti here.
* Add Composer validation and caching to start of workflow
* QA: Addressing PHPStan additional
* QA: Restore composer lock file
* QA: Addressing PHPStan additional
* QA: Addressing PHPStan additional
* QA: Complete LDAP Project
* QA: php-cs-fixer doing it's thing
* QA: Syntax is already happening in PHPStan
* QA: The md5 function no longer exists
* QA: Update after ldap changes
* QA: Undo that last password hack
* QA: Attempting to switch to MariaDB 11.8
* QA: Attempting to switch to MariaDB 11.8
* QA: Resolving some issues with PHP8.4
* QA: Resolving some issues with PHP8.4
* QA: Add PHP8.5 to the matrix
* QA: Removing PHP8.5 due to dependency issues
* QA: Add the DB version to the testing output
* QA: Switch back to MySQL for the moment
* QA: More fidelity in reporting
* QA: The pipe must be mixed
* QA: Moving audit_schema.php changes from 1.2.x
* QA: Moving audit_schema.php changes from 1.2.x
* QA: Restore mysql monitoring
* QA: php-cs-fixer issues
* QA: Attempt to roll back to MariaDB 10.6
* QA: Attempt to fix check_all_pages.sh
* QA: Make installer functional again
* QA: Fix installer php-cs-fixer issues
* QA: Type to a string
* QA: Get the database version correctly
* QA: Fix issue with reports in check_all_pages.sh
* QA: Check the server version in the right place
* Feature: Support SHA256 as a new hash for passwords
* QA: Function definition and return typing audit
* QA: Refinement of form types
* QA: Refinement of form types
* QA: Consistency of comments
* QA: Issues with php-cs-fixer and more comments
* QA: More typing issues
* QA: php-cs-fixer on merge conflict resolution
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This removes most entries to $config in the base code. A few new constants were defined to achieve this:
* CACTI_CONNECTION - The status of the current connection
* CACTI_CSRF_SECRET - The path to the csrf secret file
* CACTI_PHP_SNMP - True if php-snmp is installed
* CACTI_WHITELIST - The path to the Cacti Whitelist file if defined
I also moved several $config['poller_id'] to the existing POLLER_ID and move a number of $config['is_web'] to the existing CACTI_WEB constants.
There remain a few artifacts in the code. They will be handled in a separate commit.
* Introduce a new wrapper function for showing the show/hide column indicator
* Migrate all Core packages to use that new wrapper function
* Migrate pages to have JavaScript show immediately below the form object.
* Correct some indentation issues