Refactor setKnownStationsWPA(), add helper method addWpaNetwork()

This commit is contained in:
billz
2025-07-28 15:56:01 -07:00
parent 3c1d4325f2
commit dadc4e4fb4

View File

@@ -304,55 +304,140 @@ class WiFiManager
return $elem;
}
/*
/**
* Parses output of wpa_cli list_networks, compares with known networks
* from wpa_supplicant, and adds with wpa_cli if not found
*
* @param array $networks
* @throws Exception on wpa_cli command failure
*/
public function setKnownStationsWPA($networks)
{
$iface = escapeshellarg($_SESSION['wifi_client_interface']);
$output = shell_exec("sudo wpa_cli -i $iface list_networks");
$lines = explode("\n", $output);
array_shift($lines);
$wpaCliNetworks = [];
$output = shell_exec("sudo wpa_cli -i $iface list_networks 2>&1");
foreach ($lines as $line) {
$data = explode("\t", trim($line));
if (!empty($data) && count($data) >= 2) {
$id = $data[0];
$ssid = $data[1];
$item = [
'id' => $id,
'ssid' => $ssid
];
$wpaCliNetworks[] = $item;
if ($output === null) {
throw new \Exception("Failed to execute wpa_cli command - command returned null");
}
// check for common wpa_cli errors and try to fix them
if (strpos($output, 'Failed to connect') !== false || strpos($output, 'No such file or directory') !== false) {
error_log("wpa_supplicant not available for interface, attempting to start it");
// try starting wpa_supplicant for this interface
$unescapedIface = trim($iface, "'\"");
$startCmd = "sudo /sbin/wpa_supplicant -i $unescapedIface -c /etc/wpa_supplicant/wpa_supplicant.conf -B 2>&1";
$startResult = shell_exec($startCmd);
sleep(2);
// retry
$output = shell_exec("sudo wpa_cli -i $iface list_networks 2>&1");
// tf it still fails, throw an exception
if ($output === null || strpos($output, 'Failed to connect') !== false) {
throw new \Exception("Failed to start wpa_supplicant for interface: " . trim($startResult ?? 'unknown error'));
}
}
foreach ($networks as $network) {
$ssid = $network['ssid'];
if (!$this->networkExists($ssid, $wpaCliNetworks)) {
$ssid = escapeshellarg('"'.$network['ssid'].'"');
$psk = escapeshellarg('"'.$network['passphrase'].'"');
$protocol = $network['protocol'];
$netid = trim(shell_exec("sudo wpa_cli -i $iface add_network"));
if (isset($netid) && !isset($known[$netid])) {
$commands = [
"sudo wpa_cli -i $iface set_network $netid ssid $ssid",
"sudo wpa_cli -i $iface set_network $netid psk $psk",
"sudo wpa_cli -i $iface enable_network $netid"
];
if ($protocol === 'Open') {
$commands[1] = "sudo wpa_cli -i $iface set_network $netid key_mgmt NONE";
}
foreach ($commands as $cmd) {
exec($cmd);
usleep(1000);
// split output into lines
$lines = explode("\n", trim($output));
// check for header line
if (empty($lines) || count($lines) < 1) {
error_log("wpa_cli list_networks returned no output");
$wpaCliNetworks = [];
} else {
// remove header line if it exists
$headerLine = trim($lines[0]);
if (strpos($headerLine, 'network id') !== false || strpos($headerLine, 'id') !== false) {
array_shift($lines);
}
$wpaCliNetworks = [];
foreach ($lines as $line) {
$trimmedLine = trim($line);
// skip empty lines
if (empty($trimmedLine)) {
continue;
}
$data = explode("\t", $trimmedLine);
if (count($data) >= 2) {
$id = trim($data[0]);
$ssid = trim($data[1]);
// add if we have valid data
if ($id !== '' && $ssid !== '') {
$wpaCliNetworks[] = [
'id' => $id,
'ssid' => $ssid
];
}
}
}
}
// process networks to add
foreach ($networks as $network) {
if (!isset($network['ssid']) || empty($network['ssid'])) {
error_log("Skipping network with missing or empty SSID");
continue;
}
$ssid = $network['ssid'];
if (!$this->networkExists($ssid, $wpaCliNetworks)) {
$this->addWpaNetwork($network, $iface);
}
}
}
/**
* Helper method to add a single network to wpa_supplicant
*
* @param array $network Network configuration
* @param string $iface Escaped shell argument for interface
*/
private function addWpaNetwork($network, $iface)
{
$ssid = escapeshellarg('"' . $network['ssid'] . '"');
$psk = escapeshellarg('"' . $network['passphrase'] . '"');
$protocol = $network['protocol'] ?? 'WPA';
// add network and get its ID
$netid = trim(shell_exec("sudo wpa_cli -i $iface add_network 2>&1"));
// validate network ID
if (!$netid || !is_numeric($netid)) {
error_log("Failed to add network '{$network['ssid']}': Invalid network ID returned: '$netid'");
return;
}
// prepare command based on protocol
$commands = [
"sudo wpa_cli -i $iface set_network $netid ssid $ssid",
];
if (strtolower($protocol) === 'open') {
$commands[] = "sudo wpa_cli -i $iface set_network $netid key_mgmt NONE";
} else {
$commands[] = "sudo wpa_cli -i $iface set_network $netid psk $psk";
}
$commands[] = "sudo wpa_cli -i $iface enable_network $netid";
// execute commands, checking errors
foreach ($commands as $cmd) {
$result = shell_exec("$cmd 2>&1");
if ($result === null || strpos($result, 'FAIL') !== false) {
error_log("Command failed: $cmd - Result: " . ($result ?? 'null'));
// remove the failed network
shell_exec("sudo wpa_cli -i $iface remove_network $netid 2>&1");
return;
}
usleep(1000);
}
error_log("Successfully added network: {$network['ssid']}");
}
/*