sysopt.rs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. use serde::{Deserialize, Serialize};
  2. use std::io;
  3. #[cfg(target_os = "windows")]
  4. static DEFAULT_BYPASS: &str = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*;<local>";
  5. #[cfg(target_os = "macos")]
  6. static DEFAULT_BYPASS: &str =
  7. "192.168.0.0/16\n10.0.0.0/8\n172.16.0.0/12\n127.0.0.1\nlocalhost\n*.local\ntimestamp.apple.com\n";
  8. #[cfg(target_os = "macos")]
  9. static MACOS_SERVICE: &str = "Wi-Fi";
  10. #[derive(Debug, Deserialize, Serialize, Clone)]
  11. pub struct SysProxyConfig {
  12. pub enable: bool,
  13. pub server: String,
  14. pub bypass: String,
  15. }
  16. impl Default for SysProxyConfig {
  17. fn default() -> Self {
  18. SysProxyConfig {
  19. enable: false,
  20. server: String::from(""),
  21. bypass: String::from(""),
  22. }
  23. }
  24. }
  25. impl SysProxyConfig {
  26. pub fn new(enable: bool, port: String, bypass: Option<String>) -> Self {
  27. SysProxyConfig {
  28. enable,
  29. server: format!("127.0.0.1:{}", port),
  30. bypass: bypass.unwrap_or(DEFAULT_BYPASS.into()),
  31. }
  32. }
  33. #[cfg(target_os = "windows")]
  34. /// Get the windows system proxy config
  35. pub fn get_sys() -> io::Result<Self> {
  36. use winreg::enums::*;
  37. use winreg::RegKey;
  38. let hkcu = RegKey::predef(HKEY_CURRENT_USER);
  39. let cur_var = hkcu.open_subkey_with_flags(
  40. "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
  41. KEY_READ,
  42. )?;
  43. Ok(SysProxyConfig {
  44. enable: cur_var.get_value::<u32, _>("ProxyEnable")? == 1u32,
  45. server: cur_var.get_value("ProxyServer")?,
  46. bypass: cur_var.get_value("ProxyOverride")?,
  47. })
  48. }
  49. #[cfg(target_os = "macos")]
  50. /// Get the macos system proxy config
  51. pub fn get_sys() -> io::Result<Self> {
  52. use std::process::Command;
  53. let http = macproxy::get_proxy(&["-getwebproxy", MACOS_SERVICE])?;
  54. let https = macproxy::get_proxy(&["-getsecurewebproxy", MACOS_SERVICE])?;
  55. let sock = macproxy::get_proxy(&["-getsocksfirewallproxy", MACOS_SERVICE])?;
  56. let mut enable = false;
  57. let mut server = "".into();
  58. if sock.0 == "Yes" {
  59. enable = true;
  60. server = sock.1;
  61. }
  62. if https.0 == "Yes" {
  63. enable = true;
  64. server = https.1;
  65. }
  66. if http.0 == "Yes" || !enable {
  67. enable = http.0 == "Yes";
  68. server = http.1;
  69. }
  70. let bypass_output = Command::new("networksetup")
  71. .args(["-getproxybypassdomains", MACOS_SERVICE])
  72. .output()?;
  73. let bypass = std::str::from_utf8(&bypass_output.stdout).unwrap_or(DEFAULT_BYPASS);
  74. Ok(SysProxyConfig {
  75. enable,
  76. server,
  77. bypass: bypass.into(),
  78. })
  79. }
  80. #[cfg(target_os = "windows")]
  81. /// Set the windows system proxy config
  82. pub fn set_sys(&self) -> io::Result<()> {
  83. use winreg::enums::*;
  84. use winreg::RegKey;
  85. let hkcu = RegKey::predef(HKEY_CURRENT_USER);
  86. let cur_var = hkcu.open_subkey_with_flags(
  87. "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
  88. KEY_SET_VALUE,
  89. )?;
  90. let enable: u32 = if self.enable { 1u32 } else { 0u32 };
  91. cur_var.set_value("ProxyEnable", &enable)?;
  92. cur_var.set_value("ProxyServer", &self.server)?;
  93. cur_var.set_value("ProxyOverride", &self.bypass)
  94. }
  95. #[cfg(target_os = "macos")]
  96. /// Set the macos system proxy config
  97. pub fn set_sys(&self) -> io::Result<()> {
  98. let enable = self.enable;
  99. let server = self.server.as_str();
  100. macproxy::set_proxy("-setwebproxy", MACOS_SERVICE, enable, server)?;
  101. macproxy::set_proxy("-setsecurewebproxy", MACOS_SERVICE, enable, server)?;
  102. macproxy::set_proxy("-setsocksfirewallproxy", MACOS_SERVICE, enable, server)
  103. }
  104. }
  105. #[cfg(target_os = "macos")]
  106. mod macproxy {
  107. use super::*;
  108. use std::process::Command;
  109. /// use networksetup
  110. /// get the target proxy config
  111. pub(super) fn get_proxy(args: &[&str; 2]) -> io::Result<(String, String)> {
  112. let output = Command::new("networksetup").args(args).output()?;
  113. match std::str::from_utf8(&output.stdout) {
  114. Ok(stdout) => {
  115. let enable = parse(stdout, "Enabled:");
  116. let server = parse(stdout, "Server:");
  117. let port = parse(stdout, "Port:");
  118. let server = format!("{}:{}", server, port);
  119. Ok((enable.into(), server))
  120. }
  121. Err(_) => Err(io::Error::from_raw_os_error(1)),
  122. }
  123. }
  124. /// use networksetup
  125. /// set the target proxy config
  126. pub(super) fn set_proxy(
  127. target: &str, // like: -setwebproxy
  128. device: &str,
  129. enable: bool,
  130. server: &str,
  131. ) -> io::Result<()> {
  132. let mut split = server.split(":");
  133. let domain = split.next();
  134. let port = split.next();
  135. // can not parse the field
  136. if domain.is_none() || port.is_none() {
  137. return Err(io::Error::from_raw_os_error(1));
  138. }
  139. let args = vec![target, device, domain.unwrap(), port.unwrap()];
  140. Command::new("networksetup").args(&args).status()?;
  141. let target_state = String::from(target) + "state";
  142. let enable = if enable { "on" } else { "off" };
  143. let args = vec![target_state.as_str(), device, enable];
  144. Command::new("networksetup").args(&args).status()?;
  145. Ok(())
  146. }
  147. /// parse the networksetup output
  148. pub(super) fn parse<'a>(target: &'a str, key: &'a str) -> &'a str {
  149. match target.find(key) {
  150. Some(idx) => {
  151. let idx = idx + key.len();
  152. let value = &target[idx..];
  153. let value = match value.find("\n") {
  154. Some(end) => &value[..end],
  155. None => value,
  156. };
  157. value.trim()
  158. }
  159. None => "",
  160. }
  161. }
  162. #[test]
  163. fn test_get() {
  164. use std::process::Command;
  165. let output = Command::new("networksetup")
  166. .args(["-getwebproxy", "Wi-Fi"])
  167. .output();
  168. let output = output.unwrap();
  169. let stdout = std::str::from_utf8(&output.stdout).unwrap();
  170. let enable = parse(stdout, "Enabled:");
  171. let server = parse(stdout, "Server:");
  172. let port = parse(stdout, "Port:");
  173. println!("enable: {}, server: {}, port: {}", enable, server, port);
  174. dbg!(SysProxyConfig::get_sys().unwrap());
  175. }
  176. #[test]
  177. fn test_set() {
  178. let sysproxy = SysProxyConfig::new(true, "7890".into(), None);
  179. dbg!(sysproxy.set_sys().unwrap());
  180. }
  181. }