From ed0ded33b7d34c7b4f27466dc61d125aad9d0b76 Mon Sep 17 00:00:00 2001 From: ClSlaid Date: Sat, 28 Oct 2023 09:55:34 +0800 Subject: [PATCH] patch: fix arboard pollution Signed-off-by: ClSlaid --- Cargo.lock | 2 + Cargo.toml | 2 + .../src/platform/linux/local_file.rs | 2 +- libs/clipboard/src/platform/linux/mod.rs | 1 + src/common.rs | 73 ++++++++++++++++++- 5 files changed, 78 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aedafe453..82da07f0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5294,6 +5294,8 @@ dependencies = [ "winreg 0.11.0", "winres", "wol-rs", + "x11-clipboard", + "x11rb 0.12.0", "zip", ] diff --git a/Cargo.toml b/Cargo.toml index f6c014483..708390bf8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -132,6 +132,8 @@ dbus = "0.9" dbus-crossroads = "0.5" pam = { git="https://github.com/fufesou/pam", optional = true } users = { version = "0.11" } +x11-clipboard = {git="https://github.com/clslaid/x11-clipboard", branch = "feat/store-batch"} +x11rb = {version = "0.12", features = ["all-extensions"]} [target.'cfg(target_os = "android")'.dependencies] android_logger = "0.13" diff --git a/libs/clipboard/src/platform/linux/local_file.rs b/libs/clipboard/src/platform/linux/local_file.rs index eddde75d6..f49274b7a 100644 --- a/libs/clipboard/src/platform/linux/local_file.rs +++ b/libs/clipboard/src/platform/linux/local_file.rs @@ -122,7 +122,7 @@ impl LocalFile { let wstr: WString = WString::from(&path); let name = wstr.as_bytes(); - log::debug!( + log::trace!( "put file to list: name_len {}, name {}", name.len(), &self.name diff --git a/libs/clipboard/src/platform/linux/mod.rs b/libs/clipboard/src/platform/linux/mod.rs index 67655f6f3..3a13a5f32 100644 --- a/libs/clipboard/src/platform/linux/mod.rs +++ b/libs/clipboard/src/platform/linux/mod.rs @@ -328,6 +328,7 @@ impl ClipboardContext { } pub fn serve(&self, conn_id: i32, msg: ClipboardFile) -> Result<(), CliprdrError> { + log::debug!("serve clipboard file from conn: {}", conn_id); if self.is_stopped() { log::debug!("cliprdr stopped, restart it"); self.run()?; diff --git a/src/common.rs b/src/common.rs index cf75fab1b..e81c71b53 100644 --- a/src/common.rs +++ b/src/common.rs @@ -11,9 +11,80 @@ pub enum GrabState { Exit, } -#[cfg(not(any(target_os = "android", target_os = "ios")))] +#[cfg(not(any( + target_os = "android", + target_os = "ios", + all(target_os = "linux", not(feature = "wayland")) +)))] pub use arboard::Clipboard as ClipboardContext; +#[cfg(all(target_os = "linux", not(feature = "wayland")))] +pub struct ClipboardContext { + string_setter: x11rb::protocol::xproto::Atom, + string_getter: x11rb::protocol::xproto::Atom, + text_uri_list: x11rb::protocol::xproto::Atom, + clip: x11_clipboard::Clipboard, +} + +#[cfg(all(target_os = "linux", not(feature = "wayland")))] +impl ClipboardContext { + pub fn new() -> Result { + log::debug!("create clipboard context"); + let clip = x11_clipboard::Clipboard::new().map_err(|e| e.to_string())?; + let string_getter = clip + .getter + .get_atom("UTF8_STRING") + .map_err(|e| e.to_string())?; + let string_setter = clip + .setter + .get_atom("UTF8_STRING") + .map_err(|e| e.to_string())?; + let text_uri_list = clip + .getter + .get_atom("text/uri-list") + .map_err(|e| e.to_string())?; + log::debug!("clipboard context created"); + Ok(Self { + clip, + text_uri_list, + string_setter, + string_getter, + }) + } + + pub fn get_text(&mut self) -> Result { + let clip = self.clip.getter.atoms.clipboard; + let prop = self.clip.getter.atoms.property; + log::trace!("clipboard get text"); + + const TIMEOUT: std::time::Duration = std::time::Duration::from_millis(100); + + let text_content = self + .clip + .load(clip, self.string_getter, prop, TIMEOUT) + .map_err(|e| e.to_string())?; + + let file_urls = self.clip.load(clip, self.text_uri_list, prop, TIMEOUT); + + if file_urls.is_err() || file_urls.as_ref().unwrap().is_empty() { + log::trace!("clipboard get text, no file urls"); + String::from_utf8(text_content).map_err(|e| e.to_string()) + } else { + log::trace!("clipboard get text, file urls found"); + Err("clipboard polluted".to_owned()) + } + } + + pub fn set_text(&mut self, content: String) -> Result<(), String> { + let clip = self.clip.setter.atoms.clipboard; + + let value = content.into_bytes(); + self.clip + .store(clip, self.string_setter, value) + .map_err(|e| e.to_string()) + } +} + #[cfg(not(any(target_os = "android", target_os = "ios")))] use hbb_common::compress::decompress; use hbb_common::{