Skip to content

Commit

Permalink
Clipboard support. Closes #110
Browse files Browse the repository at this point in the history
  • Loading branch information
firecat53 committed Aug 25, 2023
1 parent 8bb3659 commit 6c0a8f8
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 12 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ For full installation documention see the [installation docs][docs/install.md].
1. Python 3.7+
2. [Pykeepass][1] >= 4.0.0 and [pynput][5]
3. Dmenu, Rofi, Wofi, Yofi or Bemenu
4. (optional) Pinentry
5. (optional) xdotool (for X), [ydotool][10] or [wtype][11](for Wayland), [dotool][12] (X or Wayland).
4. xsel or wl-copy
5. (optional) Pinentry
6. (optional) xdotool (for X), [ydotool][10] or [wtype][11](for Wayland), [dotool][12] (X or Wayland).

## Features

- Supports .kdbx databases, not .kdb.
- Auto-type username and/or password on selection. No clipboard copy/paste
involved.
- Auto-type username and/or password on selection. Select to clipboard if
desired (clears clipboard after 30s).
- Background process allows selectable time-out for locking the database.
- Multiple databases can be unlocked and switched on the fly.
- Use a custom [Keepass 2.x style auto-type sequence][6].
Expand All @@ -58,7 +59,7 @@ For full installation documention see the [installation docs][docs/install.md].

## Usage

`keepmenu [-h] [-a AUTOTYPE] [-c CONF_FILE] [-d DATABASE] [-k KEY_FILE] [-t]`
`keepmenu [-h] [-a AUTOTYPE] [-c CONF_FILE] [-C] [-d DATABASE] [-k KEY_FILE] [-t]`

- Run `keepmenu` or bind to keystroke combination.
- Enter database path on first run.
Expand Down
8 changes: 5 additions & 3 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@

## CLI Options

`keepmenu [-h] [-a AUTOTYPE] [-c CONF_FILE] [-d DATABASE] [-k KEY_FILE]`
`keepmenu [-h] [-a AUTOTYPE] [-c CONF_FILE] [-C] [-d DATABASE] [-k KEY_FILE]`

--help, -h Output a usage message and exit.

-a AUTOTYPE, --autotype AUTOTYPE Override autotype sequence in config.ini

-c CONF_FILE, --config CONF_FILE File path to a config file

-C --clipboard, type to clipboard

-d DATABASE, --database DATABASE File path to a database to open, skipping the database selection menu

-k KEY_FILE, --keyfile KEY_FILE File path of the keyfile needed to open the database specified by --database/-d
Expand All @@ -35,8 +37,8 @@
- Add, edit and type TOTP codes. RFC 6238, Steam and custom settings are supported.
Supports TOTP attributes generated by [KeePass2][3], as well as [KeeOtp][4] and [TrayTOTP][5] plugins' [formats][6].
- *Type entries*
- Auto-type username and/or password on selection. No clipboard copy/paste
involved.
- Auto-type username and/or password on selection. Select to clipboard if
desired (clears clipboard after 30s).
- Use a custom [Keepass 2.x style auto-type sequence][1] if you have one defined
(except for character repetition and the 'special commands'). Set it per entry
or set a global default. Disable autotype for an entry, if desired.
Expand Down
7 changes: 5 additions & 2 deletions keepmenu.1
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ of Keepass databases.
.SH SYNOPSIS
.PP
\f[B]keepmenu\f[R] [\f[B]\[en]autotype\f[R] pattern]
[\f[B]\[en]config\f[R] file] [\f[B]\[en]database\f[R] file]
[\f[B]\[en]keyfile\f[R] file] [\f[B]\[en]totp\f[R]]
[\f[B]\[en]config\f[R] file] [\f[B]\[en]clipboard\f[R]]
[\f[B]\[en]database\f[R] file] [\f[B]\[en]keyfile\f[R] file]
[\f[B]\[en]totp\f[R]]
.SH DESCRIPTION
.PP
\f[B]Keepmenu\f[R] is a fast and minimal application to facilitate
Expand All @@ -40,6 +41,8 @@ Overrides global default from config.ini for current database.
.PP
\f[B]-c\f[R], \f[B]\[en]config\f[R] Path to config file
.PP
\f[B]-C\f[R], \f[B]\[en]clipboard\f[R] Select to clipboard
.PP
\f[B]-d\f[R], \f[B]\[en]database\f[R] Path to Keepass database
.PP
\f[B]-k\f[R], \f[B]\[en]keyfile\f[R] Path to keyfile
Expand Down
4 changes: 3 additions & 1 deletion keepmenu.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ keepmenu - Fully featured Dmenu/Rofi frontend for autotype and managing of Keepa

# SYNOPSIS

**keepmenu** [**--autotype** pattern] [**--config** file] [**--database** file] [**--keyfile** file] [**--totp**]
**keepmenu** [**--autotype** pattern] [**--config** file] [**--clipboard**] [**--database** file] [**--keyfile** file] [**--totp**]

# DESCRIPTION

