#!/bin/bash -pe
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright 2024, Gerrit-John Los <los@lugons.org>

prog="${0##*/}"
default_timeout=5s

secstore=~/opt/etc/"$prog"
cd "$secstore"

show_usage() {
	cat <<-EOT 1>&2
	usage: $prog [-q|-e|-r|-l] [-C] [-t TIMEOUT] SECLABEL
	       $prog {h|-l}
	   -h: show this help
	   -l: list configured SECLABELs
	   -q: query SECLABEL
	   -e: add or edit a SECLABEL
	   -r: remove SECLABEL
	   -C: work around a chrome bug for query mode
	   -t: set timeout for xclip (default: $default_timeout)
	EOT
}

show_help() {
	show_usage
	cat <<-EOT 1>&2

	  A SECLABEL is an encrypted file containing lines with credential
	  data, with an optional leading tag.  The first empty tag is assumed to
	  be 'user', the second 'password'.

	  In query mode (the default) credentials are placed in turn into a one-time
	  paste buffer while the tag is shown on stdout.  If the data isn't pasted
	  within the timeout '$prog' aborts.

	  To abort editing a SECLABEL exit the editor with the tmpfile empty.

	  Chrome has trouble to count to one, and reads the cut-buffer twice to
	  get at its content.  Use '-C' to enable a workaround for this broken
	  behaviour.
	EOT
}

usage() { show_usage ; exit 1 ; }

timeout=$default_timeout
list=false
mode=''
workaround=''
while getopts "hlaert:C" opt ;do
	case "$opt" in
		h)   show_help ;;
		l)   list=true ;;
		q)   mode=query ;;
		a|e) mode=edit ;;
		r)   mode=remove ;;
		t)   timeout="$OPTARG" ;;
		C)   workaround=chrome ;;
		--) break ;;
		*) usage ;;
	esac
done
shift $((OPTIND-1))

if $list ;then
	ls "${secstore}"
	if [ -z "$mode" -a $# -eq 0 ] ;then
		exit 0
	fi
fi
[ -n "$mode" ] || mode=query
[ $# -eq 1 ] || usage
SECLABEL="$1"
[[ "$SECLABEL" != */* ]] || usage

case "$mode" in
	edit)
		passfile="${secstore}/$SECLABEL"
		trap "rm -f '${passfile}.tmp' || true" EXIT
		[ ! -e "${passfile}" ] || cp "${passfile}" "${passfile}.tmp"
		vi "${passfile}.tmp"
		if [ -s "${passfile}.tmp" ] ;then
			mcrypt "${passfile}.tmp" ||
				mcrypt "${passfile}.tmp" &&
				mv "${passfile}.tmp.nc" "${passfile}"
		fi
	;;
	query)
		: <"$secstore/$SECLABEL"

		case "$workaround" in
			chrome) xclip_opts=(-C -t "$timeout") ;;
			*) xclip_opts=(-t "$timeout") ;;
		esac

		echo -n "$1: "
		{
			mcrypt -q -d <"$secstore/$1" ||
			mcrypt -q -d <"$secstore/$1"
		} |xclip-credentials "${xclip_opts[@]}"
	;;
	remove)
		rm -v "$secstore/$SECLABEL"
	;;
	*)
		echo "${0##/}: $mode: not implemented yet" 1>&2
		exit 1
	;;
esac

