#!/bin/sh

umask 022

REPOSITORY_URI='https://deb.wormhole.dns.army'
KEYRING='/usr/share/keyrings/wormhole-debian-archive-keyring.gpg'

EXPECTED_KEYRING_SHA256='d14b35688db780dfccd61dd08b8def29bf60fcabeeee67e1d5ae199b49c2ace9'

fail() {
    printf 'wormhole-repository: ERROR: %s\n' "$1" >&2
    exit 1
}

info() {
    printf 'wormhole-repository: %s\n' "$1"
}

TEST_MODE="${WORMHOLE_REPOSITORY_TEST_MODE:-0}"

if [ "$TEST_MODE" = '1' ]; then

    OS_RELEASE="${WORMHOLE_REPOSITORY_OS_RELEASE:-}"
    ARCH="${WORMHOLE_REPOSITORY_ARCH:-}"
    SOURCES_FILE="${WORMHOLE_REPOSITORY_SOURCES_FILE:-}"

    [ -n "$OS_RELEASE" ] ||
        fail 'test mode requires WORMHOLE_REPOSITORY_OS_RELEASE'

    [ -n "$ARCH" ] ||
        fail 'test mode requires WORMHOLE_REPOSITORY_ARCH'

    [ -n "$SOURCES_FILE" ] ||
        fail 'test mode requires WORMHOLE_REPOSITORY_SOURCES_FILE'

else

    [ "$(id -u)" -eq 0 ] ||
        fail 'must run as root'

    OS_RELEASE='/etc/os-release'
    SOURCES_FILE='/etc/apt/sources.list.d/wormhole.sources'

    command -v dpkg >/dev/null 2>&1 ||
        fail 'dpkg command not found'

    command -v sha256sum >/dev/null 2>&1 ||
        fail 'sha256sum command not found'

    ARCH="$(
        dpkg --print-architecture 2>/dev/null
    )"

    [ -n "$ARCH" ] ||
        fail 'cannot determine dpkg architecture'

    [ -f "$KEYRING" ] ||
        fail "archive keyring missing: $KEYRING"

    [ ! -L "$KEYRING" ] ||
        fail "archive keyring must not be a symlink: $KEYRING"

    ACTUAL_KEYRING_SHA256="$(
        sha256sum "$KEYRING" |
            awk '{print $1}'
    )"

    [ "$ACTUAL_KEYRING_SHA256" = "$EXPECTED_KEYRING_SHA256" ] ||
        fail 'archive keyring SHA256 mismatch'
fi

[ -r "$OS_RELEASE" ] ||
    fail "os-release not readable: $OS_RELEASE"

unset \
    ID \
    ID_LIKE \
    NAME \
    PRETTY_NAME \
    VERSION \
    VERSION_ID \
    VERSION_CODENAME \
    UBUNTU_CODENAME

ID=''
ID_LIKE=''
NAME=''
PRETTY_NAME=''
VERSION=''
VERSION_ID=''
VERSION_CODENAME=''
UBUNTU_CODENAME=''

. "$OS_RELEASE" ||
    fail "cannot parse: $OS_RELEASE"

ID="${ID:-}"
ID_LIKE="${ID_LIKE:-}"
NAME="${NAME:-}"
PRETTY_NAME="${PRETTY_NAME:-}"
VERSION="${VERSION:-}"
VERSION_ID="${VERSION_ID:-}"
VERSION_CODENAME="${VERSION_CODENAME:-}"
UBUNTU_CODENAME="${UBUNTU_CODENAME:-}"

SUITE=''
DETECTED_AS=''

if [ "$ID" = 'kicksecure' ] ||
   printf '%s\n' "$NAME $PRETTY_NAME" |
       grep -qi 'kicksecure'
then
    SUITE='kicksecure'
    DETECTED_AS='kicksecure'

elif [ "$TEST_MODE" != '1' ] &&
     {
         [ -f /etc/dpkg/origins/kicksecure ] ||
         dpkg-query \
             -W \
             -f='${Status}' \
             kicksecure-base-files \
             2>/dev/null |
             grep -Fxq 'install ok installed'
     }
