diff --git a/Cargo.lock b/Cargo.lock index 1179a49..88183d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,9 +80,9 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arboard" -version = "3.4.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb4009533e8ff8f1450a5bcbc30f4242a1d34442221f72314bea1f5dc9c7f89" +checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4" dependencies = [ "clipboard-win", "core-graphics", @@ -112,6 +112,150 @@ dependencies = [ "term", ] +[[package]] +name = "async-broadcast" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" +dependencies = [ + "async-lock", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a07789659a4d385b79b18b9127fc27e1a59e1e89117c78c5ea3b806f016374" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "async-signal" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -222,6 +366,19 @@ dependencies = [ "objc2", ] +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + [[package]] name = "buffered-reader" version = "1.3.1" @@ -402,6 +559,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.38" @@ -502,6 +665,15 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "config" version = "0.11.0" @@ -1013,6 +1185,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "endi" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" + [[package]] name = "enum-map" version = "2.7.3" @@ -1033,6 +1211,27 @@ dependencies = [ "syn", ] +[[package]] +name = "enumflags2" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" +dependencies = [ + "enumflags2_derive", + "serde 1.0.209", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "enumset" version = "1.1.5" @@ -1076,6 +1275,27 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "fastrand" version = "2.1.1" @@ -1244,6 +1464,19 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.30" @@ -2473,10 +2706,23 @@ checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.6.0", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.1.1", "libc", ] +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", + "memoffset 0.9.1", +] + [[package]] name = "nom" version = "5.1.3" @@ -2782,6 +3028,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "os_pipe" version = "1.2.1" @@ -2816,6 +3072,12 @@ dependencies = [ "system-deps", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.3" @@ -2902,6 +3164,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pkg-config" version = "0.3.30" @@ -2949,6 +3222,21 @@ dependencies = [ "miniz_oxide 0.7.4", ] +[[package]] +name = "polling" +version = "3.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.4.0", + "pin-project-lite", + "rustix", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -3213,6 +3501,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ripasso-gnome-search-provider" +version = "0.1.0" +dependencies = [ + "arboard", + "ripasso", + "search-provider", + "tokio", + "zbus", + "zeroize", +] + [[package]] name = "ripasso-gtk" version = "0.7.0-alpha" @@ -3356,6 +3656,18 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "search-provider" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8de586207b4f0b88883d27791ea2e8663900fdc78bffb36660bd1eb79f129ba" +dependencies = [ + "futures-channel", + "futures-util", + "serde 1.0.209", + "zbus", +] + [[package]] name = "security-framework" version = "2.11.1" @@ -3511,6 +3823,17 @@ dependencies = [ "serde 1.0.209", ] +[[package]] +name = "serde_repr" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "serde_spanned" version = "0.6.7" @@ -3915,10 +4238,24 @@ dependencies = [ "libc", "mio", "pin-project-lite", + "signal-hook-registry", "socket2", + "tokio-macros", + "tracing", "windows-sys 0.52.0", ] +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio-native-tls" version = "0.3.1" @@ -4046,9 +4383,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.32" @@ -4084,6 +4433,17 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset 0.9.1", + "tempfile", + "winapi", +] + [[package]] name = "unic-langid" version = "0.9.5" @@ -4647,7 +5007,7 @@ dependencies = [ "derive-new", "libc", "log", - "nix", + "nix 0.28.0", "os_pipe", "tempfile", "thiserror", @@ -4698,6 +5058,16 @@ dependencies = [ "rustix", ] +[[package]] +name = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "xi-unicode" version = "0.3.0" @@ -4743,6 +5113,69 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zbus" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix 0.29.0", + "ordered-stream", + "rand", + "serde 1.0.209", + "serde_repr", + "sha1", + "static_assertions", + "tokio", + "tracing", + "uds_windows", + "windows-sys 0.52.0", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +dependencies = [ + "serde 1.0.209", + "static_assertions", + "zvariant", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -4826,3 +5259,40 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zvariant" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" +dependencies = [ + "endi", + "enumflags2", + "serde 1.0.209", + "static_assertions", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index 23e7875..718ee9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ criterion = "0.5.1" members = [ "gtk", "cursive" -] +, "gnome_search_provider"] [[bench]] name = "library_benchmark" diff --git a/gnome_search_provider/Cargo.toml b/gnome_search_provider/Cargo.toml new file mode 100644 index 0000000..2b327a0 --- /dev/null +++ b/gnome_search_provider/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "ripasso-gnome-search-provider" +version = "0.1.0" +edition = "2021" +authors = ["Austin Riba "] + +[dependencies] +arboard = { version = "3.4.1", features = ["wayland-data-control"] } +ripasso = { path = "../", version = "0.7.0-alpha" } +search-provider = "0.10.0" +tokio = { version = "1.40.0", features = ["macros"] } +zbus = { version = "4.4.0", features = ["tokio"] } +zeroize = "1.8.1" diff --git a/gnome_search_provider/README.md b/gnome_search_provider/README.md new file mode 100644 index 0000000..ee4d5ec --- /dev/null +++ b/gnome_search_provider/README.md @@ -0,0 +1,20 @@ +# Ripasso Gnome Search Provider + +This module builds a gnome search provider that allows you to simply start typing for a password in the gnome overview and get results from Ripasso. + +![image](https://github.com/user-attachments/assets/612eb516-cbb1-4e6f-b8c3-046b413a1233) + +Pressing enter when an entry is highlighted will copy it to the clipboard, erasing it after 40 seconds. + +## Installation +Run the `./install.sh` script and restart your Gnome session. The search provider and it's priority can be enabled/disabled in Gnome Settings under Search. + +## Setting a custom PASSWORD_STORE_DIR + +Use `systemctl --user edit org.gnome.Ripasso.SearchProvider.service` +to create an override file that contains the following: + +```ini +[Service] +Environment="PASSWORD_STORE_DIR=/path/to/password-store" +``` diff --git a/gnome_search_provider/conf/org.gnome.Ripasso.SearchProvider.desktop b/gnome_search_provider/conf/org.gnome.Ripasso.SearchProvider.desktop new file mode 100644 index 0000000..e375576 --- /dev/null +++ b/gnome_search_provider/conf/org.gnome.Ripasso.SearchProvider.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Version=1.0 +Categories=GNOME;Security; +Icon=dialog-password +Name=Ripasso +Comment=GNOME Shell search provider for Ripasso +Terminal=true +Type=Application +OnlyShowIn=GNOME; diff --git a/gnome_search_provider/conf/org.gnome.Ripasso.SearchProvider.service.dbus b/gnome_search_provider/conf/org.gnome.Ripasso.SearchProvider.service.dbus new file mode 100644 index 0000000..e1761cd --- /dev/null +++ b/gnome_search_provider/conf/org.gnome.Ripasso.SearchProvider.service.dbus @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.gnome.Ripasso.SearchProvider +Exec=/usr/lib/ripasso-search-provider/ripasso-gnome-search-provider +SystemdService=org.gnome.Ripasso.SearchProvider.service diff --git a/gnome_search_provider/conf/org.gnome.Ripasso.SearchProvider.service.systemd b/gnome_search_provider/conf/org.gnome.Ripasso.SearchProvider.service.systemd new file mode 100644 index 0000000..c80fa99 --- /dev/null +++ b/gnome_search_provider/conf/org.gnome.Ripasso.SearchProvider.service.systemd @@ -0,0 +1,7 @@ +[Unit] +Description=Ripasso Gnome Shell search provider for GNOME + +[Service] +Type=dbus +BusName=org.gnome.Ripasso.SearchProvider +ExecStart=/usr/lib/ripasso-search-provider/ripasso-gnome-search-provider diff --git a/gnome_search_provider/conf/org.gnome.Ripasso.search-provider.ini b/gnome_search_provider/conf/org.gnome.Ripasso.search-provider.ini new file mode 100644 index 0000000..3c4368b --- /dev/null +++ b/gnome_search_provider/conf/org.gnome.Ripasso.search-provider.ini @@ -0,0 +1,5 @@ +[Shell Search Provider] +DesktopId=org.gnome.Ripasso.SearchProvider.desktop +BusName=org.gnome.Ripasso.SearchProvider +ObjectPath=/org/gnome/Ripasso/SearchProvider +Version=2 diff --git a/gnome_search_provider/install.sh b/gnome_search_provider/install.sh new file mode 100755 index 0000000..04c3bb4 --- /dev/null +++ b/gnome_search_provider/install.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -eu -o pipefail +cd "$(dirname "$(realpath "${0}")")" + +DATADIR=${DATADIR:-/usr/share} +LIBDIR=${LIBDIR:-/usr/lib} + +install -Dm 0755 ../target/release/ripasso-gnome-search-provider "${LIBDIR}"/ripasso-search-provider/ripasso-gnome-search-provider + +install -Dm 0644 conf/org.gnome.Ripasso.search-provider.ini "${DATADIR}"/gnome-shell/search-providers/org.gnome.Ripasso.search-provider.ini + +install -Dm 0644 conf/org.gnome.Ripasso.SearchProvider.desktop "${DATADIR}"/applications/org.gnome.Ripasso.SearchProvider.desktop + +install -Dm 0644 conf/org.gnome.Ripasso.SearchProvider.service.dbus "${DATADIR}"/dbus-1/services/org.gnome.Ripasso.SearchProvider.service + +install -Dm 0644 conf/org.gnome.Ripasso.SearchProvider.service.systemd "${LIBDIR}"/systemd/user/org.gnome.Ripasso.SearchProvider.service diff --git a/gnome_search_provider/src/main.rs b/gnome_search_provider/src/main.rs new file mode 100644 index 0000000..8e5a0db --- /dev/null +++ b/gnome_search_provider/src/main.rs @@ -0,0 +1,148 @@ +use arboard::Clipboard; +use ripasso::pass::PasswordStore; +use search_provider::{ResultID, ResultMeta, SearchProvider, SearchProviderImpl}; +use std::{collections::HashMap, path::PathBuf, thread, time}; +use zbus::{blocking::Connection, proxy, zvariant::Value}; +use zeroize::Zeroize; + +#[proxy( + default_service = "org.freedesktop.Notifications", + default_path = "/org/freedesktop/Notifications" +)] +trait Notifications { + #[allow(clippy::too_many_arguments)] + fn notify( + &self, + app_name: &str, + replaces_id: u32, + app_icon: &str, + summary: &str, + body: &str, + actions: &[&str], + hints: HashMap<&str, &Value<'_>>, + expire_timeout: i32, + ) -> zbus::Result; +} + +fn copy_to_clipbard(content: &String) { + let mut clipboard = Clipboard::new().unwrap(); + clipboard.set_text(content).unwrap(); + thread::spawn(|| { + thread::sleep(time::Duration::from_secs(40)); + let mut clipboard = Clipboard::new().unwrap(); + clipboard.set_text(String::new()).unwrap(); + }); +} + +fn send_notification(summary: String, body: String) { + thread::spawn(move || { + let connection = Connection::session().unwrap(); + let proxy = NotificationsProxyBlocking::new(&connection).unwrap(); + let _ = proxy.notify( + "ripasso", + 0, + "dialog-password", + &summary, + &body, + &[], + HashMap::from([("transient", &Value::Bool(true))]), + 4000, + ); + }) + .join() + .unwrap(); +} + +struct Application { + password_store: PasswordStore, +} + +impl SearchProviderImpl for Application { + fn activate_result(&self, identifier: ResultID, terms: &[String], _timestamp: u32) { + let passwords = self.password_store.all_passwords().unwrap_or_default(); + if let Some(password) = passwords.iter().find(|entry| entry.name == identifier) { + if terms[0] == "otp" { + let mut otp = match password.mfa(&self.password_store) { + Ok(otp) => otp, + Err(err) => { + send_notification("OTP Error".to_string(), err.to_string()); + return; + } + }; + copy_to_clipbard(&otp); + otp.zeroize(); + send_notification(identifier, "OTP copied to clipboard".to_string()); + } else { + let mut secret = match password.password(&self.password_store) { + Ok(secret) => secret, + Err(err) => { + send_notification("Password Error".to_string(), err.to_string()); + return; + } + }; + copy_to_clipbard(&secret); + secret.zeroize(); + send_notification(identifier, "Password copied to clipboard".to_string()); + } + } else { + send_notification("Error".to_string(), "Could Not Find Password".to_string()); + } + } + + fn initial_result_set(&self, terms: &[String]) -> Vec { + let search_terms = if terms[0] == "otp" { + &terms[1..] + } else { + terms + }; + + self.password_store + .all_passwords() + .unwrap_or_default() + .iter() + .filter(|entry| { + search_terms + .iter() + .any(|term| entry.name.to_lowercase().contains(&term.to_lowercase())) + }) + .map(|entry| entry.name.to_owned()) + .collect() + } + + fn result_metas(&self, identifiers: &[ResultID]) -> Vec { + identifiers + .iter() + .map(|id| ResultMeta::builder(id.to_owned(), id).build()) + .collect() + } +} + +#[tokio::main] +async fn main() -> zbus::Result<()> { + let home = std::env::var("HOME").expect("Could not determine $HOME"); + let home_path = PathBuf::from(home); + let default_path = match std::env::var("PASSWORD_STORE_DIR") { + Ok(val) => PathBuf::from(val), + Err(_) => [home_path.to_str().unwrap(), ".password-store"] + .iter() + .collect(), + }; + let password_store = PasswordStore::new( + "default", + &Some(default_path), + &None, + &Some(home_path), + &None, + &ripasso::crypto::CryptoImpl::GpgMe, + &None, + ) + .unwrap(); + let app = Application { password_store }; + SearchProvider::new( + app, + "org.gnome.Ripasso.SearchProvider", + "/org/gnome/Ripasso/SearchProvider", + ) + .await?; + Ok(()) +}