From 9c4a46bcdb7ec57c405f3bf5a3e610fca58a9838 Mon Sep 17 00:00:00 2001 From: John Smith Date: Fri, 17 Mar 2023 08:20:35 +0800 Subject: [PATCH] fix: escape the space in path (#451) --- src-tauri/src/core/manager.rs | 36 ++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/core/manager.rs b/src-tauri/src/core/manager.rs index 250dc5c..dfba550 100644 --- a/src-tauri/src/core/manager.rs +++ b/src-tauri/src/core/manager.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + /// 给clash内核的tun模式授权 #[cfg(any(target_os = "macos", target_os = "linux"))] 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; 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}"); #[cfg(target_os = "macos")] 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 command = format!(r#"do shell script "{shell}" with administrator privileges"#); Command::new("osascript") @@ -35,3 +40,32 @@ pub fn grant_permission(core: String) -> anyhow::Result<()> { 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)) } + } +}