Skip to content

Commit 27165c4

Browse files
committed
Merge branch 'master' into feat/otp_uri_export
# Conflicts: # src/utils.rs
2 parents f5102cc + 6228967 commit 27165c4

File tree

9 files changed

+125
-93
lines changed

9 files changed

+125
-93
lines changed

.devcontainer/devcontainer.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"image": "mcr.microsoft.com/devcontainers/universal:2",
3+
"features": {
4+
"ghcr.io/devcontainers/features/rust:1": {
5+
"profile": "default"
6+
},
7+
"ghcr.io/devcontainers/features/python:1": {
8+
"version": "3.11"
9+
}
10+
}
11+
}

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ jobs:
8989
if: matrix.build != 'aarch64-linux'
9090
run: cargo build
9191

92-
- uses: actions/upload-artifact@v3.1.2
92+
- uses: actions/upload-artifact@v3.1.3
9393
with:
9494
name: bins-${{ matrix.build }}
9595
# Two paths, the first for x86_64 jobs, the second for aarch64.

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ jobs:
6666
cp "target/${{ matrix.target }}/release/$BIN_NAME" "dist/"
6767
fi
6868
69-
- uses: actions/upload-artifact@v3.1.2
69+
- uses: actions/upload-artifact@v3.1.3
7070
with:
7171
name: bins-${{ matrix.build }}
7272
path: dist

Cargo.lock

Lines changed: 23 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,29 +27,29 @@ debug = false
2727
strip = "symbols"
2828

2929
[dependencies]
30-
serde_json = "1.0.105"
30+
serde_json = "1.0.107"
3131
serde = { version = "1.0.188", features = ["derive"] }
3232
dirs = "5.0.1"
3333
rpassword = "7.2.0"
3434
data-encoding = "2.4.0"
3535
copypasta-ext = "0.4.4"
3636
zeroize = "1.6.0"
37-
clap = { version = "4.4.2", features = ["derive"] }
37+
clap = { version = "4.4.6", features = ["derive"] }
3838
hmac = "0.12.1"
3939
sha-1 = "0.10.1"
40-
sha2 = "0.10.7"
40+
sha2 = "0.10.8"
4141
chacha20poly1305 = "0.10.1"
4242
rust-argon2 = "2.0.0"
4343
getrandom = "0.2.10"
4444
scrypt = "0.11.0"
45-
aes-gcm = "0.10.2"
45+
aes-gcm = "0.10.3"
4646
hex = "0.4.3"
4747
qrcode = "0.12.0"
4848
urlencoding = "2.1.3"
49-
regex = "1.9.3"
49+
regex = "1.9.6"
5050
once_cell = "1.18.0"
51-
base64 = "0.21.3"
52-
md-5 = "0.10.5"
51+
base64 = "0.21.4"
52+
md-5 = "0.10.6"
5353
ratatui = { version = "0.23.0", features = ["all-widgets"] }
5454
crossterm = "0.27.0"
5555
url = "2.4.1"

src/clipboard.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use base64::{engine::general_purpose, Engine as _};
2+
use copypasta_ext::prelude::*;
3+
#[cfg(target_os = "linux")]
4+
use copypasta_ext::wayland_bin::WaylandBinClipboardContext;
5+
use copypasta_ext::x11_bin::ClipboardContext as BinClipboardContext;
6+
use copypasta_ext::x11_fork::ClipboardContext as ForkClipboardContext;
7+
use crossterm::style::Print;
8+
use std::{env, io};
9+
10+
pub enum CopyType {
11+
Native,
12+
OSC52,
13+
}
14+
15+
pub fn copy_string_to_clipboard(content: String) -> Result<CopyType, ()> {
16+
if ssh_clipboard(content.as_str()) {
17+
Ok(CopyType::OSC52)
18+
} else if wayland_clipboard(content.as_str()) || other_platform_clipboard(content.as_str()) {
19+
Ok(CopyType::Native)
20+
} else {
21+
Err(())
22+
}
23+
}
24+
25+
fn ssh_clipboard(content: &str) -> bool {
26+
env_var_set("SSH_CONNECTION")
27+
// We do not use copypasta_ext::osc52 module because we have enabled terminal raw mode, so we print with crossterm utilities
28+
// Check https://github.com/timvisee/rust-clipboard-ext/blob/371df19d2f961882a21c957f396d1e24548d1f28/src/osc52.rs#L92
29+
&& crossterm::execute!(
30+
io::stdout(),
31+
Print(format!(
32+
"\x1B]52;c;{}\x07",
33+
general_purpose::STANDARD.encode(content)
34+
))
35+
)
36+
.is_ok()
37+
}
38+
#[cfg(target_os = "linux")]
39+
fn wayland_clipboard(content: &str) -> bool {
40+
env_var_set("WAYLAND_DISPLAY")
41+
&& WaylandBinClipboardContext::new()
42+
.and_then(|mut ctx| ctx.set_contents(content.to_owned()))
43+
.is_ok()
44+
}
45+
46+
#[cfg(not(target_os = "linux"))]
47+
fn wayland_clipboard(content: &str) -> bool {
48+
false
49+
}
50+
51+
fn other_platform_clipboard(content: &str) -> bool {
52+
BinClipboardContext::new()
53+
.and_then(|mut ctx| ctx.set_contents(content.to_owned()))
54+
.is_ok()
55+
|| ForkClipboardContext::new()
56+
.and_then(|mut ctx| ctx.set_contents(content.to_owned()))
57+
.is_ok()
58+
}
59+
60+
fn env_var_set(env_var: &str) -> bool {
61+
env::var(env_var)
62+
.map(|v| !v.trim().is_empty())
63+
.unwrap_or(false)
64+
}