then
    SUITE='kicksecure'
    DETECTED_AS='kicksecure'

elif [ "$ID" = 'kali' ] ||
     [ "$VERSION_CODENAME" = 'kali-rolling' ]
then
    SUITE='kali'
    DETECTED_AS='kali'

elif [ "$ID" = 'parrot' ] ||
     printf '%s\n' "$NAME $PRETTY_NAME" |
         grep -qi 'parrot'
then
    SUITE='parrot'
    DETECTED_AS='parrot'

elif [ "$TEST_MODE" != '1' ] &&
     {
         [ -f /etc/parrot-version ] ||
         [ -f /etc/parrot-release ] ||
         dpkg-query \
             -W \
             -f='${Status}' \
             parrot-core \
             2>/dev/null |
             grep -Fxq 'install ok installed'
     }
then
    SUITE='parrot'
    DETECTED_AS='parrot'

elif [ "$ID" = 'linuxmint' ]
then
    DETECTED_AS='linuxmint'

    case "$VERSION_ID" in
        20)
            SUITE='mint-20'
            ;;
        20.1)
            SUITE='mint-20.1'
            ;;
        20.2)
            SUITE='mint-20.2'
            ;;
        20.3)
            SUITE='mint-20.3'
            ;;
        21)
            SUITE='mint-21'
            ;;
        21.1)
            SUITE='mint-21.1'
            ;;
        21.2)
            SUITE='mint-21.2'
            ;;
        21.3)
            SUITE='mint-21.3'
            ;;
        22)
            SUITE='mint-22'
            ;;
        22.1)
            SUITE='mint-22.1'
            ;;
        22.2)
            SUITE='mint-22.2'
            ;;
        22.3)
            SUITE='mint-22.3'
            ;;
        6)
            SUITE='lmde-6'
            DETECTED_AS='lmde'
            ;;
        7)
            SUITE='lmde-7'
            DETECTED_AS='lmde'
            ;;
        *)
            fail \
                "unsupported Linux Mint/LMDE VERSION_ID='$VERSION_ID'"
            ;;
    esac

elif [ "$ID" = 'ubuntu' ]
then
    DETECTED_AS='ubuntu'

    case "$VERSION_ID" in
        20.04)
            SUITE='ubuntu-20.04'
            ;;
        22.04)
            SUITE='ubuntu-22.04'
            ;;
        24.04)
            SUITE='ubuntu-24.04'
            ;;
        25.10)
            SUITE='ubuntu-25.10'
            ;;
        26.04)
            SUITE='ubuntu-26.04'
            ;;
        26.10)
            SUITE='ubuntu-26.10'
            ;;
        27.04)
            SUITE='ubuntu-27.04'
            ;;
        *)
            fail \
                "unsupported Ubuntu VERSION_ID='$VERSION_ID'"
            ;;
    esac

elif [ "$ID" = 'debian' ]
then
    DETECTED_AS='debian'

    case "$VERSION_CODENAME" in
        bookworm)
            SUITE='bookworm'
            ;;
        trixie)
            SUITE='trixie'
            ;;
        forky)
            SUITE='forky'
            ;;
        duke)
            SUITE='duke'
            ;;
        sid)
            SUITE='sid'
            ;;
        *)
            case "$VERSION_ID" in
                12)
                    SUITE='bookworm'
                    ;;
                13)
                    SUITE='trixie'
                    ;;
                14)
                    SUITE='forky'
                    ;;
                15)
                    SUITE='duke'
                    ;;
                sid|unstable)
                    SUITE='sid'
                    ;;
                *)
                    fail \
                        "unsupported Debian release: VERSION_ID='$VERSION_ID' VERSION_CODENAME='$VERSION_CODENAME'"
                    ;;
            esac
            ;;
    esac

else
    fail \
        "unsupported operating system: ID='$ID' VERSION_ID='$VERSION_ID' VERSION_CODENAME='$VERSION_CODENAME'"
fi

[ -n "$SUITE" ] ||
    fail 'internal error: repository suite not selected'

