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