ZM_Object::set() called any method whose name matched a key in its data,
and changes() called it as a getter. That data is usually a request array
(filter[...], newMonitor[...], user[...]), so a request could invoke
save(), delete(), execute() and the like. filterdebug with fid=0 did
exactly that before its authorization check: filter[save][...] stored an
AutoExecute filter with a chosen command and filter[execute] ran
zmfilter.pl on it, giving command execution to any logged-in user. The
filter and events views pass filter[...] to set() the same way.
set() and changes() now dispatch a key to a method only when the key is
a field in $defaults or is listed in the class's new static $setters, the
accessors outside $defaults that take a value (Filter's query accessors,
Monitor::Model/Manufacturer/Groups, User::Role, and so on). Other method
names are refused with a warning.
filterdebug also requires Events view before it builds a filter from the
request.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>