fix: escape the space in path (#451)

This commit is contained in:
John Smith 2023-03-17 08:20:35 +08:00 committed by GitHub
parent 52658886e7
commit 9c4a46bcdb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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)) }
}
}