From 93b305909047c9e7deaea107562c5968bb47294c Mon Sep 17 00:00:00 2001 From: Simon Bruder Date: Sat, 15 Jun 2019 11:16:15 +0000 Subject: [PATCH] [passff] add --- .../native-messaging-hosts/passff.json | 7 ++ home/bin/passff.py | 115 ++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 home/.mozilla/native-messaging-hosts/passff.json create mode 100755 home/bin/passff.py diff --git a/home/.mozilla/native-messaging-hosts/passff.json b/home/.mozilla/native-messaging-hosts/passff.json new file mode 100644 index 0000000..4aba5ef --- /dev/null +++ b/home/.mozilla/native-messaging-hosts/passff.json @@ -0,0 +1,7 @@ +{ + "name": "passff", + "description": "Host for communicating with zx2c4 pass", + "path": "/home/simon/bin/passff.py", + "type": "stdio", + "allowed_extensions": [ "passff@invicem.pro" ] +} diff --git a/home/bin/passff.py b/home/bin/passff.py new file mode 100755 index 0000000..74915f2 --- /dev/null +++ b/home/bin/passff.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +""" + Host application of the browser extension PassFF + that wraps around the zx2c4 pass script. +""" + +import json +import os +import struct +import subprocess +import sys + +VERSION = "1.2.1" + +############################################################################### +######################## Begin preferences section ############################ +############################################################################### +COMMAND = "pass" +COMMAND_ARGS = [] +COMMAND_ENV = { + "TREE_CHARSET": "ISO-8859-1", + "PATH": "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin", +} +CHARSET = "UTF-8" + +############################################################################### +######################### End preferences section ############################# +############################################################################### + + +def getMessage(): + """ Read a message from stdin and decode it. """ + rawLength = sys.stdin.buffer.read(4) + if len(rawLength) == 0: + sys.exit(0) + messageLength = struct.unpack('@I', rawLength)[0] + message = sys.stdin.buffer.read(messageLength).decode("utf-8") + return json.loads(message) + + +def encodeMessage(messageContent): + """ Encode a message for transmission, given its content. """ + encodedContent = json.dumps(messageContent) + encodedLength = struct.pack('@I', len(encodedContent)) + return {'length': encodedLength, 'content': encodedContent} + + +def sendMessage(encodedMessage): + """ Send an encoded message to stdout. """ + sys.stdout.buffer.write(encodedMessage['length']) + sys.stdout.write(encodedMessage['content']) + sys.stdout.flush() + + +if __name__ == "__main__": + # Read message from standard input + receivedMessage = getMessage() + opt_args = [] + pos_args = [] + std_input = None + + if len(receivedMessage) == 0: + opt_args = ["show"] + elif receivedMessage[0] == "insert": + opt_args = ["insert", "-m"] + pos_args = [receivedMessage[1]] + std_input = receivedMessage[2] + elif receivedMessage[0] == "generate": + opt_args = ["generate"] + pos_args = [receivedMessage[1], receivedMessage[2]] + if "-n" in receivedMessage[3:]: + opt_args.append("-n") + elif receivedMessage[0] == "grepMetaUrls" and len(receivedMessage) == 2: + opt_args = ["grep", "-iE"] + url_field_names = receivedMessage[1] + pos_args = ["^({}):".format('|'.join(url_field_names))] + elif receivedMessage[0] == "otp" and len(receivedMessage) == 2: + opt_args = ["otp"] + key = receivedMessage[1] + key = "/" + (key[1:] if key[0] == "/" else key) + pos_args = [key] + else: + opt_args = ["show"] + key = receivedMessage[0] + key = "/" + (key[1:] if key[0] == "/" else key) + pos_args = [key] + opt_args += COMMAND_ARGS + + # Set up (modified) command environment + env = dict(os.environ) + if "HOME" not in env: + env["HOME"] = os.path.expanduser('~') + for key, val in COMMAND_ENV.items(): + env[key] = val + + # Set up subprocess params + cmd = [COMMAND] + opt_args + ['--'] + pos_args + proc_params = { + 'input': bytes(std_input, CHARSET) if std_input else None, + 'stdout': subprocess.PIPE, + 'stderr': subprocess.PIPE, + 'env': env + } + + # Run and communicate with pass script + proc = subprocess.run(cmd, **proc_params) + + # Send response + sendMessage( + encodeMessage({ + "exitCode": proc.returncode, + "stdout": proc.stdout.decode(CHARSET), + "stderr": proc.stderr.decode(CHARSET), + "version": VERSION + }))