From e9bbc58fe1b54567738bc2720cd0332feb9ff3e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Ko=C4=8D=C3=AD?= Date: Mon, 30 Sep 2019 11:20:52 +0200 Subject: Add surf-pass to access user names and passwords from surf --- Makefile | 2 ++ config.h | 8 ++++++ surf-pass | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ surf.c | 18 +++++++++++- 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100755 surf-pass diff --git a/Makefile b/Makefile index f5a1dfb..435a4df 100644 --- a/Makefile +++ b/Makefile @@ -62,6 +62,8 @@ install: all chmod 755 $(DESTDIR)$(PREFIX)/bin/surf cp -f surf-menu $(DESTDIR)$(PREFIX)/bin chmod 755 $(DESTDIR)$(PREFIX)/bin/surf-menu + cp -f surf-pass $(DESTDIR)$(PREFIX)/bin + chmod 755 $(DESTDIR)$(PREFIX)/bin/surf-pass mkdir -p $(DESTDIR)$(LIBDIR) cp -f libsurf-webext.so $(DESTDIR)$(LIBDIR) chmod 644 $(DESTDIR)$(LIBDIR)/libsurf-webext.so diff --git a/config.h b/config.h index 17af18a..8e11734 100644 --- a/config.h +++ b/config.h @@ -106,6 +106,11 @@ static WebKitFindOptions findopts = WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE | } \ } +/* Pass */ +#define PASS(VAL) { \ + .v = (const char *[]){ "./surf-pass", winid, VAL, NULL } \ +} + /* styles */ /* * The iteration will stop at the first match, beginning at the beginning of @@ -138,6 +143,9 @@ static Key keys[] = { { MODKEY, GDK_KEY_f, spawn, SETPROP("_SURF_FIND", "_SURF_FIND", PROMPT_FIND) }, { MODKEY, GDK_KEY_slash, spawn, SETPROP("_SURF_FIND", "_SURF_FIND", PROMPT_FIND) }, + { MODKEY, GDK_KEY_w, spawn, PASS("NAME") }, + { MODKEY|GDK_SHIFT_MASK, GDK_KEY_w, spawn, PASS("PASS") }, + { 0, GDK_KEY_Escape, stop, { 0 } }, { MODKEY, GDK_KEY_c, stop, { 0 } }, diff --git a/surf-pass b/surf-pass new file mode 100755 index 0000000..ee20f52 --- /dev/null +++ b/surf-pass @@ -0,0 +1,98 @@ +#!/bin/bash +set -e + +usage() { + echo "Usage: $0 XID {NAME|PASS}" >&2 + exit 1 +} + +set_active_value() { + xprop -id "$xid" -f "_SURF_ACTIVE_VALUE" 8s -set "_SURF_ACTIVE_VALUE" "$1" +} + +get_active_value() { + xprop -id "$xid" -notype "_SURF_ACTIVE_VALUE" | sed -nE 's/^_SURF_ACTIVE_VALUE = "(.*)"$/\1/p' +} + +get_uri() { + xprop -id "$xid" -notype "_SURF_URI" | sed -nE 's/^_SURF_URI = "(.*)"$/\1/p' +} + +domain() { + get_uri | awk -F/ '{print $3}' +} + +primary_domain() { + domain | awk -F. '{ print $(NF-1) "." $NF}' +} + +find_pass() { + local postfix="$1" + shift + + array=() + while read -r field; do + local nogpg="${field%.gpg}" + local noprefix="${nogpg#*/.password-store/}" + if [ -n "$noprefix" ]; then + array+=("$noprefix") + fi + done <<<"$(find ~/.password-store/"$postfix" -type f "$@" 2>/dev/null)" +} + +choose_entry() { + if [ "${#array[@]}" -eq 0 ]; then + find_pass + fi + if [ "${#array[@]}" -eq 1 ]; then + echo "${array[0]}" + return + fi + printf '%s\n' "${array[@]}" | dmenu -p 'Pass:' -w "$xid" | head -1 +} + + +pass_name() { + local array + find_pass "$(primary_domain)" + + local entry + entry="$(choose_entry)" + set_active_value "${entry##*/}" +} + +pass_pass() { + local array curname + array=() + curname="$(get_active_value)" + if [ -n "$curname" ]; then + find_pass "$(primary_domain)" -name "$curname" + fi + if [ "${#array[@]}" -eq 0 ]; then + find_pass "$(primary_domain)" + fi + + local entry + entry="$(choose_entry)" + set_active_value "$(pass "$entry")" + set_active_value # Reset value to empty to hide password +} + +####################### + +[ $# -eq 2 ] || usage + + +xid="$1" + +case "$2" in + NAME) + pass_name + ;; + PASS) + pass_pass + ;; + *) + usage + ;; +esac diff --git a/surf.c b/surf.c index f553239..8a1f3d7 100644 --- a/surf.c +++ b/surf.c @@ -35,7 +35,7 @@ #define LENGTH(x) (sizeof(x) / sizeof(x[0])) #define CLEANMASK(mask) (mask & (MODKEY|GDK_SHIFT_MASK)) -enum { AtomFind, AtomGo, AtomUri, AtomLast }; +enum { AtomFind, AtomGo, AtomUri, AtomActiveValue, AtomLast }; enum { OnDoc = WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT, @@ -173,6 +173,7 @@ static void handleplumb(Client *c, const char *uri); static void newwindow(Client *c, const Arg *a, int noembed); static void spawn(Client *c, const Arg *a); static void msgext(Client *c, char type, const Arg *a); +static void activeval(Client *c, const Arg *a); static void destroyclient(Client *c); static void cleanup(void); @@ -328,6 +329,7 @@ setup(void) atoms[AtomFind] = XInternAtom(dpy, "_SURF_FIND", False); atoms[AtomGo] = XInternAtom(dpy, "_SURF_GO", False); atoms[AtomUri] = XInternAtom(dpy, "_SURF_URI", False); + atoms[AtomActiveValue] = XInternAtom(dpy, "_SURF_ACTIVE_VALUE", False); gtk_init(NULL, NULL); @@ -1048,6 +1050,14 @@ spawn(Client *c, const Arg *a) } } +void +activeval(Client *c, const Arg *a) +{ + const char *value = a->v; + + evalscript(c, "document.activeElement.value = '%s';", value); +} + void destroyclient(Client *c) { @@ -1316,6 +1326,12 @@ processx(GdkXEvent *e, GdkEvent *event, gpointer d) a.v = getatom(c, AtomGo); loaduri(c, &a); + return GDK_FILTER_REMOVE; + } else if (ev->atom == atoms[AtomActiveValue]) { + a.v = getatom(c, AtomActiveValue); + if (*(char*)a.v != '\0') + activeval(c, &a); + return GDK_FILTER_REMOVE; } } -- cgit v1.2.3