#!/bin/sh

# zypp-key 2.0
# Copyright (c) 2020 Arachnos

# Based on zypp-key 1.1
# Copyright (c) 2014 Sorokin Alexei <sor.alexei@meowr.ru>
# You can redistribute this program and/or modify under the terms of 2-clause BSDL.

prog_name="${0##*/}"
prog_version="2.0"

color_reset=`tput sgr0`
color_red=`tput setaf 1`
color_green=`tput setaf 2`
color_ltred=`tput setaf 1; tput bold;`
color_yellow=`tput setaf 3; tput bold;`
color_bold=`tput bold`
OK="[  ${color_green}OK${color_reset}  ]"
FAILED="[${color_ltred}FAILED${color_reset}]"

check_root() {
    [ $UID -eq 0 ] && { return 0; } || { echo "${color_red}Root privileges are required to run this command.${color_reset}" >&2; exit 5; }
}

gpg_list() {
    rpm -qa --nodigest --nosignature --qf "%{VERSION}-%{RELEASE}$1" 'gpg-pubkey*'
    return $?
}

gpg_add() {
    rpm --import "$1"
    return $?
}

gpg_del() {
    rpm -e "gpg-pubkey-$1"
    return $?
}

gpg_del_all() {
    if [ "$1" != "-f" ] && [ "$1" != "--force" ]; then
        echo -e "\nYou are about to delete all keys."
        echo -n "${color_bold}Continue? "
        ask_num=0
        while true; do
            read -p "${color_bold}[y/n/? shows all options] (n): ${color_reset}" choice
            case "$choice" in
                'y'|'Y'|'#1'    ) break
                                  ;;
                'n'|'N'|'#2'|'' ) exit 4
                                  ;;
                '?'             ) echo -e "\n#1 : y\t\t- Yes, accept and proceed with removal of all keys."
                                  echo -e "#2 : n\t\t- No, cancel the operation.\n"
                                  ;;
                *               ) echo -n "${color_red}Invalid answer '$choice'."
                                  [ $ask_num -eq 0 ] && { echo "${color_reset}"; } || { echo " If nothing else works enter '#1' to select the 1st option, '#2' for the 2nd one, ...${color_reset}"; }
                                  ;;
            esac
            ((ask_num++))
            [ $ask_num -gt 9 ] && { echo "${color_red}Too many retries.${color_reset}" >&2; exit 4; }
        done
    fi
    key_count=0
    del_count=0
    error_count=0
    for key in $(gpg_list '\n' | sort); do
        ((key_count++))
        echo "Deleting $key..."
        gpg_del "$key" && { ((del_count++)); echo "$OK"; } || { ((error_count++)); echo "$FAILED"; }
    done
    ret_val=$error_count
    [ $del_count -eq $key_count ] && { del_count="${color_green}${del_count}${color_reset}"; } || { [ $del_count -eq 0 ] && { del_count="${color_red}${del_count}${color_reset}"; } || { del_count="${color_yellow}${del_count}${color_reset}"; } }
    [ $error_count -eq 0 ] && { error_count="${color_green}${error_count}${color_reset}"; } || { error_count="${color_red}${error_count}${color_reset}"; }
    [ $key_count -eq 0 ] && { key_count="${color_red}${key_count}${color_reset}"; } || { key_count="${color_green}${key_count}${color_reset}"; }
    echo -e "\nTotal keys:   $key_count"
    echo "Removed keys: $del_count"
    echo "Errors:       $error_count"
    return $ret_val
}

if [ "$1" = "list" ]; then
    echo "Key ID            | Name"
    echo "------------------+-------------------------------------------------------------"
    command -v awk >/dev/null 2>&1 && \
    { gpg_list ' | %{SUMMARY}\n' | sort | awk '{ print } END { print "\nTotal keys: " NR }' && exit 0 || exit 1; } || \
    { gpg_list ' | %{SUMMARY}\n' | sort && exit 0 || exit 1; }
elif [ "$1" = "add" ]; then
    check_root
    shift
    if [ "$1" = "" ]; then
        echo "${color_red}Too few arguments.${color_reset}" >&2
        echo "At least one file is required." >&2
        exit 3
    fi
    error_count=0
    for key in "$@"; do
        echo "Adding $key..."
        gpg_add "$key" && echo "$OK" || { ((error_count++)); echo "$FAILED"; }
    done
    [ $error_count -eq 0 ] && exit 0 || exit 1
elif [ "$1" = "del" ]; then
    check_root
    shift
    if [ "$1" = "" ]; then
        echo "${color_red}Too few arguments.${color_reset}" >&2
        echo "At least one keyid is required." >&2
        exit 3
    fi
    error_count=0
    for key in "$@"; do
        echo "Deleting $key..."
        gpg_del "$key" && echo "$OK" || { ((error_count++)); echo "$FAILED"; }
    done
    [ $error_count -eq 0 ] && exit 0 || exit 1
elif [ "$1" = "del-all" ]; then
    check_root
    shift
    echo "Deleting all keys..."
    gpg_del_all "$@" && exit 0 || exit 1
elif [ "$1" = "--version" ] || [ "$1" = "-V" ]; then
    echo "zypp-key $prog_version"
elif [ "$1" = "" ] || [ "$1" = "help" ] || [ "$1" = "?" ] || [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
    echo -e "Usage: $prog_name <COMMAND> [ARGUMENTS] [--COMMAND-OPTIONS]\n"
    echo -e "Manage zypper's list of trusted keys.\n"
    echo "  help, ?, --help, -h  Help."
    echo -e "  --version, -V        Output the version number.\n"
    echo "  add <FILE>           Add the key(s) in specified file(s)."
    echo "  del <KEYID>          Remove the specified key(s)."
    echo "  del-all              Remove all keys."
    echo "    --force, -f        Don't show prompt."
    echo "  list                 List keys."
else
    echo "${color_red}Unknown command '$1'.${color_reset}" >&2
    echo "Type '$prog_name help' to get a list of options and commands."
    exit 2
fi
