diff --git a/src/common.rs b/src/common.rs index 2daf3aa2508..9f627f39aa7 100644 --- a/src/common.rs +++ b/src/common.rs @@ -993,9 +993,19 @@ fn get_api_server_(api: String, custom: String) -> String { "https://admin.rustdesk.com".to_owned() } +#[inline] +pub fn is_public(url: &str) -> bool { + url.contains("rustdesk.com") +} + +#[inline] +pub fn is_selfhost(url: &str) -> bool { + !is_public(url) +} + pub fn get_audit_server(api: String, custom: String, typ: String) -> String { let url = get_api_server(api, custom); - if url.is_empty() || url.contains("rustdesk.com") { + if url.is_empty() || is_public(&url) { return "".to_owned(); } format!("{}/api/audit/{}", url, typ) diff --git a/src/hbbs_http/sync.rs b/src/hbbs_http/sync.rs index 3502f604f60..abf62f3933e 100644 --- a/src/hbbs_http/sync.rs +++ b/src/hbbs_http/sync.rs @@ -106,40 +106,45 @@ async fn start_hbbs_sync_async() { v[keys::OPTION_PRESET_DEVICE_GROUP_NAME] = json!(device_group_name); } let v = v.to_string(); - use sha2::{Digest, Sha256}; - let mut hasher = Sha256::new(); - hasher.update(url.as_bytes()); - hasher.update(&v.as_bytes()); - let res = hasher.finalize(); - let hash = hbb_common::base64::encode(&res[..]); - let old_hash = config::Status::get("sysinfo_hash"); - let ver = config::Status::get("sysinfo_ver"); // sysinfo_ver is the version of sysinfo on server's side - if hash == old_hash { - // When the api doesn't exist, Ok("") will be returned in test. - let samever = match crate::post_request(url.replace("heartbeat", "sysinfo_ver"), "".to_owned(), "").await { - Ok(x) => { - sysinfo_ver = x.clone(); - *PRO.lock().unwrap() = true; - x == ver - } - _ => { - false // to make sure Pro can be assigned in below post for old - // hbbs pro not supporting sysinfo_ver, use false for ensuring - } - }; - if samever { - info_uploaded = (true, url.clone(), None, id.clone()); - log::info!("sysinfo not changed, skip upload"); - continue; - } + let mut hash = "".to_owned(); + if crate::is_selfhost(&url) { + use sha2::{Digest, Sha256}; + let mut hasher = Sha256::new(); + hasher.update(url.as_bytes()); + hasher.update(&v.as_bytes()); + let res = hasher.finalize(); + hash = hbb_common::base64::encode(&res[..]); + let old_hash = config::Status::get("sysinfo_hash"); + let ver = config::Status::get("sysinfo_ver"); // sysinfo_ver is the version of sysinfo on server's side + if hash == old_hash { + // When the api doesn't exist, Ok("") will be returned in test. + let samever = match crate::post_request(url.replace("heartbeat", "sysinfo_ver"), "".to_owned(), "").await { + Ok(x) => { + sysinfo_ver = x.clone(); + *PRO.lock().unwrap() = true; + x == ver + } + _ => { + false // to make sure Pro can be assigned in below post for old + // hbbs pro not supporting sysinfo_ver, use false for ensuring + } + }; + if samever { + info_uploaded = (true, url.clone(), None, id.clone()); + log::info!("sysinfo not changed, skip upload"); + continue; + } + } } match crate::post_request(url.replace("heartbeat", "sysinfo"), v, "").await { Ok(x) => { if x == "SYSINFO_UPDATED" { info_uploaded = (true, url.clone(), None, id.clone()); log::info!("sysinfo updated"); - config::Status::set("sysinfo_hash", hash); - config::Status::set("sysinfo_ver", sysinfo_ver.clone()); + if !hash.is_empty() { + config::Status::set("sysinfo_hash", hash); + config::Status::set("sysinfo_ver", sysinfo_ver.clone()); + } *PRO.lock().unwrap() = true; } else if x == "ID_NOT_FOUND" { info_uploaded.2 = None; // next heartbeat will upload sysinfo again diff --git a/src/platform/windows.rs b/src/platform/windows.rs index c55953cac59..6e48c8e7fe6 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -1267,7 +1267,7 @@ fn get_after_install( } pub fn install_me(options: &str, path: String, silent: bool, debug: bool) -> ResultType<()> { - let uninstall_str = get_uninstall(false); + let uninstall_str = get_uninstall(false, false); let mut path = path.trim_end_matches('\\').to_owned(); let (subkey, _path, start_menu, exe) = get_default_install_info(); let mut exe = exe; @@ -1428,10 +1428,10 @@ cscript \"{uninstall_shortcut}\" {tray_shortcuts} {shortcuts} copy /Y \"{tmp_path}\\Uninstall {app_name}.lnk\" \"{path}\\\" -{install_remote_printer} {dels} {import_config} {after_install} +{install_remote_printer} {sleep} ", version = crate::VERSION.replace("-", "."), @@ -1488,22 +1488,39 @@ fn get_before_uninstall(kill_self: bool) -> String { ) } -fn get_uninstall(kill_self: bool) -> String { +/// Constructs the uninstall command string for the application. +/// +/// # Parameters +/// - `kill_self`: The command will kill the process of current app name. If `true`, it will kill +/// the current process as well. If `false`, it will exclude the current process from the kill +/// command. +/// - `uninstall_printer`: If `true`, includes commands to uninstall the remote printer. +/// +/// # Details +/// The `uninstall_printer` parameter determines whether the command to uninstall the remote printer +/// is included in the generated uninstall script. If `uninstall_printer` is `false`, the printer +/// related command is omitted from the script. +fn get_uninstall(kill_self: bool, uninstall_printer: bool) -> String { let reg_uninstall_string = get_reg("UninstallString"); if reg_uninstall_string.to_lowercase().contains("msiexec.exe") { return reg_uninstall_string; } let mut uninstall_cert_cmd = "".to_string(); + let mut uninstall_printer_cmd = "".to_string(); if let Ok(exe) = std::env::current_exe() { if let Some(exe_path) = exe.to_str() { uninstall_cert_cmd = format!("\"{}\" --uninstall-cert", exe_path); + if uninstall_printer { + uninstall_printer_cmd = format!("\"{}\" --uninstall-remote-printer", &exe_path); + } } } let (subkey, path, start_menu, _) = get_install_info(); format!( " {before_uninstall} + {uninstall_printer_cmd} {uninstall_cert_cmd} reg delete {subkey} /f {uninstall_amyuni_idd} @@ -1519,10 +1536,7 @@ fn get_uninstall(kill_self: bool) -> String { } pub fn uninstall_me(kill_self: bool) -> ResultType<()> { - if crate::platform::is_win_10_or_greater() { - remote_printer::uninstall_printer(&crate::get_app_name()); - } - run_cmds(get_uninstall(kill_self), true, "uninstall") + run_cmds(get_uninstall(kill_self, true), true, "uninstall") } fn write_cmds(cmds: String, ext: &str, tip: &str) -> ResultType { @@ -2467,6 +2481,19 @@ reg add {subkey} /f /v EstimatedSize /t REG_DWORD /d {size} } else { "".to_owned() }; + + // No need to check the install option here, `is_rd_printer_installed` rarely fails. + let is_printer_installed = remote_printer::is_rd_printer_installed(&app_name).unwrap_or(false); + // Do nothing if the printer is not installed or failed to query if the printer is installed. + let (uninstall_printer_cmd, install_printer_cmd) = if is_printer_installed { + ( + format!("\"{}\" --uninstall-remote-printer", &src_exe), + format!("\"{}\" --install-remote-printer", &src_exe), + ) + } else { + ("".to_owned(), "".to_owned()) + }; + // We do not try to remove all files in the old version. // Because I don't know whether additional files will be installed here after installation, such as drivers. // Just copy files to the installation directory works fine. @@ -2487,6 +2514,8 @@ taskkill /F /IM {app_name}.exe{filter} {reg_cmd} {copy_exe} {restore_service_cmd} +{uninstall_printer_cmd} +{install_printer_cmd} {sleep} ", app_name = app_name,