diff --git a/includes/configure_client.php b/includes/configure_client.php index f9ad1f2c..619b0288 100755 --- a/includes/configure_client.php +++ b/includes/configure_client.php @@ -19,12 +19,16 @@ function DisplayWPAConfig() $iface = escapeshellarg($_SESSION['wifi_client_interface']); if (isset($_POST['connect'])) { + error_log("\nconfigure_client:DisplayWPAConfig() -> ******* Caught connect ****** \n"); $netid = intval($_POST['connect']); + error_log("\nconfigure_client:DisplayWPAConfig() -> connecting to $netid\n"); $force_remove = true; - $result = $wifi->reinitializeWPA($force_remove); - $cmd = "sudo wpa_cli -i $iface select_network $netid"; - $return = shell_exec($cmd); - sleep(2); + $return = $wifi->reinitializeWPA($force_remove); + //$cmd = "sudo wpa_cli -i $iface select_network $netid"; + //$return = shell_exec($cmd); + sleep(3); + //$cmd = "sudo wpa_cli -i $iface reassociate"; + //$return = shell_exec($cmd); if (trim($return) == "FAIL") { $status->addMessage('WPA command line client returned failure. Check your adapter.', 'danger'); } else { @@ -40,15 +44,28 @@ function DisplayWPAConfig() fwrite($wpa_file, 'ctrl_interface=DIR=' . RASPI_WPA_CTRL_INTERFACE . ' GROUP=netdev' . PHP_EOL); fwrite($wpa_file, 'update_config=1' . PHP_EOL); + error_log("\nconfigure_client:DisplayWPAConfig() -> _POST\n" . var_export($_POST, true)); + foreach (array_keys($_POST) as $post) { if (preg_match('/delete(\d+)/', $post, $post_match)) { - $network = $tmp_networks[$_POST['ssid' . $post_match[1]]]; + $network = $tmp_networks[$_POST['ssid-' . $post_match[1]]]; $netid = $network['index']; + error_log("\nconfigure_client:DisplayWPAConfig() -> netid: $netid\n"); + exec('sudo wpa_cli -i ' . $iface . ' disconnect ' . $netid); exec('sudo wpa_cli -i ' . $iface . ' remove_network ' . $netid); unset($tmp_networks[$_POST['ssid' . $post_match[1]]]); - + } elseif (preg_match('/disconnect(\d+)/', $post, $post_match)) { + error_log("\nconfigure_client:DisplayWPAConfig() -> ******* Caught disconnect ****** \n"); + $network = $tmp_networks[$_POST['ssid' . $post_match[1]]]; + $netid = $network['index']; + error_log("\nconfigure_client:DisplayWPAConfig() -> netid: $netid\n"); + exec('sudo wpa_cli -i ' . $iface . ' disconnect ' . $netid); + exec('sudo wpa_cli -i ' . $iface . ' remove_network ' . $netid); + sleep(2); + //$force_remove = true; + //$result = $wifi->reinitializeWPA($force_remove); } elseif (preg_match('/update(\d+)/', $post, $post_match)) { // NB, multiple protocols are separated with a forward slash ('/') $tmp_networks[$_POST['ssid' . $post_match[1]]] = array( diff --git a/installers/raspap.sudoers b/installers/raspap.sudoers index d5813a5e..7a5ef202 100644 --- a/installers/raspap.sudoers +++ b/installers/raspap.sudoers @@ -9,11 +9,12 @@ www-data ALL=(ALL) NOPASSWD:/sbin/wpa_supplicant -i [a-zA-Z0-9]* -c /etc/wpa_sup www-data ALL=(ALL) NOPASSWD:/bin/rm /var/run/wpa_supplicant/[a-zA-Z0-9]* www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* scan_results www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* scan +www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* status www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* reconfigure www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* add_network www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* list_networks -www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i enable_network [0-9] -www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i disconnect [0-9] +www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* enable_network [0-9] +www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* disconnect [0-9] www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* select_network [0-9] www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* set_network [0-9] * www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i [a-zA-Z0-9]* remove_network [0-9] diff --git a/src/RaspAP/Networking/Hotspot/WiFiManager.php b/src/RaspAP/Networking/Hotspot/WiFiManager.php index 03f30782..8a33f0df 100644 --- a/src/RaspAP/Networking/Hotspot/WiFiManager.php +++ b/src/RaspAP/Networking/Hotspot/WiFiManager.php @@ -22,11 +22,9 @@ class WiFiManager { // find currently configured networks exec(' sudo cat ' . RASPI_WPA_SUPPLICANT_CONFIG, $known_return); - $index = 0; foreach ($known_return as $line) { if (preg_match('/network\s*=/', $line)) { $network = array('visible' => false, 'configured' => true, 'connected' => false, 'index' => null); - ++$index; } elseif (isset($network) && $network !== null) { if (preg_match('/^\s*}\s*$/', $line)) { $networks[$ssid] = $network; @@ -38,8 +36,7 @@ class WiFiManager $ssid = trim($lineArr[1], '"'); $ssid = str_replace('P"','',$ssid); $network['ssid'] = $ssid; - $index = $this->getNetworkIdBySSID($ssid); - $network['index'] = $index; + $network['index'] = $this->getNetworkIdBySSID($ssid); break; case 'psk': $network['passkey'] = trim($lineArr[1]); @@ -93,13 +90,16 @@ class WiFiManager } ); + // determine the next index that follows the indexes of the known networks $index = 0; if (!empty($networks)) { - $lastnet = end($networks); - if (isset($lastnet['index'])) { - $index = $lastnet['index'] + 1; + foreach ($networks as $network) { + if (isset($network['index']) && is_numeric($network['index']) && ($network['index'] > $index)) { + $index = (int)$network['index']; + } } } + $index++; $current = []; $commitCurrent = function () use (&$current, &$networks, &$index) { @@ -136,7 +136,7 @@ class WiFiManager 'RSSI' => $rssi, 'index' => $index ]; - ++$index; + $index++; // increment for next new network } }; @@ -177,19 +177,50 @@ class WiFiManager } $commitCurrent(); } - /** - * + * Check if networks are connected via wpa_cli status + * NB: iwconfig shows the last associated SSID even when connection is inactive */ public function connectedWifiStations(&$networks) { - exec('iwconfig ' .$_SESSION['wifi_client_interface'], $iwconfig_return); - foreach ($iwconfig_return as $line) { - if (preg_match('/ESSID:\"([^"]+)\"/i', $line, $iwconfig_ssid)) { - $ssid=hexSequence2lower($iwconfig_ssid[1]); - $networks[$ssid]['connected'] = true; - $networks[$ssid]["portal-url"]=$check["URL"]; + $wpa_state = null; + $connected_ssid = null; + $iface = $_SESSION['wifi_client_interface']; + + $cmd = "sudo wpa_cli -i $iface status"; + $status_output = shell_exec($cmd); + + if ($status_output === null || empty($status_output)) { + error_log("WiFiManager::connectedWifiStations: wpa_cli command failed or returned no output"); + return; + } + $lines = explode("\n", trim($status_output)); + + foreach ($lines as $line) { + $line = trim($line); + if (preg_match('/^wpa_state=(.+)$/', $line, $matches)) { + $wpa_state = trim($matches[1]); } + if (preg_match('/^ssid=(.+)$/', $line, $matches)) { + $connected_ssid = trim($matches[1]); + } + } + + if ($wpa_state === 'COMPLETED' && !empty($connected_ssid)) { + $ssid = hexSequence2lower($connected_ssid); + + // check if this SSID exists in networks array + if (array_key_exists($ssid, $networks)) { + $networks[$ssid]['connected'] = true; + } else { + error_log("WiFiManager::connectedWifiStations: SSID '$ssid' not found. SSIDs: " . implode(', ', array_keys($networks))); + } + + // captive portal detection + // $check = detectCaptivePortal($iface); + // if (isset($check["URL"])) { + // $networks[$ssid]["portal-url"] = $check["URL"]; + // } } } @@ -258,6 +289,7 @@ class WiFiManager $result = shell_exec($cmd); $cmd = "sudo /sbin/wpa_supplicant -i $iface -c /etc/wpa_supplicant/wpa_supplicant.conf -B 2>&1"; $result = shell_exec($cmd); + sleep(2); } $cmd = "sudo wpa_cli -i $iface reconfigure"; $result = shell_exec($cmd); diff --git a/templates/wifi_stations/network.php b/templates/wifi_stations/network.php index 322bdf45..827155de 100644 --- a/templates/wifi_stations/network.php +++ b/templates/wifi_stations/network.php @@ -3,6 +3,18 @@ use RaspAP\Networking\Hotspot\WiFiManager; $wifi = new WiFiManager(); +// set defaults +$network = $network ?? []; +$network['ssid'] = $network['ssid'] ?? ''; +$network['ssidutf8'] = $network['ssidutf8'] ?? $network['ssid']; +$network['configured'] = $network['configured'] ?? false; +$network['connected'] = $network['connected'] ?? false; +$network['visible'] = $network['visible'] ?? false; +$network['channel'] = $network['channel'] ?? ''; +$network['protocol'] = $network['protocol'] ?? $wifi::SECURITY_OPEN; +$network['passphrase'] = $network['passphrase'] ?? ''; + +error_log("\ntemplates/wifi_stations/network.php -> network\n" . var_export($network, true)); ?>