summaryrefslogtreecommitdiff
path: root/bin/guiscripts/osurf-fill
blob: 43af80790c13aa1aa1cb330a2c87fa2fb848a472 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/bin/sh

# Fills a password for a given website 
# original script by Avalon Williams (avalonwilliams@protonmail.com)
# This version uses the window id to know the url of the surf window
# and to know which fifo it must use.  Then it injects javascript code.
# that will fill the forms with the credentials

# dependencies:
# - surf fifo patch (http://surf.suckless.org/patches/fifo/)
# - xprop
# - 'pass' with password store in form dir/url/pass.gpg

# $1: winid

fifodir="$HOME/.config/surf/fifo" 
if [ -z "${winid:=$1}" ]
then
    winid="$(osurfls | dmenu -c -F -i | cut -f1 -d' ')"
fi
[ "$winid" ] || exit 1
fifo="$fifodir/$winid"
[ -p "$fifo" ] || exit 2

# Get only domain name + top-level domain
url="$(xprop -id "$winid" _SURF_URI |
	 cut -f 2 -d'"' |
	 sed 's,^.*://\([^/]*\)/.*,\1,' |
	 sed -r -e 's/^([^.]+)\.([^.]+)\.([^.]+)$/\2.\3/')"
[ "$url" ] || exit 3
>&2 printf 'url: %s\n' "$url"

# get pass with url and ask if multiple are found
pass="$({ find $PASSWORD_STORE_DIR/websites/ -type f -name '*.gpg' |
	 grep "$url/" || echo; } | head -n 1 |
	 sed "s,$PASSWORD_STORE_DIR/,,;s/\.gpg$//" |
	 dmenu -c)"
# if dmenu was stopped, exit
[ $? -gt 0 ] && exit 4

# if no password was found, search through password store manually with dmenu
if [ -z "$pass" ]
then
 	store="${PASSWORD_STORE_DIR:-$HOME/.password-store}"
 	while [ -d "$store/$file" ]
	do
		choice="$(find "$store/$file" \
			-maxdepth 1 -mindepth 1 \
			-not -name '.*' -type d -printf "%y\t%f\n" -o \
			-not -name '.*' -not -type d -printf "%y\t%f\n" |
			sort -k1 -k2 |
			cut -f 2 | sed 's/\.gpg$//' |
			dmenu -c)"
		[ "$choice" ] || exit 1
		[ -z "$file" ] && file="$choice" || file="$file/$choice"
	done
	pass="$file"
fi
>&2 printf 'pass: %s\n' "$pass"
herbe "filling ${pass#websites/}" &

# Get password and username in variables with only one call to 'pass'
# escape single quotes
eval "$(pass show "$pass" |
	 sed -n "1s/'/'\\\\''/g;1s/.*/password='&'/p;s/^login: \?\(.\+\)/username='\1'/p")"
printf '%s : %s\n' "$username" "$password"

# Escape quotes and backslashes for javascript
javascript_escape() {
    printf '%s' "$1" | sed -s 's,['\''"\\\\],\\\\&,g'
}

js() {
cat <<EOF
    function isVisible(elem) {
        var style = elem.ownerDocument.defaultView.getComputedStyle(elem, null);
        if (style.getPropertyValue("visibility") !== "visible" ||
            style.getPropertyValue("display") === "none" ||
            style.getPropertyValue("opacity") === "0") {
            return false;
        }
        return elem.offsetWidth > 0 && elem.offsetHeight > 0;
    };
    function hasPasswordField(form) {
        var inputs = form.getElementsByTagName("input");
        for (var j = 0; j < inputs.length; j++) {
            var input = inputs[j];
            if (input.type == "password" || input.autocomplete == "password" || input.name == "password") {
                return true;
            }
        }
        return false;
    };
    function loadData2Form (form) {
        var inputs = form.getElementsByTagName("input");
        for (var j = 0; j < inputs.length; j++) {
            var input = inputs[j];
            if (isVisible(input) && (input.type == "text" || input.type == "email")) {
                input.focus();
                input.value = "$(javascript_escape "$username")";
                input.blur();
                console.log("user: $(javascript_escape "$username")")
            }
            if (input.type == "password" || input.name == "password" || input.autocomplete == "password" || input.id == "password" ) {
                input.focus();
                input.value = "$(javascript_escape "$password")";
                input.blur();
                console.log("password: $(javascript_escape "$password")")
            }
            console.log(input)
        }
    };
    var forms = document.getElementsByTagName("form");
    for (i = 0; i < forms.length; i++) {
        if (hasPasswordField(forms[i])) {
            loadData2Form(forms[i]);
	    // forms[i].submit();
        }
    }
EOF
}

printjs() {
    js | sed 's,//.*$,,' | tr '\n' ' '
}

echo "inject $(printjs)" >> "$fifo"