summaryrefslogtreecommitdiff
path: root/misc/userscripts/qute-1pass
blob: 19e5414a581c828e6f69e0135d64ebce27ab7520 (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
#!/usr/bin/env bash

set +e

# JS field injection code from https://github.com/qutebrowser/qutebrowser/blob/main/misc/userscripts/password_fill
javascript_escape() {
    # print the first argument in an escaped way, such that it can safely
    # be used within javascripts double quotes
    # shellcheck disable=SC2001
    sed "s,[\\\\'\"\/],\\\\&,g" <<< "$1"
}

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") {
                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.dispatchEvent(new Event('change'));
                input.blur();
            }
            if (input.type == "password") {
                input.focus();
                input.value = "$(javascript_escape "${PASSWORD}")";
                input.dispatchEvent(new Event('change'));
                input.blur();
            }
        }
    };
    var forms = document.getElementsByTagName("form");
    if("$(javascript_escape "${QUTE_URL}")" == window.location.href) {
        for (i = 0; i < forms.length; i++) {
            if (hasPasswordField(forms[i])) {
                loadData2Form(forms[i]);
            }
        }
    } else {
        alert("Secrets will not be inserted.\nUrl of this page and the one where the user script was started differ.");
    }
EOF
}

URL=$(echo "$QUTE_URL" | awk -F/ '{print $3}' | sed 's/www.//g')
TOKEN_TMPDIR="${TMPDIR:-/tmp}"
TOKEN_CACHE="$TOKEN_TMPDIR/1pass.token"

echo "message-info 'Looking for password for $URL...'" >> "$QUTE_FIFO"

if [ -f "$TOKEN_CACHE" ]; then
    TOKEN=$(cat "$TOKEN_CACHE")
    if ! op signin --session="$TOKEN" --output=raw > /dev/null; then
        TOKEN=$(rofi -dmenu -password -p "1password: "| op signin --output=raw) || TOKEN=""
        echo "$TOKEN" > "$TOKEN_CACHE"
    fi
else
    TOKEN=$(rofi -dmenu -password -p "1password: "| op signin --output=raw) || TOKEN=""
    install -m 600 /dev/null "$TOKEN_CACHE"
    echo "$TOKEN" > "$TOKEN_CACHE"
fi


if [ -n "$TOKEN" ]; then
    UUID=$(op list items --cache --session="$TOKEN" | jq --arg url "$URL" -r '[.[] | {uuid, url: [.overview.URLs[]?.u, .overview.url][]?} | select(.uuid != null) | select(.url != null) | select(.url|test(".*\($url).*"))][.0].uuid') || UUID="" 

    if [ -z "$UUID" ] || [ "$UUID" == "null" ];then
        echo "message-error 'No entry found for $URL'" >> "$QUTE_FIFO"
        TITLE=$(op list items --cache --session="$TOKEN" | jq -r '.[].overview.title' | rofi -dmenu -i) || TITLE=""
        if [ -n "$TITLE" ]; then
            UUID=$(op list items --cache --session="$TOKEN" | jq --arg title "$TITLE" -r '[.[] | {uuid, title:.overview.title}|select(.title|test("\($title)"))][.0].uuid') || UUID=""
        else
            UUID=""
        fi
    fi

    if [ -n "$UUID" ];then
        ITEM=$(op get item --cache --session="$TOKEN" "$UUID")

        PASSWORD=$(echo "$ITEM" | jq -r '.details.fields | .[] | select(.designation=="password") | .value')

        if [ -n "$PASSWORD" ]; then
            TITLE=$(echo "$ITEM" | jq -r '.overview.title')
            USERNAME=$(echo "$ITEM" | jq -r '.details.fields | .[] | select(.designation=="username") | .value')

            printjs() {
                js | sed 's,//.*$,,' | tr '\n' ' '
            }
            echo "jseval -q $(printjs)" >> "$QUTE_FIFO"

            TOTP=$(echo "$ITEM" | op get totp --cache --session="$TOKEN" "$UUID") || TOTP=""
            if [ -n "$TOTP" ]; then
                echo "$TOTP" | xclip -in -selection clipboard
                echo "message-info 'Pasted one time password for $TITLE to clipboard'" >> "$QUTE_FIFO" 
            fi
        else
            echo "message-error 'No password found for $URL'" >> "$QUTE_FIFO"
        fi
    else
        echo "message-error 'Entry not found for $UUID'" >> "$QUTE_FIFO"
    fi
else
    echo "message-error 'Wrong master password'" >> "$QUTE_FIFO"
fi