Files
zoneminder/tests/php/test_config_file_booleans.php
Isaac ConnorandClaude Opus 5.5 7603a7458f fix: read yes/no, true/false and on/off in config files as booleans in PHP and Perl
A boolean option set in zm.conf or conf.d wins over the Config table, and a
person editing a file writes yes or off rather than 1 or 0. The C++ daemons
now read those words (ConfigFileValue, 4d7609d36), but PHP and Perl took the
value as written, and a non-empty string is true in both. So
ZM_STRICT_VIDEO_CONFIG=off in conf.d left the option on in the web UI and the
Perl scripts while zmc turned it off.

Read a file value for a boolean option the same way in all three: yes, true
and on are 1; no, false and off are 0; anything else stays as written. Only
booleans are read this way, so a string option such as a title keeps "Yes".

PHP defines the file values as constants before it reads the Config table,
since it needs the database settings to connect, and only the table says
which options are booleans. So a word now waits until the table has been
read, apart from ZM_DB_* settings, whose words database.php reads itself.
Perl reads the type with each row.

Tested on 1.38's zm138 database with a conf.d file setting
ZM_OPT_FAST_DELETE=yes (0 in the table), ZM_STRICT_VIDEO_CONFIG=off (1)
and ZM_WEB_TITLE=Yes. The installed PHP and Perl gave 'yes', 'off' and
'Yes'; these give '1', '0' and 'Yes'. tests/php/test_config_file_booleans.php
checks the rule.

refs #5289

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 22:37:07 -04:00

37 lines
1.5 KiB
PHP

<?php
// A boolean option set in zm.conf or conf.d may be written as a word. The box owner's
// file value wins over the Config table, and a word used to reach PHP as written, so
// ZM_X=off was the string 'off': truthy, so the option was on. configFileValue() reads
// it as the Config table would hold it, the same way as ConfigFileValue() in
// src/zm_config.cpp and ZoneMinder::Config do.
//
// Run: sudo -u www-data php tests/php/test_config_file_booleans.php
// (from the repo root, on a tree with a readable zm.conf)
set_include_path(__DIR__.'/../../web/includes'.PATH_SEPARATOR.get_include_path());
require_once('config.php');
$failures = 0;
$passes = 0;
function check($name, $got, $expected) {
global $failures, $passes;
if ($got === $expected) {
$passes++;
echo "ok - $name\n";
} else {
$failures++;
echo "not ok - $name (got ".var_export($got, true)." expected ".var_export($expected, true).")\n";
}
}
foreach (array('1', 'yes', 'Yes', 'true', 'on', ' on ') as $v)
check("boolean '$v' is on", configFileValue($v, 'boolean'), '1');
foreach (array('0', 'no', 'false', 'off', 'OFF') as $v)
check("boolean '$v' is off", configFileValue($v, 'boolean'), '0');
check('a boolean that is not a word stays as written', configFileValue('2', 'boolean'), '2');
check('a string option keeps a word', configFileValue('Yes', 'string'), 'Yes');
check('an integer option keeps its value', configFileValue('5', 'integer'), '5');
echo "\n$passes passed, $failures failed\n";
exit($failures ? 1 : 0);