This repository has been archived on 2021-04-06. You can view files and clone it, but cannot push or open issues or pull requests.
dotfiles/home/bin/passff.py
2019-06-15 11:16:15 +00:00

116 lines
3.6 KiB
Python
Executable file

#!/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
}))