Compare commits

...

4 Commits

Author SHA1 Message Date
Kuksgauzen
5b4d6baf47 fix: wrap BackingScaleFactor in autoreleasepool to stop NSDictionary accumulation on macOS (#15623)
Signed-off-by: Viktor Kuksgauzen <vkpiar@gmail.com>
2026-07-21 05:42:43 +08:00
gateslu
7696b0ee51 fix(linux): forward forced display server to user server (#15627)
Signed-off-by: Gateslu <lyjbbq@163.com>
2026-07-20 13:24:48 +08:00
CHarris
20ab5ab0ad fix(deploy): don't wipe local id when --deploy gets an empty --id (#15633)
`rustdesk --deploy --id ""` (e.g. an unset variable in a deployment
script) deploys a blank id, then wipes the local id and unconfirms the
key through the IPC config write. The Android deploy flow already guards
an empty id (#15146); apply the same guard to the CLI, and reject an
empty id at the IPC write boundary the same way the read path was fixed
in #15626.
2026-07-20 10:58:28 +08:00
CHarris
c01300be20 fix(ipc): never adopt an empty id from the main IPC (#15626) 2026-07-20 10:22:46 +08:00
4 changed files with 45 additions and 21 deletions

View File

@@ -667,7 +667,8 @@ pub fn core_main() -> Option<Vec<String>> {
None None
} }
}; };
let new_id = get_value("--id"); // An empty --id (e.g. an unset var) would deploy a blank id; the Android flow guards this too (#15146).
let new_id = get_value("--id").filter(|s| !s.is_empty());
match crate::ui_interface::deploy_device(token, new_id) { match crate::ui_interface::deploy_device(token, new_id) {
crate::ui_interface::DeployResult::Ok => { crate::ui_interface::DeployResult::Ok => {
println!("Device deployed."); println!("Device deployed.");

View File

@@ -881,8 +881,14 @@ async fn handle(data: Data, stream: &mut Connection) {
Some(value) => { Some(value) => {
let mut updated = true; let mut updated = true;
if name == "id" { if name == "id" {
// An empty id would wipe the local id and unconfirm the key (cf. #15626).
if value.is_empty() {
log::warn!("Ignoring empty id write over IPC");
updated = false;
} else {
Config::set_key_confirmed(false); Config::set_key_confirmed(false);
Config::set_id(&value); Config::set_id(&value);
}
} else if name == "temporary-password" { } else if name == "temporary-password" {
password::update_temporary_password(); password::update_temporary_password();
} else if name == "permanent-password" { } else if name == "permanent-password" {
@@ -1689,7 +1695,12 @@ pub fn clear_trusted_devices() {
} }
pub fn get_id() -> String { pub fn get_id() -> String {
// An empty id may come from a process that took over the main IPC with a
// config scope that has no id yet (e.g. a user GUI that became the server
// while the installed service was restarting). Treat it as no answer,
// otherwise the empty id is adopted below and wipes the local one.
if let Ok(Some(v)) = get_config("id") { if let Ok(Some(v)) = get_config("id") {
if !v.is_empty() {
// update salt also, so that next time reinstallation not causing first-time auto-login failure // update salt also, so that next time reinstallation not causing first-time auto-login failure
if let Ok(Some(v2)) = get_config("salt") { if let Ok(Some(v2)) = get_config("salt") {
Config::set_salt(&v2); Config::set_salt(&v2);
@@ -1698,11 +1709,11 @@ pub fn get_id() -> String {
Config::set_key_confirmed(false); Config::set_key_confirmed(false);
Config::set_id(&v); Config::set_id(&v);
} }
v return v;
} else {
Config::get_id()
} }
} }
Config::get_id()
}
pub async fn get_rendezvous_server(ms_timeout: u64) -> (String, Vec<String>) { pub async fn get_rendezvous_server(ms_timeout: u64) -> (String, Vec<String>) {
if let Ok(Some(v)) = get_config_async("rendezvous_server", ms_timeout).await { if let Ok(Some(v)) = get_config_async("rendezvous_server", ms_timeout).await {

View File

@@ -646,6 +646,16 @@ fn try_start_server_(desktop: Option<&Desktop>) -> ResultType<Option<Child>> {
if !desktop.dbus.is_empty() { if !desktop.dbus.is_empty() {
envs.push(("DBUS_SESSION_BUS_ADDRESS", desktop.dbus.clone())); envs.push(("DBUS_SESSION_BUS_ADDRESS", desktop.dbus.clone()));
} }
if let Ok(forced_display_server) =
std::env::var("RUSTDESK_FORCED_DISPLAY_SERVER")
{
if !forced_display_server.is_empty() {
envs.push((
"RUSTDESK_FORCED_DISPLAY_SERVER",
forced_display_server,
));
}
}
envs.push(( envs.push((
"TERM", "TERM",
get_cur_term(&desktop.uid).unwrap_or_else(|| suggest_best_term()), get_cur_term(&desktop.uid).unwrap_or_else(|| suggest_best_term()),

View File

@@ -118,6 +118,7 @@ extern "C" bool MacCheckAdminAuthorization() {
// https://gist.github.com/briankc/025415e25900750f402235dbf1b74e42 // https://gist.github.com/briankc/025415e25900750f402235dbf1b74e42
extern "C" float BackingScaleFactor(uint32_t display) { extern "C" float BackingScaleFactor(uint32_t display) {
@autoreleasepool {
NSArray<NSScreen *> *screens = [NSScreen screens]; NSArray<NSScreen *> *screens = [NSScreen screens];
for (NSScreen *screen in screens) { for (NSScreen *screen in screens) {
NSDictionary *deviceDescription = [screen deviceDescription]; NSDictionary *deviceDescription = [screen deviceDescription];
@@ -129,6 +130,7 @@ extern "C" float BackingScaleFactor(uint32_t display) {
} }
return 1; return 1;
} }
}
// https://github.com/jhford/screenresolution/blob/master/cg_utils.c // https://github.com/jhford/screenresolution/blob/master/cg_utils.c
// https://github.com/jdoupe/screenres/blob/master/setgetscreen.m // https://github.com/jdoupe/screenres/blob/master/setgetscreen.m