From 8a608c3c3eac4a0088d62863b4b761827a352646 Mon Sep 17 00:00:00 2001 From: MystiPanda Date: Thu, 14 Dec 2023 12:50:45 +0800 Subject: [PATCH] chore: Optimize service path --- src-tauri/Cargo.lock | 87 +++++++++++++++++++++++ src-tauri/Cargo.toml | 2 +- src-tauri/src/config/prfitem.rs | 5 +- src-tauri/src/core/win_uwp.rs | 9 ++- src-tauri/src/utils/dirs.rs | 84 ++++++---------------- src-tauri/src/utils/init.rs | 80 ++++++++++++++++----- src-tauri/src/utils/resolve.rs | 5 +- src/components/profile/profile-viewer.tsx | 2 +- 8 files changed, 185 insertions(+), 89 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 04831c2..248737b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1954,6 +1954,20 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -3602,6 +3616,7 @@ dependencies = [ "http", "http-body", "hyper", + "hyper-rustls", "hyper-tls", "ipnet", "js-sys", @@ -3611,12 +3626,15 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "system-configuration", "tokio", "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3624,6 +3642,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", "winreg 0.50.0", ] @@ -3651,6 +3670,20 @@ dependencies = [ "windows 0.37.0", ] +[[package]] +name = "ring" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +dependencies = [ + "cc", + "getrandom 0.2.11", + "libc", + "spin", + "untrusted", + "windows-sys 0.48.0", +] + [[package]] name = "rquickjs" version = "0.3.1" @@ -3745,6 +3778,18 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.21.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" +dependencies = [ + "log 0.4.20", + "ring", + "rustls-webpki", + "sct", +] + [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -3754,6 +3799,16 @@ dependencies = [ "base64 0.21.5", ] +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -3802,6 +3857,16 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "security-framework" version = "2.9.2" @@ -4862,6 +4927,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.14" @@ -5147,6 +5222,12 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5449,6 +5530,12 @@ dependencies = [ "system-deps 6.2.0", ] +[[package]] +name = "webpki-roots" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" + [[package]] name = "webview2-com" version = "0.19.1" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index b9d89b4..4aba68b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -37,7 +37,7 @@ percent-encoding = "2.3.1" window-shadows = { version = "0.2" } tokio = { version = "1", features = ["full"] } serde = { version = "1.0", features = ["derive"] } -reqwest = { version = "0.11", features = ["json"] } +reqwest = { version = "0.11", features = ["json", "rustls-tls"] } sysproxy = { git="https://github.com/zzzgydi/sysproxy-rs", branch = "main" } tauri = { version = "1.5", features = ["icon-png", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all"] } diff --git a/src-tauri/src/config/prfitem.rs b/src-tauri/src/config/prfitem.rs index 1cc9607..a7de9ef 100644 --- a/src-tauri/src/config/prfitem.rs +++ b/src-tauri/src/config/prfitem.rs @@ -190,7 +190,7 @@ impl PrfItem { let self_proxy = opt_ref.map_or(false, |o| o.self_proxy.unwrap_or(false)); let user_agent = opt_ref.map_or(None, |o| o.user_agent.clone()); - let mut builder = reqwest::ClientBuilder::new().no_proxy(); + let mut builder = reqwest::ClientBuilder::new().use_rustls_tls().no_proxy(); // 使用软件自己的代理 if self_proxy { @@ -231,8 +231,7 @@ impl PrfItem { }; } - let version = unsafe { dirs::APP_VERSION }; - let version = format!("clash-verge/{version}"); + let version = format!("clash-verge-rev"); builder = builder.user_agent(user_agent.unwrap_or(version)); let resp = builder.build()?.get(url).send().await?; diff --git a/src-tauri/src/core/win_uwp.rs b/src-tauri/src/core/win_uwp.rs index c34511f..4a19b93 100644 --- a/src-tauri/src/core/win_uwp.rs +++ b/src-tauri/src/core/win_uwp.rs @@ -7,8 +7,8 @@ use runas::Command as RunasCommand; use std::process::Command as StdCommand; pub async fn invoke_uwptools() -> Result<()> { - let binary_path = dirs::service_path()?; - let tool_path = binary_path.with_file_name("enableLoopback.exe"); + let resource_dir = dirs::app_resources_dir()?; + let tool_path = resource_dir.join("enableLoopback.exe"); if !tool_path.exists() { bail!("enableLoopback exe not found"); @@ -17,10 +17,9 @@ pub async fn invoke_uwptools() -> Result<()> { let token = Token::with_current_process()?; let level = token.privilege_level()?; - match level { + match level { PrivilegeLevel::NotPrivileged => RunasCommand::new(tool_path).status()?, - _ => StdCommand::new(tool_path) - .status()?, + _ => StdCommand::new(tool_path).status()?, }; Ok(()) diff --git a/src-tauri/src/utils/dirs.rs b/src-tauri/src/utils/dirs.rs index 0c7e7b5..e3347ad 100644 --- a/src-tauri/src/utils/dirs.rs +++ b/src-tauri/src/utils/dirs.rs @@ -1,8 +1,9 @@ +use crate::core::handle; use anyhow::Result; use std::path::PathBuf; use tauri::{ api::path::{data_dir, resource_dir}, - Env, PackageInfo, + Env, }; #[cfg(not(feature = "verge-dev"))] @@ -14,73 +15,38 @@ static CLASH_CONFIG: &str = "config.yaml"; static VERGE_CONFIG: &str = "verge.yaml"; static PROFILE_YAML: &str = "profiles.yaml"; -static mut RESOURCE_DIR: Option = None; - -/// portable flag -#[allow(unused)] -static mut PORTABLE_FLAG: bool = false; - -pub static mut APP_VERSION: &str = "v1.2.0"; - -/// initialize portable flag -#[cfg(target_os = "windows")] -pub unsafe fn init_portable_flag() -> Result<()> { +/// get the verge app home dir +pub fn app_home_dir() -> Result { use tauri::utils::platform::current_exe; - let exe = current_exe()?; - - if let Some(dir) = exe.parent() { + let app_exe = current_exe()?; + if let Some(dir) = app_exe.parent() { let dir = PathBuf::from(dir).join(".config/PORTABLE"); if dir.exists() { - PORTABLE_FLAG = true; - } - } - - Ok(()) -} - -/// get the verge app home dir -pub fn app_home_dir() -> Result { - #[cfg(target_os = "windows")] - unsafe { - use tauri::utils::platform::current_exe; - - if !PORTABLE_FLAG { - Ok(data_dir() - .ok_or(anyhow::anyhow!("failed to get app home dir"))? - .join(APP_ID)) - } else { - let app_exe = current_exe()?; let app_exe = dunce::canonicalize(app_exe)?; let app_dir = app_exe .parent() .ok_or(anyhow::anyhow!("failed to get the portable app dir"))?; - Ok(PathBuf::from(app_dir).join(".config").join(APP_ID)) + return Ok(PathBuf::from(app_dir).join(".config").join(APP_ID)); } } - - #[cfg(not(target_os = "windows"))] Ok(data_dir() .ok_or(anyhow::anyhow!("failed to get app home dir"))? .join(APP_ID)) } /// get the resources dir -pub fn app_resources_dir(package_info: &PackageInfo) -> Result { - let res_dir = resource_dir(package_info, &Env::default()) - .ok_or(anyhow::anyhow!("failed to get the resource dir"))? - .join("resources"); - - unsafe { - RESOURCE_DIR = Some(res_dir.clone()); - - let ver = package_info.version.to_string(); - let ver_str = format!("v{ver}"); - APP_VERSION = Box::leak(Box::new(ver_str)); - } - - Ok(res_dir) +pub fn app_resources_dir() -> Result { + let handle = handle::Handle::global(); + let app_handle = handle.app_handle.lock(); + if let Some(app_handle) = app_handle.as_ref() { + let res_dir = resource_dir(app_handle.package_info(), &Env::default()) + .ok_or(anyhow::anyhow!("failed to get the resource dir"))? + .join("resources"); + return Ok(res_dir); + }; + Err(anyhow::anyhow!("failed to get the resource dir")) } /// profiles dir @@ -105,22 +71,18 @@ pub fn profiles_path() -> Result { Ok(app_home_dir()?.join(PROFILE_YAML)) } -#[allow(unused)] -pub fn app_res_dir() -> Result { - unsafe { - Ok(RESOURCE_DIR - .clone() - .ok_or(anyhow::anyhow!("failed to get the resource dir"))?) - } -} - pub fn clash_pid_path() -> Result { Ok(app_home_dir()?.join("clash.pid")) } +#[cfg(windows)] +pub fn service_dir() -> Result { + Ok(app_home_dir()?.join("service")) +} + #[cfg(windows)] pub fn service_path() -> Result { - Ok(app_home_dir()?.join("clash-verge-service.exe")) + Ok(service_dir()?.join("clash-verge-service.exe")) } #[cfg(windows)] diff --git a/src-tauri/src/utils/init.rs b/src-tauri/src/utils/init.rs index ed6aa33..d797eaa 100644 --- a/src-tauri/src/utils/init.rs +++ b/src-tauri/src/utils/init.rs @@ -9,7 +9,6 @@ use log4rs::config::{Appender, Logger, Root}; use log4rs::encode::pattern::PatternEncoder; use std::fs::{self, DirEntry}; use std::str::FromStr; -use tauri::PackageInfo; /// initialize this instance's log file fn init_log() -> Result<()> { @@ -142,11 +141,6 @@ pub fn delete_log() -> Result<()> { /// Initialize all the config files /// before tauri setup pub fn init_config() -> Result<()> { - #[cfg(target_os = "windows")] - unsafe { - let _ = dirs::init_portable_flag(); - } - let _ = init_log(); let _ = delete_log(); @@ -188,9 +182,9 @@ pub fn init_config() -> Result<()> { /// initialize app resources /// after tauri setup -pub fn init_resources(package_info: &PackageInfo) -> Result<()> { +pub fn init_resources() -> Result<()> { let app_dir = dirs::app_home_dir()?; - let res_dir = dirs::app_resources_dir(package_info)?; + let res_dir = dirs::app_resources_dir()?; if !app_dir.exists() { let _ = fs::create_dir_all(&app_dir); @@ -200,14 +194,7 @@ pub fn init_resources(package_info: &PackageInfo) -> Result<()> { } #[cfg(target_os = "windows")] - let file_list = [ - "Country.mmdb", - "geoip.dat", - "geosite.dat", - "clash-verge-service.exe", - "install-service.exe", - "uninstall-service.exe", - ]; + let file_list = ["Country.mmdb", "geoip.dat", "geosite.dat"]; #[cfg(not(target_os = "windows"))] let file_list = ["Country.mmdb", "geoip.dat", "geosite.dat"]; @@ -251,3 +238,64 @@ pub fn init_resources(package_info: &PackageInfo) -> Result<()> { Ok(()) } + +/// initialize service resources +/// after tauri setup +#[cfg(target_os = "windows")] +pub fn init_service() -> Result<()> { + let service_dir = dirs::service_dir()?; + let res_dir = dirs::app_resources_dir()?; + + if !service_dir.exists() { + let _ = fs::create_dir_all(&service_dir); + } + if !res_dir.exists() { + let _ = fs::create_dir_all(&res_dir); + } + + let file_list = [ + "clash-verge-service.exe", + "install-service.exe", + "uninstall-service.exe", + ]; + + // copy the resource file + // if the source file is newer than the destination file, copy it over + for file in file_list.iter() { + let src_path = res_dir.join(file); + let dest_path = service_dir.join(file); + + let handle_copy = || { + match fs::copy(&src_path, &dest_path) { + Ok(_) => log::debug!(target: "app", "resources copied '{file}'"), + Err(err) => { + log::error!(target: "app", "failed to copy resources '{file}', {err}") + } + }; + }; + + if src_path.exists() && !dest_path.exists() { + handle_copy(); + continue; + } + + let src_modified = fs::metadata(&src_path).and_then(|m| m.modified()); + let dest_modified = fs::metadata(&dest_path).and_then(|m| m.modified()); + + match (src_modified, dest_modified) { + (Ok(src_modified), Ok(dest_modified)) => { + if src_modified > dest_modified { + handle_copy(); + } else { + log::debug!(target: "app", "skipping resource copy '{file}'"); + } + } + _ => { + log::debug!(target: "app", "failed to get modified '{file}'"); + handle_copy(); + } + }; + } + + Ok(()) +} diff --git a/src-tauri/src/utils/resolve.rs b/src-tauri/src/utils/resolve.rs index b8949b2..4e8a57d 100644 --- a/src-tauri/src/utils/resolve.rs +++ b/src-tauri/src/utils/resolve.rs @@ -30,8 +30,9 @@ pub fn resolve_setup(app: &mut App) { handle::Handle::global().init(app.app_handle()); - log_err!(init::init_resources(app.package_info())); - + log_err!(init::init_resources()); + #[cfg(target_os = "windows")] + log_err!(init::init_service()); // 处理随机端口 let enable_random_port = Config::verge().latest().enable_random_port.unwrap_or(false); diff --git a/src/components/profile/profile-viewer.tsx b/src/components/profile/profile-viewer.tsx index cdb190e..40700f5 100644 --- a/src/components/profile/profile-viewer.tsx +++ b/src/components/profile/profile-viewer.tsx @@ -209,7 +209,7 @@ export const ProfileViewer = forwardRef( )}