From 477566a076085442b313abc530260b5cd40b86b0 Mon Sep 17 00:00:00 2001 From: Q Date: Sun, 9 Mar 2025 15:20:32 +0200 Subject: [PATCH] simple but colorful pw asking --- bin/qaskpass | 1 + shell/qaskpass | 124 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 120000 bin/qaskpass create mode 100755 shell/qaskpass diff --git a/bin/qaskpass b/bin/qaskpass new file mode 120000 index 0000000..dbc6e63 --- /dev/null +++ b/bin/qaskpass @@ -0,0 +1 @@ +../shell/qaskpass \ No newline at end of file diff --git a/shell/qaskpass b/shell/qaskpass new file mode 100755 index 0000000..9f46a65 --- /dev/null +++ b/shell/qaskpass @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 + +import curses +import os +import sys +import termios +import tty +import argparse + +class getch: + def get(self): + fd = sys.stdin.fileno() + old_settings = termios.tcgetattr(fd) + try: + tty.setraw(sys.stdin.fileno()) + ch = sys.stdin.read(1) + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + return ch + +def get_opts(): + parser = argparse.ArgumentParser( + description='Colorful password dialog', + epilog="Dialog printed to stderr, user input echoed to stdout, i.e. input=$( qaskpass )") + + parser.add_argument('--title','-t', action='store', default=None, + help="Title for dialog") + parser.add_argument('-w', action='store', type=int, default=5, + help="Width of display area. 0 to disable display.") + + parser.add_argument('--no-color', action='store_true', default=False, + help="Disable colors") + + args = parser.parse_args() + return args + + + + +def termsize(): + rows, columns = os.popen("stty size", "r").read().split() + return (int(rows), int(columns)) + + +class bc: + m = "\033[95m" + b = "\033[94m" + g = "\033[92m" + y = "\033[93m" + r = "\033[91m" + c = "\033[96m" + B = "\033[1m" + z = "\033[0m" + + def disable(self): + for x in "rgbcmyBz": + setattr(self, x, "") + + +def animchar(i, pos, colorpos, width,c): + if i < 0: + return " " + if pos == colorpos: + clr = c.c + else: + if i < 10: + clr = c.r + elif i < 20: + clr = c.y + else: + clr = c.g + return clr + "▁▂▃▄▅▆▇█▇▆▅▄▃▂"[int(i / width) % 14] + + +def pquit(s="", e=0): + print("", file=sys.stderr) + print(s, end="", file=sys.stdout if e == 0 else sys.stderr) + sys.exit(e) + + +if __name__ == "__main__": + + opts = get_opts() + # 3= ctrl-c, 13=enter + # 127 = backspace + ch = getch() + user_input = "" + display = "**** ****" + c = bc() + if opts.no_color: + c.disable() + if opts.title: + print(f"{c.y}{c.B}{opts.title}{c.z}", file=sys.stderr) + while True: + + try: + if opts.w>0: + colorpos = len(user_input) % opts.w + display = c.m + "•••• " + for i in range(opts.w): + display += animchar(len(user_input) - i, i, colorpos,opts.w,c) + display += c.m + " ••••" + c.z + print("\r" + display, file=sys.stderr, end="") + sys.stderr.flush() + key = ch.get() + + if ord(key) == 3: # ctrl-c + pquit(e=1) + if ord(key) == 13: # enter + pquit(user_input, e=0) + if ord(key) == 27: # esc (also starts control characters + key = ch.get() + if ord(key) == 27: + pquit(e=1) + continue + if ord(key) == 127: # backspace + user_input = user_input[0:-1] + else: + user_input += key + # ~ print(f'-{key}-',file=sys.stderr) + # ~ print(f'-{ord(key)}-',file=sys.stderr) + + except Exception as e: + pquit(s=str(e),e=1)