case "$ARCH" in
    amd64)
        ;;
    i386)
        if [ "$SUITE" != 'bookworm' ]; then
            fail \
                "architecture i386 is not published for suite '$SUITE'"
        fi
        ;;
    arm64|armhf|ppc64el|riscv64|s390x)
        fail \
            "architecture '$ARCH' is currently disabled in Wormhole repositories"
        ;;
    *)
        fail \
            "unsupported architecture: '$ARCH'"
        ;;
esac

SOURCE_DIR="$(
    dirname "$SOURCES_FILE"
)"

install -d -m 0755 "$SOURCE_DIR" ||
    fail "cannot create source directory: $SOURCE_DIR"

if [ -L "$SOURCES_FILE" ]; then
    fail \
        "refusing to replace symlink: $SOURCES_FILE"
fi

if [ -e "$SOURCES_FILE" ] &&
   [ ! -f "$SOURCES_FILE" ]
then
    fail \
        "repository source exists but is not a regular file: $SOURCES_FILE"
fi

TMP="$(
    mktemp "${SOURCES_FILE}.tmp.XXXXXX"
)" ||
    fail 'cannot create temporary repository source'

cleanup() {
    if [ -n "${TMP:-}" ] &&
       [ -e "$TMP" ]
    then
        rm -f "$TMP"
    fi
}

trap cleanup 0 1 2 15

cat > "$TMP" <<EOF_SOURCE
Types: deb
URIs: $REPOSITORY_URI
Suites: $SUITE
Components: main
Architectures: $ARCH
Signed-By: $KEYRING
EOF_SOURCE

[ "$?" -eq 0 ] ||
    fail 'cannot write temporary repository source'

chmod 0644 "$TMP" ||
    fail 'cannot set temporary source permissions'

if [ -f "$SOURCES_FILE" ] &&
   cmp -s "$TMP" "$SOURCES_FILE"
then
    rm -f "$TMP"
    TMP=''

    info 'repository configuration already correct'

else

    if [ "$TEST_MODE" != '1' ] &&
       [ -f "$SOURCES_FILE" ]
    then
        BACKUP_DIR='/var/backups/wormhole-repository'

        BACKUP_STAMP="$(
            date +%Y.%m.%d--%H-%M-%S--%s
        )"

        BACKUP="$BACKUP_DIR/wormhole.sources.${BACKUP_STAMP}.$$"

        install -d -m 0755 "$BACKUP_DIR" ||
            fail \
                "cannot create backup directory: $BACKUP_DIR"

        cp -a \
            "$SOURCES_FILE" \
            "$BACKUP" ||
            fail \
                'cannot back up existing repository source'

        info \
            "previous repository source backed up to $BACKUP"
    fi

    mv \
        "$TMP" \
        "$SOURCES_FILE" ||
        fail \
            "cannot install repository source: $SOURCES_FILE"

    TMP=''

    chmod 0644 "$SOURCES_FILE" ||
        fail \
            'cannot set final repository source permissions'

    if [ "$TEST_MODE" != '1' ]; then
        chown root:root "$SOURCES_FILE" ||
            fail \
                'cannot set repository source ownership'
    fi

    info \
        "repository configuration written to $SOURCES_FILE"
fi

trap - 0 1 2 15

printf '%s\n' \
    'WORMHOLE_REPOSITORY_CONFIGURED=YES' \
    "DETECTED_AS=$DETECTED_AS" \
    "OS_ID=$ID" \
    "OS_VERSION_ID=$VERSION_ID" \
    "OS_VERSION_CODENAME=$VERSION_CODENAME" \
    "SUITE=$SUITE" \
    "ARCHITECTURE=$ARCH" \
    "SOURCES_FILE=$SOURCES_FILE" \
    'APT_UPDATE_RUN=NO'

if [ "$TEST_MODE" != '1' ]; then
    printf '\n%s\n' \
        'Wormhole repository configured successfully.' \
        '' \
        'Next:' \
        '  apt update' \
        '  apt install wormhole-domu-template'
fi

exit 0
