1use std::collections::HashMap;
2use std::process::Command;
3use std::sync::mpsc;
4use tauri::{plugin::PluginApi, AppHandle, Runtime};
5use zbus::names::InterfaceName;
6use zbus::zvariant::Value;
7
8use crate::error::Result;
9use crate::models::{NetworkInfo, WiFiConnectionConfig, WiFiSecurityType, VSKNetworkManager};
10use crate::nm_helpers::NetworkManagerHelpers;
11
12impl<R: Runtime> VSKNetworkManager<'static, R> {
13 fn get_wifi_icon(strength: u8) -> String {
15 match strength {
16 0..=25 => "network-wireless-signal-weak-symbolic".to_string(),
17 26..=50 => "network-wireless-signal-ok-symbolic".to_string(),
18 51..=75 => "network-wireless-signal-good-symbolic".to_string(),
19 76..=100 => "network-wireless-signal-excellent-symbolic".to_string(),
20 _ => "network-wireless-signal-none-symbolic".to_string(),
21 }
22 }
23
24 fn get_wired_icon(is_connected: bool) -> String {
25 if is_connected {
26 "network-wired-symbolic".to_string()
27 } else {
28 "network-offline-symbolic".to_string()
29 }
30 }
31
32 pub async fn new(app: AppHandle<R>) -> Result<Self> {
34 let connection = zbus::blocking::Connection::system()?;
35 let proxy = zbus::blocking::fdo::PropertiesProxy::builder(&connection)
36 .destination("org.freedesktop.NetworkManager")?
37 .path("/org/freedesktop/NetworkManager")?
38 .build()?;
39
40 Ok(Self {
41 connection,
42 proxy,
43 app,
44 })
45 }
46
47 pub fn get_current_network_state(&self) -> Result<NetworkInfo> {
48 let active_connections_variant = self.proxy.get(
50 InterfaceName::from_static_str_unchecked("org.freedesktop.NetworkManager"),
51 "ActiveConnections",
52 )?;
53
54 match active_connections_variant.downcast_ref() {
56 Some(Value::Array(arr)) if !arr.is_empty() => {
57 match arr[0] {
59 zbus::zvariant::Value::ObjectPath(ref path) => {
60 let properties_proxy =
63 zbus::blocking::fdo::PropertiesProxy::builder(&self.connection)
64 .destination("org.freedesktop.NetworkManager")?
65 .path(path)?
66 .build()?;
67
68 let devices_variant = properties_proxy.get(
69 InterfaceName::from_static_str_unchecked(
70 "org.freedesktop.NetworkManager.Connection.Active",
71 ),
72 "Devices",
73 )?;
74
75 let device_path = match devices_variant.downcast_ref() {
77 Some(Value::Array(device_arr)) if !device_arr.is_empty() => {
78 match device_arr[0] {
79 zbus::zvariant::Value::ObjectPath(ref dev_path) => {
80 dev_path.clone()
81 }
82 _ => return Ok(NetworkInfo::default()),
83 }
84 }
85 _ => return Ok(NetworkInfo::default()),
86 };
87
88 let device_properties_proxy =
91 zbus::blocking::fdo::PropertiesProxy::builder(&self.connection)
92 .destination("org.freedesktop.NetworkManager")?
93 .path(&device_path)?
94 .build()?;
95
96 let connection_type = device_properties_proxy.get(
97 InterfaceName::from_static_str_unchecked(
98 "org.freedesktop.NetworkManager.Device",
99 ),
100 "DeviceType",
101 )?;
102
103 let state_variant = properties_proxy.get(
104 InterfaceName::from_static_str_unchecked(
105 "org.freedesktop.NetworkManager.Connection.Active",
106 ),
107 "State",
108 )?;
109
110 let is_connected = match state_variant.downcast_ref() {
111 Some(zbus::zvariant::Value::U32(state)) => *state == 2, _ => false,
113 };
114
115 let connection_type_str = match connection_type.downcast_ref() {
117 Some(zbus::zvariant::Value::U32(device_type)) => match device_type {
118 1 => "Ethernet".to_string(),
119 2 => "WiFi".to_string(),
120 _ => "Unknown".to_string(),
121 },
122 _ => "Unknown".to_string(),
123 };
124
125 let mut network_info = NetworkInfo {
127 name: "Unknown".to_string(),
128 ssid: "Unknown".to_string(),
129 connection_type: connection_type_str.clone(),
130 icon: "network-offline-symbolic".to_string(),
131 ip_address: "0.0.0.0".to_string(),
132 mac_address: "00:00:00:00:00:00".to_string(),
133 signal_strength: 0,
134 security_type: WiFiSecurityType::None,
135 is_connected: is_connected && NetworkManagerHelpers::has_internet_connectivity(&self.proxy)?,
136 };
137
138 let hw_address_variant = device_properties_proxy.get(
139 InterfaceName::from_static_str_unchecked(
140 "org.freedesktop.NetworkManager.Device",
141 ),
142 "HwAddress",
143 )?;
144
145 network_info.mac_address = match hw_address_variant.downcast_ref() {
146 Some(zbus::zvariant::Value::Str(s)) => s.to_string(),
147 _ => "00:00:00:00:00:00".to_string(),
148 };
149
150 if connection_type_str == "WiFi" {
152 let wireless_properties_proxy =
155 zbus::blocking::fdo::PropertiesProxy::builder(&self.connection)
156 .destination("org.freedesktop.NetworkManager")?
157 .path(&device_path)?
158 .build()?;
159
160 let active_ap_path = wireless_properties_proxy.get(
161 InterfaceName::from_static_str_unchecked(
162 "org.freedesktop.NetworkManager.Device.Wireless",
163 ),
164 "ActiveAccessPoint",
165 )?;
166
167 if let Some(zbus::zvariant::Value::ObjectPath(ap_path)) =
168 active_ap_path.downcast_ref()
169 {
170 let _ap_proxy = zbus::blocking::Proxy::new(
171 &self.connection,
172 "org.freedesktop.NetworkManager",
173 ap_path,
174 "org.freedesktop.NetworkManager.AccessPoint",
175 )?;
176
177 let ap_properties_proxy =
180 zbus::blocking::fdo::PropertiesProxy::builder(&self.connection)
181 .destination("org.freedesktop.NetworkManager")?
182 .path(ap_path)?
183 .build()?;
184
185 let ssid_variant = ap_properties_proxy.get(
186 InterfaceName::from_static_str_unchecked(
187 "org.freedesktop.NetworkManager.AccessPoint",
188 ),
189 "Ssid",
190 )?;
191
192 network_info.ssid = match ssid_variant.downcast_ref() {
193 Some(zbus::zvariant::Value::Array(ssid_bytes)) => {
194 let bytes: Vec<u8> = ssid_bytes
196 .iter()
197 .filter_map(|v| {
198 if let zbus::zvariant::Value::U8(b) = v {
199 Some(*b)
200 } else {
201 None
202 }
203 })
204 .collect();
205
206 String::from_utf8_lossy(&bytes).to_string()
207 }
208 _ => "Unknown".to_string(),
209 };
210 network_info.name = network_info.ssid.clone();
211
212 let strength_variant = ap_properties_proxy.get(
214 InterfaceName::from_static_str_unchecked(
215 "org.freedesktop.NetworkManager.AccessPoint",
216 ),
217 "Strength",
218 )?;
219
220 network_info.signal_strength = match strength_variant.downcast_ref()
221 {
222 Some(zbus::zvariant::Value::U8(s)) => *s,
223 _ => 0,
224 };
225
226 network_info.icon =
228 Self::get_wifi_icon(network_info.signal_strength);
229
230 network_info.security_type = NetworkManagerHelpers::detect_security_type(&ap_properties_proxy)?;
232 }
233 } else {
234 network_info.icon = Self::get_wired_icon(network_info.is_connected);
236 }
237 let ip4_config_path = device_properties_proxy.get(
239 InterfaceName::from_static_str_unchecked(
240 "org.freedesktop.NetworkManager.Device",
241 ),
242 "Ip4Config",
243 )?;
244
245 if let Some(zbus::zvariant::Value::ObjectPath(config_path)) =
247 ip4_config_path.downcast_ref()
248 {
249 let ip_config_properties_proxy =
251 zbus::blocking::fdo::PropertiesProxy::builder(&self.connection)
252 .destination("org.freedesktop.NetworkManager")?
253 .path(config_path)?
254 .build()?;
255
256 let addresses_variant = ip_config_properties_proxy.get(
257 InterfaceName::from_static_str_unchecked(
258 "org.freedesktop.NetworkManager.IP4Config",
259 ),
260 "Addresses",
261 )?;
262
263 if let Some(Value::Array(addr_arr)) = addresses_variant.downcast_ref() {
264 if let Some(Value::Array(ip_tuple)) = addr_arr.first() {
265 if ip_tuple.len() >= 1 {
266 if let Value::U32(ip_int) = &ip_tuple[0] {
267 use std::net::Ipv4Addr;
268 network_info.ip_address =
269 Ipv4Addr::from((*ip_int).to_be()).to_string();
270 }
271 }
272 }
273 }
274 }
275
276 Ok(network_info)
277 }
278 _ => Ok(NetworkInfo::default()),
279 }
280 }
281 _ => Ok(NetworkInfo::default()),
282 }
283 }
284
285 pub fn list_wifi_networks(&self) -> Result<Vec<NetworkInfo>> {
287 let devices_variant = self.proxy.get(
289 InterfaceName::from_static_str_unchecked("org.freedesktop.NetworkManager"),
290 "Devices",
291 )?;
292
293 let mut networks = Vec::new();
294 let current_network = self.get_current_network_state()?;
295
296 if let Some(zbus::zvariant::Value::Array(devices)) = devices_variant.downcast_ref() {
297 let device_values = devices.get();
299 for device in device_values {
300 if let zbus::zvariant::Value::ObjectPath(ref device_path) = device {
301 let device_props =
303 zbus::blocking::fdo::PropertiesProxy::builder(&self.connection)
304 .destination("org.freedesktop.NetworkManager")?
305 .path(device_path)?
306 .build()?;
307
308 let device_type_variant = device_props.get(
310 InterfaceName::from_static_str_unchecked(
311 "org.freedesktop.NetworkManager.Device",
312 ),
313 "DeviceType",
314 )?;
315
316 if let Some(zbus::zvariant::Value::U32(device_type)) =
318 device_type_variant.downcast_ref()
319 {
320 if device_type == &2u32 {
321 let wireless_props =
323 zbus::blocking::fdo::PropertiesProxy::builder(&self.connection)
324 .destination("org.freedesktop.NetworkManager")?
325 .path(device_path)?
326 .build()?;
327
328 let access_points_variant = wireless_props.get(
329 InterfaceName::from_static_str_unchecked(
330 "org.freedesktop.NetworkManager.Device.Wireless",
331 ),
332 "AccessPoints",
333 )?;
334
335 if let Some(zbus::zvariant::Value::Array(aps)) =
336 access_points_variant.downcast_ref()
337 {
338 let ap_values = aps.get();
340 for ap in ap_values {
341 if let zbus::zvariant::Value::ObjectPath(ref ap_path) = ap {
342 let ap_props = zbus::blocking::fdo::PropertiesProxy::builder(
343 &self.connection,
344 )
345 .destination("org.freedesktop.NetworkManager")?
346 .path(ap_path)?
347 .build()?;
348
349 let ssid_variant = ap_props.get(
351 InterfaceName::from_static_str_unchecked(
352 "org.freedesktop.NetworkManager.AccessPoint",
353 ),
354 "Ssid",
355 )?;
356
357 let ssid = match ssid_variant.downcast_ref() {
358 Some(zbus::zvariant::Value::Array(ssid_bytes)) => {
359 let bytes: Vec<u8> = ssid_bytes
361 .iter()
362 .filter_map(|v| {
363 if let zbus::zvariant::Value::U8(b) = v {
364 Some(*b)
365 } else {
366 None
367 }
368 })
369 .collect();
370
371 String::from_utf8_lossy(&bytes).to_string()
372 }
373 _ => "Unknown".to_string(),
374 };
375
376 let strength_variant = ap_props.get(
378 InterfaceName::from_static_str_unchecked(
379 "org.freedesktop.NetworkManager.AccessPoint",
380 ),
381 "Strength",
382 )?;
383
384 let strength = match strength_variant.downcast_ref() {
385 Some(zbus::zvariant::Value::U8(s)) => *s,
386 _ => 0,
387 };
388
389 let security_type = NetworkManagerHelpers::detect_security_type(&ap_props)?;
391
392 let mac_address = match device_props.get(
393 InterfaceName::from_static_str_unchecked(
394 "org.freedesktop.NetworkManager.Device",
395 ),
396 "HwAddress",
397 )?.downcast_ref() {
398 Some(zbus::zvariant::Value::Str(s)) => s.to_string(),
399 _ => "00:00:00:00:00:00".to_string(),
400 };
401
402 let is_connected = current_network.ssid == ssid;
403
404 let network_info = NetworkInfo {
405 name: ssid.clone(),
406 ssid,
407 connection_type: "wifi".to_string(),
408 icon: Self::get_wifi_icon(strength),
409 ip_address: if is_connected {
410 current_network.ip_address.clone()
411 } else {
412 "0.0.0.0".to_string()
413 },
414 mac_address,
415 signal_strength: strength,
416 security_type,
417 is_connected,
418 };
419
420 if !networks.iter().any(|n: &NetworkInfo| n.ssid == network_info.ssid) {
421 networks.push(network_info);
422 }
423 }
424 }
425 }
426 }
427 }
428 }
429 }
430 }
431
432 networks.sort_by(|a, b| b.signal_strength.cmp(&a.signal_strength));
434
435 Ok(networks)
436 }
437
438 pub async fn connect_to_wifi(&self, config: WiFiConnectionConfig) -> Result<()> {
440 log::debug!("connect_to_wifi called: ssid='{}' security={:?} username={:?}",
442 config.ssid, config.security_type, config.username);
443
444 let mut connection_settings = HashMap::new();
446 let mut wifi_settings = HashMap::new();
447 let mut security_settings = HashMap::new();
448
449 let mut connection = HashMap::new();
451 connection.insert("id".to_string(), Value::from(config.ssid.clone()));
452 connection.insert("type".to_string(), Value::from("802-11-wireless"));
453 connection_settings.insert("connection".to_string(), connection);
454
455 wifi_settings.insert("ssid".to_string(), Value::from(config.ssid.clone()));
457 wifi_settings.insert("mode".to_string(), Value::from("infrastructure"));
458
459 match config.security_type {
461 WiFiSecurityType::None => {
462 }
464 WiFiSecurityType::Wep => {
465 security_settings.insert("key-mgmt".to_string(), Value::from("none"));
466 if let Some(password) = config.password.clone() {
467 security_settings.insert("wep-key0".to_string(), Value::from(password));
468 }
469 }
470 WiFiSecurityType::WpaPsk => {
471 security_settings.insert("key-mgmt".to_string(), Value::from("wpa-psk"));
472 if let Some(password) = config.password.clone() {
473 security_settings.insert("psk".to_string(), Value::from(password));
474 }
475 }
476 WiFiSecurityType::WpaEap => {
477 security_settings.insert("key-mgmt".to_string(), Value::from("wpa-eap"));
478 if let Some(password) = config.password.clone() {
479 security_settings.insert("password".to_string(), Value::from(password));
480 }
481 if let Some(username) = config.username.clone() {
482 security_settings.insert("identity".to_string(), Value::from(username));
483 }
484 }
485 WiFiSecurityType::Wpa2Psk => {
486 security_settings.insert("key-mgmt".to_string(), Value::from("wpa-psk"));
487 security_settings.insert("proto".to_string(), Value::from("rsn"));
488 if let Some(password) = config.password.clone() {
489 security_settings.insert("psk".to_string(), Value::from(password));
490 }
491 }
492 WiFiSecurityType::Wpa3Psk => {
493 security_settings.insert("key-mgmt".to_string(), Value::from("sae"));
494 if let Some(password) = config.password.clone() {
495 security_settings.insert("psk".to_string(), Value::from(password));
496 }
497 }
498 }
499
500 connection_settings.insert("802-11-wireless".to_string(), wifi_settings);
501 connection_settings.insert("802-11-wireless-security".to_string(), security_settings);
502
503 log::trace!("connection_settings: {:#?}", connection_settings);
505
506 let nm_proxy = zbus::blocking::Proxy::new(
508 &self.connection,
509 "org.freedesktop.NetworkManager",
510 "/org/freedesktop/NetworkManager",
511 "org.freedesktop.NetworkManager",
512 )?;
513
514 let call_result: zbus::Result<(zbus::zvariant::OwnedObjectPath, zbus::zvariant::OwnedObjectPath)> = nm_proxy.call("AddAndActivateConnection", &(connection_settings, "/", "/"));
516
517 match call_result {
518 Ok((conn_path, active_path)) => {
519 log::info!(
520 "AddAndActivateConnection succeeded for ssid='{}' conn='{}' active='{}'",
521 config.ssid,
522 conn_path.as_str(),
523 active_path.as_str()
524 );
525 }
526 Err(e) => {
527 log::error!(
528 "AddAndActivateConnection failed for ssid='{}': {:?}",
529 config.ssid,
530 e
531 );
532 return Err(e.into());
533 }
534 }
535
536 log::debug!("connect_to_wifi finished for ssid='{}'", config.ssid);
537
538 Ok(())
539 }
540
541 pub fn toggle_network_state(&self, enabled: bool) -> Result<bool> {
543 let nm_proxy = zbus::blocking::Proxy::new(
544 &self.connection,
545 "org.freedesktop.NetworkManager",
546 "/org/freedesktop/NetworkManager",
547 "org.freedesktop.NetworkManager",
548 )?;
549
550 let state = if enabled { "on" } else { "off" };
551 let _output = Command::new("nmcli")
552 .arg("networking")
553 .arg(state)
554 .output()?;
555
556 let current_state: bool = nm_proxy.get_property("NetworkingEnabled")?;
557 Ok(current_state)
558 }
559
560 pub fn get_wireless_enabled(&self) -> Result<bool> {
562 let nm_proxy = zbus::blocking::Proxy::new(
563 &self.connection,
564 "org.freedesktop.NetworkManager",
565 "/org/freedesktop/NetworkManager",
566 "org.freedesktop.NetworkManager",
567 )?;
568 Ok(nm_proxy.get_property("WirelessEnabled")?)
569 }
570
571 pub fn set_wireless_enabled(&self, enabled: bool) -> Result<()> {
573 let nm_proxy = zbus::blocking::Proxy::new(
574 &self.connection,
575 "org.freedesktop.NetworkManager",
576 "/org/freedesktop/NetworkManager",
577 "org.freedesktop.NetworkManager",
578 )?;
579 nm_proxy.set_property("WirelessEnabled", enabled)?;
580 Ok(())
581 }
582
583 pub fn is_wireless_available(&self) -> Result<bool> {
585 let devices_variant = self.proxy.get(
587 InterfaceName::from_static_str_unchecked("org.freedesktop.NetworkManager"),
588 "Devices",
589 )?;
590
591 if let Some(zbus::zvariant::Value::Array(devices)) = devices_variant.downcast_ref() {
592 let device_values = devices.get();
593 for device in device_values {
594 if let zbus::zvariant::Value::ObjectPath(ref device_path) = device {
595 let device_props = zbus::blocking::fdo::PropertiesProxy::builder(&self.connection)
596 .destination("org.freedesktop.NetworkManager")?
597 .path(device_path)?
598 .build()?;
599
600 let device_type_variant = device_props.get(
601 InterfaceName::from_static_str_unchecked("org.freedesktop.NetworkManager.Device"),
602 "DeviceType",
603 )?;
604
605 if let Some(zbus::zvariant::Value::U32(device_type)) = device_type_variant.downcast_ref() {
606 if device_type == &2u32 { return Ok(true);
608 }
609 }
610 }
611 }
612 }
613 Ok(false)
614 }
615
616 pub fn listen_network_changes(&self) -> Result<mpsc::Receiver<NetworkInfo>> {
618 let (tx, rx) = mpsc::channel();
619 let connection_clone = self.connection.clone();
620 let app_handle = self.app.clone();
621
622 std::thread::spawn(move || {
624 match zbus::blocking::Connection::system() {
625 Ok(conn) => {
626 if let Ok(proxy) = zbus::blocking::Proxy::new(
628 &conn,
629 "org.freedesktop.NetworkManager",
630 "/org/freedesktop/NetworkManager",
631 "org.freedesktop.NetworkManager",
632 ) {
633 if let Ok(mut signal) = proxy.receive_signal("StateChanged") {
634 while let Some(_msg) = signal.next() {
635 let network_manager = VSKNetworkManager {
636 connection: connection_clone.clone(),
637 proxy: zbus::blocking::fdo::PropertiesProxy::builder(
638 &connection_clone,
639 )
640 .destination("org.freedesktop.NetworkManager")
641 .unwrap()
642 .path("/org/freedesktop/NetworkManager")
643 .unwrap()
644 .build()
645 .unwrap(),
646 app: app_handle.clone(),
647 };
648
649 if let Ok(network_info) =
650 network_manager.get_current_network_state()
651 {
652 if tx.send(network_info).is_err() {
653 break;
654 }
655 }
656 }
657 }
658 }
659 }
660 Err(e) => {
661 eprintln!(
662 "Error al conectar con D-Bus para escuchar cambios de red: {:?}",
663 e
664 );
665 }
666 }
667 });
668
669 Ok(rx)
670 }
671
672 pub async fn disconnect_from_wifi(&self) -> Result<()> {
674 let _current_state = self.get_current_network_state()?;
676
677 let nm_proxy = zbus::blocking::Proxy::new(
679 &self.connection,
680 "org.freedesktop.NetworkManager",
681 "/org/freedesktop/NetworkManager",
682 "org.freedesktop.NetworkManager",
683 )?;
684
685 let active_connections_variant: zbus::zvariant::OwnedValue = self.proxy.get(
687 InterfaceName::from_static_str_unchecked("org.freedesktop.NetworkManager"),
688 "ActiveConnections",
689 )?;
690
691 let active_connections = match active_connections_variant.downcast_ref() {
693 Some(zbus::zvariant::Value::Array(arr)) => arr
694 .iter()
695 .filter_map(|v| match v {
696 zbus::zvariant::Value::ObjectPath(path) => {
697 Some(zbus::zvariant::OwnedObjectPath::from(path.to_owned()))
698 }
699 _ => None,
700 })
701 .collect::<Vec<zbus::zvariant::OwnedObjectPath>>(),
702 _ => Vec::new(),
703 };
704
705 if !active_connections.is_empty() {
706 nm_proxy.call::<_, _, ()>("DeactivateConnection", &(active_connections[0].as_str()))?;
707 Ok(())
708 } else {
709 Ok(())
710 }
711 }
712
713 pub fn get_saved_wifi_networks(&self) -> Result<Vec<NetworkInfo>> {
715 let settings_proxy = zbus::blocking::Proxy::new(
717 &self.connection,
718 "org.freedesktop.NetworkManager",
719 "/org/freedesktop/NetworkManager/Settings",
720 "org.freedesktop.NetworkManager.Settings",
721 )?;
722
723 let connections: Vec<zbus::zvariant::OwnedObjectPath> =
725 settings_proxy.call("ListConnections", &())?;
726 let mut saved_networks = Vec::new();
727
728 for conn_path in connections {
730 let conn_proxy = zbus::blocking::Proxy::new(
732 &self.connection,
733 "org.freedesktop.NetworkManager",
734 conn_path.as_str(),
735 "org.freedesktop.NetworkManager.Settings.Connection",
736 )?;
737
738 let settings: std::collections::HashMap<String, zbus::zvariant::OwnedValue> =
740 conn_proxy.call("GetSettings", &())?;
741
742 if let Some(connection) = settings.get("connection") {
744 let connection_value = connection.to_owned();
745 let connection_dict =
746 match <zbus::zvariant::Value<'_> as Clone>::clone(&connection_value)
747 .downcast::<std::collections::HashMap<String, zbus::zvariant::OwnedValue>>(
748 ) {
749 Some(dict) => dict,
750 _ => continue,
751 };
752
753 if let Some(conn_type) = connection_dict.get("type") {
755 let conn_type_value = conn_type.to_owned();
756 let conn_type_str =
757 match <zbus::zvariant::Value<'_> as Clone>::clone(&conn_type_value)
758 .downcast::<String>()
759 {
760 Some(s) => s,
761 _ => continue,
762 };
763
764 if conn_type_str == "802-11-wireless" {
766 let mut network_info = NetworkInfo::default();
767 network_info.connection_type = "wifi".to_string();
768
769 if let Some(id) = connection_dict.get("id") {
771 let id_value = id.to_owned();
772 if let Some(name) =
773 <zbus::zvariant::Value<'_> as Clone>::clone(&id_value)
774 .downcast::<String>()
775 {
776 network_info.name = name;
777 }
778 }
779
780 if let Some(wireless) = settings.get("802-11-wireless") {
782 let wireless_value = wireless.to_owned();
783 let wireless_dict = match <zbus::zvariant::Value<'_> as Clone>::clone(&wireless_value).downcast::<std::collections::HashMap<String, zbus::zvariant::OwnedValue>>() {
784 Some(dict) => dict,
785 _ => continue,
786 };
787
788 if let Some(ssid) = wireless_dict.get("ssid") {
789 let ssid_value = ssid.to_owned();
790 if let Some(ssid_bytes) =
791 <zbus::zvariant::Value<'_> as Clone>::clone(&ssid_value)
792 .downcast::<Vec<u8>>()
793 {
794 if let Ok(ssid_str) = String::from_utf8(ssid_bytes) {
795 network_info.ssid = ssid_str;
796 }
797 }
798 }
799 }
800
801 if let Some(security) = settings.get("802-11-wireless-security") {
803 let security_value = security.to_owned();
804 let security_dict = match <zbus::zvariant::Value<'_> as Clone>::clone(&security_value).downcast::<std::collections::HashMap<String, zbus::zvariant::OwnedValue>>() {
805 Some(dict) => dict,
806 _ => {
807 network_info.security_type = WiFiSecurityType::None;
808 saved_networks.push(network_info);
809 continue;
810 },
811 };
812
813 if let Some(key_mgmt) = security_dict.get("key-mgmt") {
814 let key_mgmt_value = key_mgmt.to_owned();
815 if let Some(key_mgmt_str) =
816 <zbus::zvariant::Value<'_> as Clone>::clone(&key_mgmt_value)
817 .downcast::<String>()
818 {
819 match key_mgmt_str.as_str() {
820 "none" => {
821 network_info.security_type = WiFiSecurityType::None
822 }
823 "wpa-psk" => {
824 network_info.security_type = WiFiSecurityType::WpaPsk
825 }
826 "wpa-eap" => {
827 network_info.security_type = WiFiSecurityType::WpaEap
828 }
829 _ => network_info.security_type = WiFiSecurityType::None,
830 }
831 }
832 }
833 } else {
834 network_info.security_type = WiFiSecurityType::None;
835 }
836
837 saved_networks.push(network_info);
839 }
840 }
841 }
842 }
843
844 Ok(saved_networks)
845 }
846
847 pub fn delete_wifi_connection(&self, ssid: &str) -> Result<bool> {
849 let settings_proxy = zbus::blocking::Proxy::new(
851 &self.connection,
852 "org.freedesktop.NetworkManager",
853 "/org/freedesktop/NetworkManager/Settings",
854 "org.freedesktop.NetworkManager.Settings",
855 )?;
856
857 let connections: Vec<zbus::zvariant::OwnedObjectPath> =
859 settings_proxy.call("ListConnections", &())?;
860
861 for conn_path in connections {
863 let conn_proxy = zbus::blocking::Proxy::new(
865 &self.connection,
866 "org.freedesktop.NetworkManager",
867 conn_path.as_str(),
868 "org.freedesktop.NetworkManager.Settings.Connection",
869 )?;
870
871 let settings: std::collections::HashMap<String, zbus::zvariant::OwnedValue> =
873 conn_proxy.call("GetSettings", &())?;
874
875 if let Some(connection) = settings.get("connection") {
877 let connection_value = connection.to_owned();
878 let connection_dict =
879 match <zbus::zvariant::Value<'_> as Clone>::clone(&connection_value)
880 .downcast::<std::collections::HashMap<String, zbus::zvariant::OwnedValue>>(
881 ) {
882 Some(dict) => dict,
883 _ => continue,
884 };
885
886 if let Some(conn_type) = connection_dict.get("type") {
888 let conn_type_value = conn_type.to_owned();
889 let conn_type_str =
890 match <zbus::zvariant::Value<'_> as Clone>::clone(&conn_type_value)
891 .downcast::<String>()
892 {
893 Some(s) => s,
894 _ => continue,
895 };
896
897 if conn_type_str == "802-11-wireless" {
899 if let Some(wireless) = settings.get("802-11-wireless") {
900 let wireless_value = wireless.to_owned();
901 let wireless_dict = match <zbus::zvariant::Value<'_> as Clone>::clone(&wireless_value).downcast::<std::collections::HashMap<String, zbus::zvariant::OwnedValue>>() {
902 Some(dict) => dict,
903 _ => continue,
904 };
905
906 if let Some(ssid_value) = wireless_dict.get("ssid") {
907 let ssid_owned = ssid_value.to_owned();
908 if let Some(ssid_bytes) =
909 <zbus::zvariant::Value<'_> as Clone>::clone(&ssid_owned)
910 .downcast::<Vec<u8>>()
911 {
912 if let Ok(conn_ssid_str) = String::from_utf8(ssid_bytes) {
913 if conn_ssid_str == ssid {
915 conn_proxy.call::<_, _, ()>("Delete", &())?;
916 return Ok(true);
917 }
918 }
919 }
920 }
921 }
922 }
923 }
924 }
925 }
926
927 Ok(false)
929 }
930}
931
932pub async fn init(
934 app: &AppHandle<tauri::Wry>,
935 _api: PluginApi<tauri::Wry, ()>,
936) -> Result<VSKNetworkManager<'static, tauri::Wry>> {
937 Ok(VSKNetworkManager::new(app.clone()).await?)
938}