Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add time delay for key strokes in type command #64

Merged
merged 3 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions MANUAL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ COMMANDS
show [-h] [--field FIELD] [--totp] PATH
Show the contents of an entry, where *PATH* is the full path to the entry. The password field is spoilered and must be highlighted to reveal the plaintext password. Use --field *FIELD* to print only the specified field, where *FIELD* is one of 'title', 'username', 'password', 'url', or a custom field. The --totp option will parse any OTP URIs and print the code.

type [-h] [--prog PROG] [--tabbed] [--totp] [--xdotool] [--username] [name]
Automatically type out the password as if the user had typed it on the keyboard, where *PROG* is a dmenu-like program for selecting an entry. *PROG* defaults to 'dmenu'. This is useful when you want to automatically fill a selected password field in any application. *name* is the name of the database to type from. If not given, type from all databases. Use the --tabbed option to type out the username then password, separated by a tab. Use the --totp option to generate and type otp using 'otp' attribute. Use the --username option to show entry username in parenthesis during selection. Use the --xdotool option to use xdotool instead of the Python keyboard library. Useful for handling unicode input. Note that this command is intended to be invoked via keyboard shortcut.
type [-h] [--prog PROG] [--tabbed] [--totp] [--xdotool] [--username] [--duration TIME] [--delay TIME] [name]
Automatically type out the password as if the user had typed it on the keyboard, where *PROG* is a dmenu-like program for selecting an entry. *PROG* defaults to 'dmenu'. This is useful when you want to automatically fill a selected password field in any application. *name* is the name of the database to type from. If not given, type from all databases. Use the --tabbed option to type out the username then password, separated by a tab. Use the --totp option to generate and type otp using 'otp' attribute. Use the --username option to show entry username in parenthesis during selection. Use the --xdotool option to use xdotool instead of the Python keyboard library. Useful for handling unicode input. Use --duration to specify the time in seconds for which a key should be pressed when typing (defaults to 0.012) and --delay to set the time between to separate key strokes. Note that this command is intended to be invoked via keyboard shortcut.

add [-h] [-w [LENGTH] | -a [LENGTH] | -s [LENGTH]] [--append STR] [--fields FIELD1,...] PATH
Add a new entry/group to the database, where *PATH* is the full path to the entry or group. Use -w, -a, or -s to generate a `correct horse battery staple`_, alphanumeric, or alphanumeric + symbolic password, respectively. *LENGTH* defaults to 5 words for -w and 32 characters for -a and -s unless otherwise specified. Use --append to append *STR* to the end of the generated password to meet specific password requirements. Use --fields to specify a comma separated list of custom fields to prompt for during entry creation.
Expand Down
37 changes: 35 additions & 2 deletions passhole/passhole.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,35 @@ def prompt_open(
c[default_section].get('cache-timeout', cache_timeout)
)

def type_string(k, s, stroke_duration=0.012, stroke_delay=0.0):
"""Type out a string using pynput

Prints the given string using the keyboard with specific delays
between actions.

Parameters
----------
k : Controller
Keyboard controller object
s : string
String to send to keyboard
stroke_duration : float , optional
Duration of a key press, defaults to 12 ms (like xdotool)
stroke_delay : float, optional
Delay between two separate key strokes, defaults to 0 ms
"""
from time import sleep
for i, character in enumerate(s):
try:
k.press(character)
if stroke_duration > 0.0:
sleep(stroke_duration)
k.release(character)
if stroke_delay > 0.0:
sleep(stroke_delay)

except (ValueError, k.InvalidKeyException):
raise k.InvalidCharacterException(i, character)

def type_entries(args):
"""Type out password using keyboard
Expand Down Expand Up @@ -675,7 +704,9 @@ def call_xdotool(args):
call_xdotool(['type', selected_entry.username])
call_xdotool(['key', 'Tab'])
else:
k.type(selected_entry.username)
# FIXME - replace with `k.type` when pynput PR is merged https://github.com/moses-palmer/pynput/pull/579
type_string(k, selected_entry.username, args.duration, args.delay)

k.press(Key.tab)
k.release(Key.tab)
else:
Expand All @@ -685,7 +716,7 @@ def call_xdotool(args):
if args.xdotool:
call_xdotool(['type', selected_entry.password])
else:
k.type(selected_entry.password)
type_string(k, selected_entry.password, args.duration, args.delay)
else:
log.warning("Selected entry does not have a password")

Expand Down Expand Up @@ -1197,6 +1228,8 @@ def create_parser():
type_parser.add_argument('--totp', action='store_true', default=False, help="type entry TOTP")
type_parser.add_argument('--xdotool', action='store_true', default=False, help="use xdotool for typing passwords")
type_parser.add_argument('--username', action='store_true', default=False, help="show username in parenthesis during selection")
type_parser.add_argument('--duration', type=float, default=0.012, help="how long a typed key will be pressed in seconds")
type_parser.add_argument('--delay', type=float, default=0.0, help="the delay between two key presses in seconds")
type_parser.set_defaults(func=type_entries)

# process args for `init` command
Expand Down