From a2bfdf331b006e9019445189951120b95e40587f Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Fri, 19 Sep 2025 20:50:32 +0200 Subject: [PATCH] Implement x-kde-passwordManagerHint --- Cargo.lock | 43 +++++++++++++++++++++++++++++++++++-------- Cargo.toml | 1 + shell.nix | 2 ++ src/daemon.rs | 40 +++++++++++++++++++++++++++++++++++----- src/lib.rs | 4 ++++ 5 files changed, 77 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9788284..07b6619 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -614,6 +614,7 @@ name = "clippyboard" version = "0.1.0" dependencies = [ "ciborium", + "ctrlc", "dirs", "eframe", "egui_extras", @@ -727,6 +728,17 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +[[package]] +name = "ctrlc" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881c5d0a13b2f1498e2306e82cbada78390e152d4b1378fb28a84f4dcd0dc4f3" +dependencies = [ + "dispatch", + "nix", + "windows-sys 0.61.0", +] + [[package]] name = "cursor-icon" version = "1.2.0" @@ -3609,7 +3621,7 @@ dependencies = [ "windows-collections", "windows-core 0.61.2", "windows-future", - "windows-link", + "windows-link 0.1.3", "windows-numerics", ] @@ -3643,7 +3655,7 @@ checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement 0.60.0", "windows-interface 0.59.1", - "windows-link", + "windows-link 0.1.3", "windows-result 0.3.4", "windows-strings 0.4.2", ] @@ -3655,7 +3667,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ "windows-core 0.61.2", - "windows-link", + "windows-link 0.1.3", "windows-threading", ] @@ -3709,6 +3721,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + [[package]] name = "windows-numerics" version = "0.2.0" @@ -3716,7 +3734,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ "windows-core 0.61.2", - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -3734,7 +3752,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -3753,7 +3771,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] @@ -3792,6 +3810,15 @@ dependencies = [ "windows-targets 0.53.3", ] +[[package]] +name = "windows-sys" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +dependencies = [ + "windows-link 0.2.0", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -3829,7 +3856,7 @@ version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ - "windows-link", + "windows-link 0.1.3", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", @@ -3846,7 +3873,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" dependencies = [ - "windows-link", + "windows-link 0.1.3", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 7acd52d..32e2afc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ name = "clippyboard-select" [dependencies] ciborium = "0.2.2" +ctrlc = "3.5.0" dirs = "6.0.0" eframe = "0.32.2" egui_extras = { version = "0.32.2", features = ["image"] } diff --git a/shell.nix b/shell.nix index a7c67b4..461ce06 100644 --- a/shell.nix +++ b/shell.nix @@ -12,6 +12,8 @@ pkgs.mkShell rec { libxkbcommon ]; + CLIPPYBOARD_SOCKET = "./clippyboard.socket"; + LD_LIBRARY_PATH = builtins.foldl' (a: b: "${a}:${b}/lib") "${pkgs.vulkan-loader}/lib" buildInputs; } diff --git a/src/daemon.rs b/src/daemon.rs index c42e6cd..cd972dd 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -175,23 +175,47 @@ impl Dispatch for WlState { .expect("missing InProgressOffer data for ExtDataControlOfferV1"); let mime_types = offer_data.mime_types.lock().unwrap(); + + let has_password_manager_hint = + mime_types.contains("x-kde-passwordManagerHint"); + let Some(mime) = MIME_TYPES.iter().find(|mime| mime_types.contains(**mime)) else { warn!( "No supported mime type found. Found mime types: {:?}", - offer_data.mime_types + mime_types ); return; }; drop(mime_types); + let history_state = state.shared_state.clone(); + let time = offer_data.time; + let (reader, writer) = std::io::pipe().unwrap(); offer.receive(mime.to_string(), writer.as_fd()); - let history_state = state.shared_state.clone(); - let mime = mime.to_string(); - let time = offer_data.time; + let password_manager_hint_reader = if has_password_manager_hint { + let (reader, writer) = std::io::pipe().unwrap(); + offer.receive(mime.to_string(), writer.as_fd()); + Some(reader) + } else { + None + }; + std::thread::spawn(move || { + if let Some(mut password_manager_hint_reader) = password_manager_hint_reader + { + let mut buf = Vec::new(); + if password_manager_hint_reader.read_to_end(&mut buf).is_ok() + && buf == b"secret" + { + info!("Clipboard entry is marked as secret, not storing it"); + return; + } + } + + let mime = mime.to_string(); let result = read_fd_into_history(&history_state, time, mime, reader); if let Err(err) = result { warn!("Failed to read clipboard: {:?}", err) @@ -394,6 +418,7 @@ fn read_fd_into_history( data_reader .read_to_end(&mut data) .wrap_err("reading content data")?; + let new_entry = HistoryItem { id: history_state .next_item_id @@ -435,6 +460,12 @@ fn read_fd_into_history( } pub fn main(socket_path: &PathBuf) -> eyre::Result<()> { + let socket_path2 = socket_path.clone(); + let _ = ctrlc::set_handler(move || { + cleanup(&socket_path2); + std::process::exit(130); // sigint + }); + let Err(err) = main_inner(socket_path); if let Some(ioerr) = err.downcast_ref::() @@ -495,7 +526,6 @@ pub fn main_inner(socket_path: &PathBuf) -> eyre::Result { ExtDataControlManagerV1::interface().name ); } - rustix::fs::fcntl_setfl(notify_write_recv.as_fd(), OFlags::NONBLOCK).expect("todo"); rustix::fs::fcntl_setfl(conn.as_fd(), OFlags::NONBLOCK).expect("TODO"); diff --git a/src/lib.rs b/src/lib.rs index 3c9fc6f..7274e49 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,10 @@ const MESSAGE_READ: u8 = 1; const MESSAGE_COPY: u8 = 2; pub fn socket_path() -> eyre::Result { + if let Some(path) = std::env::var_os("CLIPPYBOARD_SOCKET") { + return Ok(path.into()); + } + Ok(dirs::runtime_dir() .ok_or_eyre("missing XDG_RUNTIME_DIR")? .join("clippyboard.sock"))