src/interface/handler.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
use crate::clipboard::{copy_string_to_clipboard, CopyType};
12
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
23

34
use crate::interface::app::{App, AppResult};
45
use crate::interface::enums::Page::*;
56
use crate::otp::otp_type::OTPType;
6-
use crate::utils::{copy_string_to_clipboard, CopyType};
77

88
use super::app::Popup;
99
use super::enums::Page;
@@ -103,7 +103,7 @@ fn main_handler(key_event: KeyEvent, app: &mut App) {
103103
handle_exit(app);
104104
}
105105
// exit application on Ctrl-D
106-
KeyCode::Char('d') | KeyCode::Char('D') => {
106+
KeyCode::Char('d') | KeyCode::Char('D') | KeyCode::Char('c') => {
107107
if key_event.modifiers == KeyModifiers::CONTROL {
108108
handle_exit(app);
109109
} else if app.table.state.selected().is_some() {

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use zeroize::Zeroize;
1515

1616
mod args;
1717
mod argument_functions;
18+
mod clipboard;
1819
mod crypto;
1920
mod exporters;
2021
mod importers;

src/utils.rs

Lines changed: 15 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,33 @@
1-
use base64::{engine::general_purpose, Engine as _};
2-
use copypasta_ext::prelude::*;
3-
use copypasta_ext::x11_fork::ClipboardContext;
4-
use crossterm::style::Print;
5-
#[cfg(not(debug_assertions))]
61
use dirs::home_dir;
72
use std::path::PathBuf;
83
use std::time::{SystemTime, UNIX_EPOCH};
94
use std::{env, io};
105

11-
pub enum CopyType {
12-
Native,
13-
OSC52,
14-
}
15-
166
pub fn get_db_path() -> PathBuf {
177
match env::var("COTP_DB_PATH") {
188
Ok(value) => PathBuf::from(value),
199
Err(_e) => get_default_db_path(),
2010
}
2111
}
2212

13+
pub fn is_portable_mode() -> bool {
14+
PathBuf::from("db.cotp").exists()
15+
}
16+
2317
// Pushing an absolute path to a PathBuf replaces the entire PathBuf: https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.push
2418
pub fn get_default_db_path() -> PathBuf {
25-
let result: Option<PathBuf> = {
26-
#[cfg(not(debug_assertions))]
27-
{
28-
home_dir()
29-
}
30-
#[cfg(debug_assertions)]
31-
Some(PathBuf::from("."))
32-
};
33-
match result {
34-
Some(home) => home,
35-
None => {
36-
let current_dir = PathBuf::from(".");
37-
if let Some(str_dir) = current_dir.to_str() {
38-
eprintln!("Cannot get home folder, using: {str_dir}");
39-
} else {
40-
eprintln!("Cannot get home folder, using");
41-
}
42-
current_dir
43-
}
19+
let db_from_current_dir = PathBuf::from("./db.cotp");
20+
21+
// If db.cotp is present in the current directory or we are using a debug artifact, do not use the one in home dir
22+
// First condition is optimized away in release mode
23+
if cfg!(debug_assertions) || is_portable_mode() {
24+
return db_from_current_dir;
4425
}
45-
.join(".cotp/db.cotp")
26+
27+
// Take from homedir, otherwise fallback to portable mode
28+
home_dir()
29+
.map(|path| path.join(".cotp/db.cotp"))
30+
.unwrap_or(db_from_current_dir)
4631
}
4732

4833
pub fn init_app() -> Result<bool, ()> {
@@ -94,33 +79,3 @@ pub fn verified_password(message: &str, minimum_length: usize) -> String {
9479
return password;
9580
}
9681
}
97-
98-
fn in_ssh_shell() -> bool {
99-
return env::var("SSH_CONNECTION")
100-
.map(|v| !v.trim().is_empty())
101-
.unwrap_or(false);
102-
}
103-
104-
pub fn copy_string_to_clipboard(content: String) -> Result<CopyType, ()> {
105-
if in_ssh_shell() {
106-
// We do not use copypasta_ext::osc52 module because we have enabled terminal raw mode, so we print with crossterm utilities
107-
// Check https://github.com/timvisee/rust-clipboard-ext/blob/371df19d2f961882a21c957f396d1e24548d1f28/src/osc52.rs#L92
108-
return match crossterm::execute!(
109-
io::stdout(),
110-
Print(format!(
111-
"\x1B]52;c;{}\x07",
112-
general_purpose::STANDARD.encode(content)
113-
))
114-
) {
115-
Ok(_) => Ok(CopyType::OSC52),
116-
Err(_) => Err(()),
117-
};
118-
} else if let Ok(mut ctx) = ClipboardContext::new() {
119-
return if ctx.set_contents(content).is_ok() {
120-
Ok(CopyType::Native)
121-
} else {
122-
Err(())
123-
};
124-
}
125-
Err(())
126-
}

0 commit comments

Comments
 (0)