-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Fix string interpolation and platform where 'ip' command (from iproute2) is unavailable. #4734
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 8 commits
8a84284
9681d00
f34f3ad
d627ca2
88d7c11
21cb8bf
7e28665
1527ae6
09a92b1
9628328
154ea38
a155155
ce8f113
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -70,6 +70,10 @@ ZM_PATH_IP="@ZM_PATH_IP@" | |||||
| # ZoneMinder will find the ifconfig binary automatically on most systems | ||||||
| ZM_PATH_IFCONFIG="@ZM_PATH_IFCONFIG@" | ||||||
|
|
||||||
| # Full path to optional route binary or just route to use PATH | ||||||
|
||||||
| # Full path to optional route binary or just route to use PATH | |
| # Full path to optional route binary |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2240,59 +2240,86 @@ function i18n() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function get_networks() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $interfaces = array(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $interfaces = array(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (defined('ZM_PATH_IP') and ZM_PATH_IP and file_exists(ZM_PATH_IP)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exec(ZM_PATH_IP.' link', $output, $status); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( $status ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $html_output = implode('<br/>', $output); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ZM\Error("Unable to list network interfaces, status is '$status'. Output was:<br/><br/>$html_output"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| foreach ( $output as $line ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( preg_match('/^\d+: ([[:alnum:]]+):/', $line, $matches ) ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( $matches[1] != 'lo' ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $interfaces[$matches[1]] = $matches[1]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ZM\Debug("No match for $line"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (defined('ZM_PATH_IP') and ZM_PATH_IP and file_exists(ZM_PATH_IP)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exec(ZM_PATH_IP.' link', $output, $status); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( $status ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $html_output = implode('<br/>', $output); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ZM\Error("Unable to list network interfaces, status is '$status'. Output was:<br/><br/>$html_output"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| foreach ( $output as $line ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( preg_match('/^\d+: ([[:alnum:]]+):/', $line, $matches ) ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( $matches[1] != 'lo' ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $interfaces[$matches[1]] = $matches[1]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+2252
to
+2254
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ZM\Debug("Skipping loopback interface $line"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $routes = array(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exec(ZM_PATH_IP.' route', $output, $status); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ($status) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $html_output = implode('<br/>', $output); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ZM\Error("Unable to list network interfaces, status is '$status'. Output was:<br/><br/>$html_output"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| foreach ($output as $line) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ( preg_match('/^default via [.[:digit:]]+ dev ([[:alnum:]]+)/', $line, $matches) ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $interfaces['default'] = $matches[1]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if ( preg_match('/^([.[:digit:]]+\/[[:digit:]]+) dev ([[:alnum:]]+)/', $line, $matches) ) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $interfaces[$matches[2]] .= ' ' . $matches[1]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ZM\Debug("Matched $line: $matches[2] .= $matches[1]"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $routes = array(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| $routes = array(); |
Copilot
AI
Apr 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$interfaces[$matches[2]] .= ... assumes the interface key already exists. If the link parsing missed an interface (or route output references an interface not listed), this will raise a notice and produce a malformed label. Initialize the entry when it’s not set before appending.
| } else if ( preg_match('/^([.[:digit:]]+\/[[:digit:]]+) dev ([[:alnum:]]+)/', $line, $matches) ) { | |
| } else if ( preg_match('/^([.[:digit:]]+\/[[:digit:]]+) dev ([[:alnum:]]+)/', $line, $matches) ) { | |
| if ( !isset($interfaces[$matches[2]]) ) { | |
| $interfaces[$matches[2]] = $matches[2]; | |
| } |
Copilot
AI
Apr 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Route parsing uses the same [[:alnum:]]+ constraint for interface names, which can miss valid interface names containing -, ., or @. This can prevent default-route detection and subnet annotations from working on common setups (bridges/VLANs/veth). Widen the interface-name match here as well.
Copilot
AI
Apr 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ZM\Debug(print_r($matches, true)); runs for every ifconfig line, including non-matching lines, which can generate very noisy logs and extra overhead when debug is enabled. Consider logging only when a line matches (or when a match is rejected), and avoid dumping the full matches array for every line.
| ZM\Debug(print_r($matches, true)); | |
| if (($retval == 1) && (strlen($matches[3]) > 0) && | |
| (strpos($matches[3], "LOOPBACK") === false) && (strpos($matches[3], "RUNNING") !== false)) | |
| { | |
| $interfaces[$matches[1]] = $matches[1]; | |
| if ($retval == 1) { | |
| if ((strlen($matches[3]) > 0) && | |
| (strpos($matches[3], "LOOPBACK") === false) && (strpos($matches[3], "RUNNING") !== false)) | |
| { | |
| ZM\Debug("Accepted interface '".$matches[1]."' with flags '".$matches[3]."'"); | |
| $interfaces[$matches[1]] = $matches[1]; | |
| } else { | |
| ZM\Debug("Rejected interface '".$matches[1]."' with flags '".$matches[3]."'"); | |
| } |
Copilot
AI
Apr 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On failure of the route command, the logged output is built from $output (ifconfig output) rather than $defaultIface (route output). This makes the error misleading and may hide the actual failure reason. Use the variable that captured the route output for the error report.
| $html_output = implode("\n", $output); | |
| $html_output = implode("\n", $defaultIface); |
Copilot
AI
Apr 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the ifconfig fallback, the code executes ZM_PATH_IFCONFIG and then immediately executes plain ifconfig, overwriting $output. This ignores the explicitly configured ZM_PATH_IFCONFIG (and will fail if ifconfig isn’t in the web server PATH). Use only ZM_PATH_IFCONFIG for the actual interface listing, and remove the redundant second exec/branching.
| exec('ifconfig', $output, $status); | |
| if ($status) { | |
| $html_output = implode("\n", $output); | |
| ZM\Error("Unable to list network interfaces, status is '$status'. Output was:$html_output"); | |
| } else { | |
| array_walk($output, function($value, $key) use (&$interfaces) { | |
| $retval = preg_match("/^([A-Za-z0-9]*):\s+flags=([0-9]*)<([A-Z,]*)>.*/ims", $value, $matches); | |
| ZM\Debug(print_r($matches, true)); | |
| if (($retval == 1) && (strlen($matches[3]) > 0) && | |
| (strpos($matches[3], "LOOPBACK") === false) && (strpos($matches[3], "RUNNING") !== false)) | |
| { | |
| $interfaces[$matches[1]] = $matches[1]; | |
| } | |
| }); | |
| if (defined('ZM_PATH_ROUTE') and ZM_PATH_ROUTE and file_exists(ZM_PATH_ROUTE)) { | |
| // Get default route iface | |
| if (strcmp($osname, 'freebsd') == 0) { | |
| exec(ZM_PATH_ROUTE . " get default | grep interface | awk '{print $2}'", $defaultIface, $status); | |
| } else { | |
| exec(ZM_PATH_ROUTE . " -n | grep '^0.0.0.0' | head -n 1 | awk '{print $8}'", $defaultIface, $status); | |
| } | |
| if ($status) { | |
| $html_output = implode("\n", $output); | |
| ZM\Error("Unable to get default ip route, status is '$status'. Output was:$html_output"); | |
| } else { | |
| if (isset($defaultIface) && isset($defaultIface[0])) { | |
| $interfaces['default'] = $defaultIface[0]; | |
| } | |
| } | |
| array_walk($output, function($value, $key) use (&$interfaces) { | |
| $retval = preg_match("/^([A-Za-z0-9]*):\s+flags=([0-9]*)<([A-Z,]*)>.*/ims", $value, $matches); | |
| ZM\Debug(print_r($matches, true)); | |
| if (($retval == 1) && (strlen($matches[3]) > 0) && | |
| (strpos($matches[3], "LOOPBACK") === false) && (strpos($matches[3], "RUNNING") !== false)) | |
| { | |
| $interfaces[$matches[1]] = $matches[1]; | |
| } | |
| }); | |
| if (defined('ZM_PATH_ROUTE') and ZM_PATH_ROUTE and file_exists(ZM_PATH_ROUTE)) { | |
| // Get default route iface | |
| if (strcmp($osname, 'freebsd') == 0) { | |
| exec(ZM_PATH_ROUTE . " get default | grep interface | awk '{print $2}'", $defaultIface, $status); | |
| } else { | |
| exec(ZM_PATH_ROUTE . " -n | grep '^0.0.0.0' | head -n 1 | awk '{print $8}'", $defaultIface, $status); | |
| } | |
| if ($status) { | |
| $html_output = implode("\n", $output); | |
| ZM\Error("Unable to get default ip route, status is '$status'. Output was:$html_output"); | |
| } else { | |
| if (isset($defaultIface) && isset($defaultIface[0])) { | |
| $interfaces['default'] = $defaultIface[0]; | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says “an route compatible executable”; grammatically this should be “a route compatible executable”.