Expand All @@ -26,6 +26,8 @@ Passhole, but is more dmenu and less command line focused.

**-c**, **--config** Path to config file

**-C**, **--clipboard** Select to clipboard

**-d**, **--database** Path to Keepass database

**-k**, **--keyfile** Path to keyfile
Expand Down
6 changes: 6 additions & 0 deletions keepmenu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
SEQUENCE = "{USERNAME}{TAB}{PASSWORD}{ENTER}"
MAX_LEN = 24
CONF = configparser.ConfigParser()
CLIPBOARD = False


def reload_config(conf_file = None): # pylint: disable=too-many-statements,too-many-branches
Expand All @@ -43,6 +44,7 @@ def reload_config(conf_file = None): # pylint: disable=too-many-statements,too-
# pragma pylint: disable=global-statement,global-variable-not-assigned
global CACHE_PERIOD_MIN, \
CACHE_PERIOD_DEFAULT_MIN, \
CLIPBOARD_CMD, \
CONF, \
MAX_LEN, \
ENV, \
Expand Down Expand Up @@ -95,5 +97,9 @@ def reload_config(conf_file = None): # pylint: disable=too-many-statements,too-
dmenu_err(f"{typ} not installed.\n"
"Please install or remove that option from config.ini")
sys.exit()
if os.environ.get('WAYLAND_DISPLAY'):
CLIPBOARD_CMD = 'wl-copy'
else:
CLIPBOARD_CMD = 'xsel'

# vim: set et ts=4 sw=4 :
10 changes: 10 additions & 0 deletions keepmenu/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,15 @@ def main():
help="File path to a config file",
)

parser.add_argument(
"-C",
"--clipboard",
action="store_true",
default=False,
required=False,
help="Copy values to clipboard instead of typing.",
)

parser.add_argument(
"-d",
"--database",
Expand All @@ -199,6 +208,7 @@ def main():
)

args = vars(parser.parse_args())
keepmenu.CLIPBOARD = args.get('clipboard', False)

port, auth = get_auth()
if port_in_use(port) is False:
Expand Down
8 changes: 8 additions & 0 deletions keepmenu/keepmenu.py
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ def dmenu_run(self, totp_mode=False):
i for i in self.database.kpo.entries if not
any(j in "/".join(i.path[:-1]) for j in hid_groups)
]
clip = "Clipboard off" if keepmenu.CLIPBOARD is True else "Clipboard"
options = {
'View/Type Individual entries':
functools.partial(self.menu_view_type_individual_entries, hid_groups),
Expand All @@ -389,6 +390,7 @@ def dmenu_run(self, totp_mode=False):
'Manage groups': self.menu_manage_groups,
'Reload database': self.menu_reload_database,
'Open/create another database': self.menu_open_another_database,
clip: self.menu_clipboard,
'Kill Keepmenu daemon': self.menu_kill_daemon,
}
if self.prev_entry is None:
Expand Down Expand Up @@ -505,6 +507,12 @@ def menu_open_another_database(self, **kwargs):
self.expiring = get_expiring_entries(self.database.kpo.entries)
self.dmenu_run(self.database.totp)

def menu_clipboard(self):
"""Process menu entry - Toggle clipboard entry
"""
keepmenu.CLIPBOARD = not keepmenu.CLIPBOARD

def menu_kill_daemon(self):
"""Process menu entry - Kill keepmenu daemon
Expand Down
22 changes: 21 additions & 1 deletion keepmenu/type.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# pylint: disable=import-outside-toplevel
import re
from subprocess import call, PIPE, run
from threading import Timer
import time

import keepmenu
Expand Down Expand Up @@ -98,7 +99,12 @@ def type_entry(entry, db_autotype=None):
"""
sequence = keepmenu.SEQUENCE

if keepmenu.CLIPBOARD is True:
if entry.password:
type_clipboard(entry.password)
else:
dmenu_err("Clipboard is active. 'View/Type Individual entries' and select field to copy")
return
if hasattr(entry, 'autotype_enabled') and entry.autotype_enabled is False:
dmenu_err("Autotype disabled for this entry")
return
Expand Down Expand Up @@ -338,6 +344,9 @@ def type_text(data):
"""Type the given text data
"""
if keepmenu.CLIPBOARD is True:
type_clipboard(data)
return
library = 'pynput'
if keepmenu.CONF.has_option('database', 'type_library'):
library = keepmenu.CONF.get('database', 'type_library')
Expand All @@ -360,3 +369,14 @@ def type_text(data):
except kbd.InvalidCharacterException:
dmenu_err("Unable to type string...bad character.\n"
"Try setting `type_library = xdotool` in config.ini")


def type_clipboard(text):
"""Copy text to clipboard and clear clipboard after 30 seconds
Args: text - str
"""
run([keepmenu.CLIPBOARD_CMD], input=text.encode(keepmenu.ENC))
clear = Timer(30, lambda: run([keepmenu.CLIPBOARD_CMD, "--clear"]))
clear.start()

0 comments on commit 6c0a8f8

Please sign in to comment.