#!/bin/bash

## Copyright (C) 2020 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@kicksecure.com>
## See the file COPYING for copying conditions.

set -e
set -o pipefail

fail_closed_maybe() {
   if [ "${dist_build_virtualbox}" = 'true' ]; then
     $output_command "$0 ERROR: Variable 'dist_build_virtualbox' is set to 'true', therefore failing closed." >&2
     exit 1
   fi
}

output_more_information() {
   $output_command ""
   $output_command "$0 INFO: This is not about security."
   $output_command "$0 INFO: This is about usability only."
   $output_command "$0 INFO: If you do not need or have no issues with full screen, clipboard sharing, mouse capture or shared folder this can be safely ignored."
   $output_command "$0 INFO: For more information, see:"
   $output_command "https://www.kicksecure.com/wiki/ga"
}

virtualbox_guest_additions_packages_still_installed() {
   $output_command "$0 INFO: VirtualBox guest additions Debian package '$1' already installed."
   $output_command "$0 INFO: Will not install VirtualBox guest additions from package 'virtualbox-guest-additions-iso'."
   $output_command "$0 INFO: This is OK."
   $output_command "$0 INFO: For more information, see:"
   $output_command "https://www.kicksecure.com/wiki/VirtualBox/Guest_Additions#vbox-guest-installer"
   fail_closed_maybe
   exit 0
}

## {{{ taken from https://github.com/dell/dkms/blob/master/dkms_common.postinst

## GPLv2

# Copyright (C) 2002-2005 Flavio Stanchina
# Copyright (C) 2005-2006 Aric Cyr
# Copyright (C) 2007 Mario Limonciello
# Copyright (C) 2009 Alberto Milone

