|
@@ -1,3 +1,5 @@
|
|
|
|
+use std::borrow::Cow;
|
|
|
|
+
|
|
/// 给clash内核的tun模式授权
|
|
/// 给clash内核的tun模式授权
|
|
#[cfg(any(target_os = "macos", target_os = "linux"))]
|
|
#[cfg(any(target_os = "macos", target_os = "linux"))]
|
|
pub fn grant_permission(core: String) -> anyhow::Result<()> {
|
|
pub fn grant_permission(core: String) -> anyhow::Result<()> {
|
|
@@ -5,12 +7,15 @@ pub fn grant_permission(core: String) -> anyhow::Result<()> {
|
|
use tauri::utils::platform::current_exe;
|
|
use tauri::utils::platform::current_exe;
|
|
|
|
|
|
let path = current_exe()?.with_file_name(core).canonicalize()?;
|
|
let path = current_exe()?.with_file_name(core).canonicalize()?;
|
|
- let path = path.display();
|
|
|
|
|
|
+ let path = path.display().to_string();
|
|
|
|
|
|
log::debug!("grant_permission path: {path}");
|
|
log::debug!("grant_permission path: {path}");
|
|
|
|
|
|
#[cfg(target_os = "macos")]
|
|
#[cfg(target_os = "macos")]
|
|
let output = {
|
|
let output = {
|
|
|
|
+ // the path of clash /Applications/Clash Verge.app/Contents/MacOS/clash
|
|
|
|
+ // https://apple.stackexchange.com/questions/82967/problem-with-empty-spaces-when-executing-shell-commands-in-applescript
|
|
|
|
+ let path = escape(&path);
|
|
let shell = format!("chown root:admin {path}\nchmod +sx {path}");
|
|
let shell = format!("chown root:admin {path}\nchmod +sx {path}");
|
|
let command = format!(r#"do shell script "{shell}" with administrator privileges"#);
|
|
let command = format!(r#"do shell script "{shell}" with administrator privileges"#);
|
|
Command::new("osascript")
|
|
Command::new("osascript")
|
|
@@ -35,3 +40,32 @@ pub fn grant_permission(core: String) -> anyhow::Result<()> {
|
|
anyhow::bail!("{stderr}");
|
|
anyhow::bail!("{stderr}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+pub fn escape<'a>(text: &'a str) -> Cow<'a, str> {
|
|
|
|
+ let bytes = text.as_bytes();
|
|
|
|
+
|
|
|
|
+ let mut owned = None;
|
|
|
|
+
|
|
|
|
+ for pos in 0..bytes.len() {
|
|
|
|
+ let special = match bytes[pos] {
|
|
|
|
+ b' ' => Some(b' '),
|
|
|
|
+ _ => None,
|
|
|
|
+ };
|
|
|
|
+ if let Some(s) = special {
|
|
|
|
+ if owned.is_none() {
|
|
|
|
+ owned = Some(bytes[0..pos].to_owned());
|
|
|
|
+ }
|
|
|
|
+ owned.as_mut().unwrap().push(b'\\');
|
|
|
|
+ owned.as_mut().unwrap().push(b'\\');
|
|
|
|
+ owned.as_mut().unwrap().push(s);
|
|
|
|
+ } else if let Some(owned) = owned.as_mut() {
|
|
|
|
+ owned.push(bytes[pos]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if let Some(owned) = owned {
|
|
|
|
+ unsafe { Cow::Owned(String::from_utf8_unchecked(owned)) }
|
|
|
|
+ } else {
|
|
|
|
+ unsafe { Cow::Borrowed(std::str::from_utf8_unchecked(bytes)) }
|
|
|
|
+ }
|
|
|
|
+}
|