diff --git a/gopass/.local/bin/rofi-gopass b/gopass/.local/bin/rofi-gopass index b6a9224..e39dc1d 100755 --- a/gopass/.local/bin/rofi-gopass +++ b/gopass/.local/bin/rofi-gopass @@ -1,228 +1,116 @@ -#!/bin/bash +#!/usr/bin/env bash +# +# Code originally inspired by https://github.com/carnager/rofi-pass/ -# Code belongs to https://github.com/carnager/rofi-pass/ -# Copyright (C) 2019 carnager +# DEFAULT OPTIONS + +# typing tool used, choice of: +# xdotool | +BACKEND=xdotool + +# the complete typing chain autoentry uses +# possible fields: +# :tab | :space | :enter | username | password +# +# Note that spaces have to be passed explicitly with :space, +# putting a literal ' ' in the chain will not work +# +# By default it enters the username, tabs down, and enters the password +# It does not press return at the end for safety, though you can add +# :return to make it do so. +AUTOENTRY_CHAIN="username :tab password" + +# wait time before entering each input +# in milliseconds +AUTOENTRY_DELAY=20 + +# default key bindings +# Automatically enter username and password +KEY_AUTOENTRY="Return" # rofi wrapper. Add custom settings here. _rofi() { + # TODO add check for dmenu + exist rofi critical "rofi-pass" || exit 0 rofi -dmenu -no-auto-select -i "$@" -theme /themes/dmenu } -# default settings -backend=xdotool -dotool_delay=20 -daemon_wait=2 -autotype_delay=2 -key_autotype="Return" -key_usertype="Alt+2" -key_passtype="Alt+3" -key_actions="Alt+a" -key_clipboard="Alt+1" -key_fieldtype="Return" - -# read config file -get_config_file() { - configs=("$ROFI_PASS_CONFIG" - "$HOME/.config/rofi-pass/rofi-gopass.conf" - "/etc/rofi-gopass.conf") - - # return the first config file with a valid path - for config in "${configs[@]}"; do - # '! -z' is needed in case ROFI_PASS_CONFIG is not set - if [[ ! -z "${config}" && -f "${config}" ]]; then - printf "%s" "$config" - return - fi - done -} - -# Make sure ESC will always end the programm. -# Call this function with "exit_check $?" after each rofi call. +# exit on escape pressed +# rofi returns exit code 1 on esc exit_check() { - exit_value=$1 - if [[ "${exit_value}" == "1" ]]; then - exit - fi + [ "$1" -eq 1 ] && exit } -clipboard() { - local entry - local key - local value - entry="${1}" - key="${2}" - value="$(gopass show "${entry}" "${key}")" - printf '%s' "${value}" | xclip -sel clip - notify-send "rofi-gopass" "Copied ${key} to clipboard\nClearing in 45 seconds." - ( - sleep 45 - printf '%s' "" | xclip - printf '%s' "" | xclip -selection clipboard | notify-send "rofi-gopass" "Clipboard cleared" - ) & - exit -} - -_ydotoold() { - if ! pgrep -x "ydotoold" >/dev/null; then - # ydotoold blocks the terminal, so we need to background it. - # Sadly this way we never know when the process finished starting up. - # Until ydotoold receives proper daemonizing we add a sleep value here. - ydotoold & - sleep "${daemon_wait}" - fi -} - -_dotool() { - local mode - local key - mode="${1}" - key="${2:-null}" - case "${mode}" in - "type") - case "${backend}" in - "xdotool") xdotool type --delay "${dotool_delay}" --file - ;; - "ydotool") - _ydotoold - ydotool type --delay "${dotool_delay}" --file - - ;; - esac - ;; - "key") - case "${backend}" in - "xdotool") xdotool key "${key}" ;; - "ydotool") - _ydotoold - ydotool key "${key}" - ;; - esac - ;; - esac -} - -list_passwords() { +# simply return a list of all passwords in gopass store +# TODO choose password store +# TODO only show website names (+ folder names), and account names for multiple accounts on one site +_gp_list_passwords() { gopass list --flat } -autopass() { - local entry - local autotype - entry="${1}" - autotype="$(gopass show "${entry}" autotype)" - autotype="${autotype:-username :tab pass}" +# return password for argument passed +_gp_show_password() { + gopass show -f --password "$1" +} - for word in ${autotype}; do - case "$word" in - ":tab") _dotool key Tab ;; - ":space") _dotool key " " ;; - ":delay") sleep "${autotype_delay}" ;; - ":enter") _dotool key enter ;; - "pass") printf '%s' "$(gopass show --password "${entry}")" | _dotool type ;; - *) printf '%s' "$(gopass show "${entry}" "${word}")" | _dotool type ;; +GOPASS_USERNAME_ATTEMPTS="username user login" + +# return username for argument passed +_gp_show_username() { + for key in $GOPASS_USERNAME_ATTEMPTS; do + + done + gopass show -f "$1" username || gopass -f show "$1" user || gopass -f show "$1" login +} + +# send password to clipboard +_gp_clip_password() { + gopass show -c "$1" +} + +# invoke the dotool to type inputs +_type() { + local tool + local toolmode + local key + tool="${BACKEND}" + toolmode="$1" + key="$2" + + "$tool" "$toolmode" --delay "$AUTOENTRY_DELAY" "$key" +} + +# automatically enter entry chain, set via AUTOENTRY_CHAIN +# transform special chain entries into valid dotool commands +autoentry() { + local selected + local autoentry_chain + selected="${1}" + autoentry_chain="${AUTOENTRY_CHAIN}" + + for part in $autoentry_chain; do + case "$part" in + ":tab") _type key Tab ;; + ":return") _type key Return ;; + ":space") _type key space ;; + "username") _type type "$(_gp_show_username "$selected")" ;; + "password") _type type "$(_gp_show_password "$selected")" ;; + *) printf '%s' "$part" ;; esac done } -list_keys() { - # gopass has no option to only list keys, so we need to build the list ourselves. - local entry - local keys - entry="${1}" - keys="$(gopass show "${entry}")" - printf '%s\n' "${keys}" | while read -r line; do - if [[ "${line}" == *": "* ]]; then - printf '%s\n' "${line%: *}" - fi - done -} - -edit_key() { - local entry - local keys - entry="${1}" - keys="$(list_keys "${entry}")" - key_name=$(printf '%s\n' "${keys}" | _rofi -mesg "Enter new key or chose existing one") - exit_check $? - value_name=$(printf '%s' "" | _rofi -mesg "Enter Value for key \"${key_name}\"") - exit_check $? - if [[ -z "${key_name}" ]]; then - printf '%s' "${value_name}" | gopass insert -a "${entry}" "${key_name}" - else - printf '%s' "${value_name}" | gopass insert "${entry}" "${key_name}" - fi -} - -# For dangerous operations call this function first. You can provide a message as argument. -# Example: confirm "Are you sure you want to delete entry?" -confirm() { - local message - message="${1}" - confirm_content=( - "Yes" - "No") - - confirm_menu=$(printf '%s\n' "${confirm_content[@]}" | _rofi -mesg "${message}") - exit_check $? - case "${confirm_menu}" in - "Yes") : ;; - "No") exit ;; - esac -} - -custom_type() { - local entry - local keys - entry="${1}" - keys="$(list_keys "${entry}")" - key_name=$(printf '%s\n' "${keys}" | _rofi -kb-accept-entry "" -no-custom -kb-custom-1 "${key_clipboard}" -kb-custom-2 "${key_fieldtype}" -mesg "${key_clipboard}: Copy to Clipboard | ${key_fieldtype}: Type Field") - local exit_value=$? - exit_check "${exit_value}" - case "${exit_value}" in - "10") clipboard "${entry}" "${key_name}" ;; - "11") - printf '%s' "$(gopass show "${entry}" "${key_name}")" | _dotool type - exit - ;; - esac -} - -do_menu() { - local entry - entry="${1}" - action_menu_content=( - "< Go Back" - "---" - "Show Fields" - "Add/Edit Keys" - "Generate New Password" - "Delete Entry" - ) - - action_menu="$(printf '%s\n' "${action_menu_content[@]}" | _rofi -no-custom -mesg "Selected Entry: ${entry}" -p '> ')" - exit_value=$? - exit_check "${exit_value}" - - case "${action_menu}" in - "< Go Back") main ;; - "Show Fields") custom_type "${entry}" ;; - "Add/Edit Keys") edit_key "${entry}" ;; - "Delete Entry") - confirm "Delete ${entry}?" - gopass rm -f "${entry}" - ;; - "Generate New Password") - confirm "Generate a new password for ${entry}?" - gopass generate -f "${entry}" - ;; - esac -} - main() { - entry="$(list_passwords | _rofi -kb-accept-entry "" -kb-custom-1 "${key_autotype}" -kb-custom-2 "${key_usertype}" -kb-custom-3 "${key_passtype}" -kb-custom-4 "${key_actions}" -mesg "${key_autotype}: Autotype | ${key_usertype}: Type User | ${key_passtype}: Type Pass | ${key_actions}: More Actions")" + # entry="$(list_passwords | _rofi -kb-accept-entry "" -kb-custom-1 "${key_autotype}" -kb-custom-2 "${key_usertype}" -kb-custom-3 "${key_passtype}" -kb-custom-4 "${key_actions}" -mesg "${key_autotype}: Autotype | ${key_usertype}: Type User | ${key_passtype}: Type Pass | ${key_actions}: More Actions")" + + entry="$(_gp_list_passwords | _rofi -kb-accept-entry "" -kb-custom-1 "${KEY_AUTOENTRY}")" exit_value=$? + exit_check "${exit_value}" case "${exit_value}" in + # autoentry selected "10") - autopass "${entry}" + autoentry "${entry}" exit ;; "11")