# Get the most recent kernel on Debian based systems. This keeps
# into account both the version and the ABI. If the current kernel
# is the most recent kernel then the function will print a null string.
_get_newest_kernel_debian() {
    NEWEST_KERNEL=
    NEWEST_VERSION=
    NEWEST_ABI=

    for kernel in /boot/config-*; do
        [ -f "$kernel" ] || continue
        KERNEL=${kernel#*-}
        KERNEL_VERSION=${KERNEL%%-*}
        ABI=${KERNEL#*-}
        ABI=${ABI%%-*}

        if [ -z "$NEWEST_KERNEL" ]; then
            # The 1st time get a version which is bigger than $1
            COMPARE_TO=$1
        else
            # Get the biggest version
            COMPARE_TO="$NEWEST_VERSION-$NEWEST_ABI"
        fi

        # if $kernel is greater than $COMPARE_TO
        if [ `dpkg --compare-versions "$KERNEL_VERSION-$ABI" ge "$COMPARE_TO" && printf '%s\n' "yes" || \
              printf '%s\n' "no"` = "yes" ]; then
            NEWEST_KERNEL=$KERNEL
            NEWEST_VERSION=$KERNEL_VERSION
            NEWEST_ABI=$ABI
        fi
    done

    printf '%s\n' "$NEWEST_KERNEL"
}

## }}}

error_handler() {
   $output_command "$0 ERROR: BASH_COMMAND: '$BASH_COMMAND' failed with exit code '$?'." >&2
   $output_command "$0 ERROR: Please search Kicksecure forums and report if required." >&2
   output_more_information
   fail_closed_maybe
   exit 0
}

if test -o xtrace ; then
   output_command='true'
else
   output_command='printf %s\n'
fi

trap error_handler ERR

printf '%s\n' "$0 (part of package 'vm-config-dist') INFO: This is VirtualBox guest additions from Debian package 'virtualbox-guest-additions-iso' installation helper by Kicksecure developers."

if [ "$(id -u)" != "0" ]; then
   $output_command "$0 ERROR: Must run as root. Run:"
   $output_command "sudo $0"
   exit 112
fi

if [ "$dist_build_virtualbox" = "true" ] || [ -f '/var/lib/dist-base-files/live_build' ] || [ "$(systemd-detect-virt)" = "oracle" ]; then
   true "INFO: dist_build_virtualbox=true, or '/var/lib/dist-base-files/live_build' exists, or systemd-detect-virt returned oracle, therefore proceed."
else
   printf '%s\n' "$0 (part of package 'vm-config-dist') INFO: Neither variable 'dist_build_virtualbox=true' is set, nor does '/var/lib/dist-base-files/live_build' exist, nor 'systemd-detect-virt' returned 'oracle', therefore doing nothing, ok."
   exit 0
fi

if ischroot --default-false ; then
   printf '%s\n' "$0 INFO: chroot detected."
   ## /opt/VBoxGuestAdditions-6.1.18/init/vboxadd uses:
   # test -z "${TARGET_VER}" && TARGET_VER=`uname -r`
   #
   #if test -d /lib/modules/"$TARGET_VER"/build; then
   #   setup_modules "$TARGET_VER"
   #   depmod
   #else
   #   info "Kernel headers not found for target kernel $TARGET_VER. \
#Please install them and execute
#/sbin/rcvboxadd setup"
   #fi
   ## Output of `uname -r` is host kernel version.
   ## Not build chroot kernel version.
   ## Therefore building for that version would fail.
   ## Hence, manually setting to correct version.
   TARGET_VER="$(_get_newest_kernel_debian)"
   export TARGET_VER
   printf '%s\n' "$0 INFO: chroot detected. Therefore: export TARGET_VER='$TARGET_VER'"
   if [ "$TARGET_VER" = "" ]; then
      printf '%s\n' "$0 ERROR: variable TARGET_VER is empty. Failing closed. Exit error."
      exit 1
   fi
fi

if package-installed-check "virtualbox-guest-x11" ; then
   virtualbox_guest_additions_packages_still_installed virtualbox-guest-x11
fi
if package-installed-check "virtualbox-guest-utils" ; then
   virtualbox_guest_additions_packages_still_installed virtualbox-guest-utils
fi

if package-installed-check "virtualbox-guest-additions-iso" ; then
   $output_command "$0 INFO: VirtualBox guest additions package 'virtualbox-guest-additions-iso' installed."
else
   $output_command "$0 ERROR: package 'virtualbox-guest-additions-iso' not installed! To install, run:" >&2
   $output_command "sudo apt update" >&2
   $output_command "sudo apt install virtualbox-guest-additions-iso" >&2
   output_more_information
   exit 0
fi

rm -r -f -- /var/cache/vm-config-dist/vbox-guest-additions-extracted-iso
rm -r -f -- /var/cache/vm-config-dist/vbox-guest-additions-extracted-makeself

mkdir -p -- /var/cache/vm-config-dist/vbox-guest-additions-extracted-iso

pushd -- /var/cache/vm-config-dist/vbox-guest-additions-extracted-iso >/dev/null

printf '%s\n' "$0 INFO: Extracting file '/usr/share/virtualbox/VBoxGuestAdditions.iso' (from package 'virtualbox-guest-additions-iso') to folder '/var/cache/vm-config-dist/vbox-guest-additions-extracted-iso' now..."
7z x -o/var/cache/vm-config-dist/vbox-guest-additions-extracted-iso /usr/share/virtualbox/VBoxGuestAdditions.iso >/dev/null

chmod +x -- VBoxLinuxAdditions.run

printf '%s\n' "$0 INFO: Running '/var/cache/vm-config-dist/vbox-guest-additions-extracted-iso/VBoxLinuxAdditions.run --check' now..."
./VBoxLinuxAdditions.run --check >/dev/null

## Could run VBoxLinuxAdditions.run directly but extracting it allows easier debugging in case of failure.
#./VBoxLinuxAdditions.run

## Add new line because './VBoxLinuxAdditions.run --check' did not.
printf '%s\n' ""
printf '%s\n' "$0 INFO: Extracting file '/var/cache/vm-config-dist/vbox-guest-additions-extracted-iso/VBoxLinuxAdditions.run' to folder '/var/cache/vm-config-dist/vbox-guest-additions-extracted-makeself' now..."
./VBoxLinuxAdditions.run --noexec --keep --target /var/cache/vm-config-dist/vbox-guest-additions-extracted-makeself

popd >/dev/null

pushd -- /var/cache/vm-config-dist/vbox-guest-additions-extracted-makeself >/dev/null

installer_exit_code=0

printf '%s\n' "$0 INFO: Running '/var/cache/vm-config-dist/vbox-guest-additions-extracted-makeself/install.sh force force' now..."
./install.sh force force || { installer_exit_code=$? ; true; };

printf '%s\n' "$0 INFO: /var/cache/vm-config-dist/vbox-guest-additions-extracted-makeself/install.sh exited with exit code '$installer_exit_code'."

## /etc/xdg/autostart/vboxclient.desktop competes with /usr/lib/systemd/user/vboxclient-wayland.service
## Therefore deleting it.
## https://forums.whonix.org/t/how-to-enable-shared-clipboard-drag-and-drop-features-inside-virtualbox-with-whonix-lxqt-18-0-8-7/22588/100
rm -f -- /etc/xdg/autostart/vboxclient.desktop

if [ "$installer_exit_code" = 0 ] || [ "$installer_exit_code" = 2 ]; then
   $output_command "$0 INFO: Success, installed VirtualBox guest additions from package 'virtualbox-guest-additions-iso'."
   output_more_information
else
   $output_command "$0 WARNING: Might have failed to install VirtualBox guest additions from package 'virtualbox-guest-additions-iso'."
   $output_command "$0 INFO: You could have a look at the installation log file. Run:"
   $output_command "cat /var/log/vboxadd-install.log"
   output_more_information
   fail_closed_maybe
fi

popd >/dev/null

exit 0
