#!/bin/bash

# CHECK IF THE SCRIPT IS BEING RUN AS ROOT
if [ "$EUID" -ne 0 ]; then
	cat <<-EOH
		This script must be run under elevated privileges (root),
		to allow package installation.
		Restarting requesting elevated privileges …

	EOH
	export SUDO_ASKPASS="/usr/bin/ssh-askpass"
	exec sudo -A -- "$0" "$@"
fi

### INIT
PROGRAM="${0#*/}"
OPTIONS_WGET=("-q" "--backups" "0")

SET_PERM_PASS=false
#URL_CONFIG="STUB_CONFIG_URL"
URL_CONFIG="https://rustdesk.rockstable.it/config-base64.txt"
URL_DL_BASE="https://github.com/rustdesk/rustdesk/releases/download"
#VERSION="1.2.6"
VERSION="latest"
PACKAGES_REQ=("jq")


echo "Installation of required packages"
if ! apt install "${PACKAGES_REQ[@]}"; then
	cat <<-EOH
		Installation of required packages failed.
		Please eximine. Exiting …
	EOH
	exit 1
fi

### FUNCTIONS
release_info () {
	local PROJECT="$1"

	URL_API="https://api.github.com/repos/$PROJECT/releases/latest"
	RESPONSE="$(curl --silent "$URL_API")"
	VERSION="$(jq -r .tag_name <<< "$RESPONSE")"
}

genpw () {
	tr -dc 'a-zA-Z0-9' < /dev/urandom \
		| fold -w 24 \
		| head -n 1
}

check_pass () {
	local PASSWORD="$1"
	local RETURN="Password strength:\t"

	RETURN+="$(cracklib-check <<< "$PASSWORD" \
		| cut -f2- -d\ )"
	echo -e "Checking password with cracklib.\n$RETURN\n"

	if ! grep -q "OK" <<< "$RETURN"; then
		echo "Exiting …"
		exit 1
	fi
}

usage () {
	cat <<-EOH
		$PROGRAM [OPTIONS] -- 
		where:
		  --		Breaks option parsing
		  []		optional parameters 
		  OPTIONS are:
		    -h|--help			Print this page
		    -c|--config "CONFIG_BASE64"	Configure rustdesk with reversed base64 json
		    -p[__PASSWORD}|
		    --password[[=]__PASSWORD]	Generate random password or
		                                set optionally specified password
		    -u|--url-config "URL2CFG"	Configure rustdesk from a custom URL
		    -v|--verbose		More detailed output
		    -V|--version		Set version to be downloaded (instead of latest)

		Hints:
		 - When specifying a password in the shell
		   make sure that it is not leaked to the history or to 'ps'.
		   iConsider using something like 'read PASSWORD' and '-p "\$PASSWORD"'.
		 - The parsing of the password demands with the short option '-p'
		   that the __PASSWORD is directly written after the opion.
		   With the long option it may be separated by "="
		   or by a whitespace (as the next argument).
	EOH
}

### CLI OPTION PARSING
TEMP=$(getopt \
	-o 'c:hp::u:vV' \
	--long 'config:,help,password::,verbose,url-config:,version' \
	-n "$PROGRAM" \
	-- "$@")

# shellcheck disable=SC2181
if [ $? -ne 0 ]; then
	echo 'Terminating...' >&2
	exit 1
fi

# Note the quotes around "$TEMP": they are essential!
eval set -- "$TEMP"
unset TEMP

while true; do
	case "$1" in
		'-c'|'--config-base64')
			CONFIG_BASE64="$2"
			shift 2
			continue
		;;
		'-h'|'--help')
			usage
			exit 0
		;;
		'-p'|'--password')
			SET_PERM_PASS=true
			case "$2" in
				'')
					RUSTDESK_PW="$(genpw)"
				;;
				*)
					RUSTDESK_PW="$2"
				;;
			esac
			shift 2
			continue
		;;
		'-u'|'--url-config')
			URL_CONFIG="$2"
			shift 2
			continue
		;;
		'-v'|'--verbose')
			OPTIONS_WGET+=("-v")
			shift
			continue
		;;
		'-V'|'--version')
			VERSION="$2"
			shift 2
			continue
		;;
		'--')
			shift
			break
		;;
		*)
			echo 'Internal error!' >&2
			exit 1
		;;
	esac
done

### SANITY CHECKS
### CHECK VERSION (SEMVER)
if ! grep -qE \
	-e '[0-9]+\.[0-9]+\.[0-9]+(-[0-9])?' \
	-e 'latest' <<< "$VERSION"; then
	cat <<-EOH
		Version string '$VERSION' does not seam to be valid.
		Exiting…
	EOH
	exit 1
fi

### MAKE SURE PASSWORD IS STRONG
$SET_PERM_PASS && check_pass "$RUSTDESK_PW"

### CHECK SECURITY OF CONFIGURATION URL
if ! grep -q '^https://' <<< "$URL_CONFIG"; then
	cat <<-EOH
		URL to rustdesk configuration does not begin with the secure scheme "https://"
		and is therefore insecure. Continue [N/y]?
	EOH
	read -r 'CONFIRM'
	if ! grep -qi '[jyn]' <<< "$CONFIRM"; then
		echo "Wise decision. Exiting …"
		exit 1
	fi
fi

### DETERMINE MACHINE ARCHITECTURE
if type arch >/dev/null; then
	ARCH="$(command arch)"
elif type uname >/dev/null; then
	ARCH="$(command uname -i)"
else
	echo "Unable to determine machine architecture. Exiting…"
	exit 1
fi

# IDENTIFY OS
if [ -f "/etc/os-release" ]; then
	# freedesktop.org and systemd
	. "/etc/os-release"
	OS="$NAME"
	UPSTREAM_ID="${ID_LIKE,,}"

	# FALLBACK TO ID_LIKE IF ID WAS NOT 'ubuntu' OR 'debian'
	if [ "${UPSTREAM_ID}" != "debian" ] \
		&& [ "${UPSTREAM_ID}" != "ubuntu" ]; then
		UPSTREAM_ID="$(echo "${ID_LIKE,,}" \
			| sed 's/\"//g' \
			| cut -d\  -f1)"
	fi

elif type lsb_release >/dev/null 2>&1; then
	OS="$(lsb_release -si)"
elif [ -f "/etc/lsb-release" ]; then
	# FOR SOME VERSIONS OF DEBIAN/UBUNTU WITHOUT THE COMMAND 'lsb_release'
	# shellcheck disable=SC1091
	. "/etc/lsb-release"
	OS="$DISTRIB_ID"
elif [ -f "/etc/debian_version" ]; then
	# OLDER DEBIAN, UBUNTU, ETC.
	OS="Debian"

elif [ -f "/etc/SuSE-release" ]; then
	# OLDER SUSE ETC.
	OS="SuSE"
elif [ -f "/etc/redhat-release" ]; then
	# OLDER RED HAT, CENTOS, ETC.
	OS="RedHat"
else
	# FALL BACK TO UNAME, E.G. "LINUX <VERSION>",
	# ALSO WORKS FOR BSD, ETC.
	OS="$(uname -s)"
fi

### FETCH RELEASE METADATA AND SET VERSION
if [ "$VERSION" == "latest" ]; then
	release_info "rustdesk/rustdesk"
fi

### DOWNLOAD AND INSTALL RUSTDESK
echo "Downloading and installing RustDesk …"
URL_DL_PREFIX="$URL_DL_BASE/$VERSION"
if [ "${ID}" = "debian" ] || \
	 [ "$OS" = "Ubuntu" ] || \
	 [ "$OS" = "Debian" ] || \
	 [ "${UPSTREAM_ID}" = "ubuntu" ] || \
	 [ "${UPSTREAM_ID}" = "debian" ]; then
	PACKAGE="rustdesk-$VERSION-$ARCH.deb"
	URL_DL="$URL_DL_PREFIX/$PACKAGE"
	wget "${OPTIONS_WGET[@]}" "$URL_DL"
	apt-get install -fy "./$PACKAGE" >/dev/null
	RETURN_INSTALL="$?"
elif [ "$OS" = "CentOS" ] || \
	 [ "$OS" = "RedHat" ] || \
	 [ "$OS" = "Fedora Linux" ] || \
	 [ "${UPSTREAM_ID}" = "rhel" ]; then
	PACKAGE="rustdesk-$VERSION.$ARCH.rpm"
	URL_DL="$URL_DL_PREFIX/$PACKAGE"
	wget "${OPTIONS_WGET[@]}" "$URL_DL"
	yum localinstall "./$PACKAGE" -y >/dev/null
	RETURN_INSTALL="$?"
elif [ "$OS" = "SuSE" ] || \
	 [ "${UPSTREAM_ID}" = "suse" ]; then
	PACKAGE="rustdesk-$VERSION.$ARCH-suse.rpm"
	URL_DL="$URL_DL_PREFIX/$PACKAGE"
	wget "${OPTIONS_WGET[@]}" "$URL_DL"
	zypper -n install --allow-unsigned-rpm "./$PACKAGE" >/dev/null
	RETURN_INSTALL="$?"
else
    echo "Unsupported OS"
    # here you could ask the user for permission to try and install anyway
    # if they say yes, then do the install
    # if they say no, exit the script
    exit 1
fi

cleanup () {
	cat <<-EOH

		Cleaning up downloaded package: '$PACKAGE'
	EOH
	[ -n "$PACKAGE" ] && rm "$PACKAGE"
}

trap cleanup EXIT SIGINT

### SCRIPT IF PACKAGE INSTALLATION FAILED
if [ "$RETURN_INSTALL" -eq 0 ]; then
	cat <<-EOH
		RustDesk has been downloaded and installed from the following URL:
		'$URL_DL'
	EOH
else
	cat <<-EOH
		Rustdesk installation failed.
		Maybe a lock is hold on the package management,
		maybe the download link is no longer valid:
		$URL_DL
		Please check. Exiting …
	EOH
	exit 1
fi

# RUN THE RUSTDESK COMMAND WITH "--get-id" 
# AND STORE THE OUTPUT IN THE RUSTDESK_ID VARIABLE
if ! RUSTDESK_ID="$(rustdesk --get-id)"; then
	echo "Failed to get RustDesk ID. Please check. Exiting …"
	exit 1
fi

# SET PERMANENT PASSWORD TO RUSTDESK
if $SET_PERM_PASS; then
	rustdesk --password "$RUSTDESK_PW" &> /dev/null
else
	RUSTDESK_PW=__kept_by_default
fi

### CONFIGURE RUSTDESK WITH REVERSED BASE64 JSON
if grep -qE '^https://' <<< "$URL_CONFIG"; then
	echo -e "\nDownloading RustDesk configuration from:\n'$URL_CONFIG'"
elif ! grep -qE '^http' <<< "$URL_CONFIG"; then
	cat <<-EOH
		Configuration URL seams to be invalid:
		$URL_CONFIG
		Exiting …
	EOH
	exit 1
fi

### DOWNLOAD REVERSED BASE64 CONFIG FROM URL
if [ -z "$CONFIG_BASE64" ]; then
	CONFIG_BASE64="$(curl "$URL_CONFIG" 2>/dev/null)"
fi

### CHECK CONFIGURATION STRING
CONFIG_JSON="$(rev <<< "$CONFIG_BASE64" \
	| base64 -d)"
CONFIG_JSON_PRETTY="$(jq . <<< "$CONFIG_JSON")"

### CHECK CONFIGURATION STRING
if [ "$?" -eq 5 ]; then
	cat <<-EOH
		Configuration seams to be misformatted.
		jq complains with error code 5.
		Exiting …
	EOH
	exit 1
fi

rustdesk --config "$CONFIG_BASE64"

### RESTART SERVICE TO APPLY CONFIGURATION CHANGES
systemctl restart rustdesk.service

### OUTPUT RUSTDESK INFO
cat <<-EOH

	Installation finished successfully. :-)

	Please save the following information to establish a connection
	to your system using a permanent password (if set, unless you don't care).
	The permanent password can be altered any time
	from within the gui or using the following command series:
	read PASSWORD
	sudo --password "\$PASSWORD"
	systemctl restart rustdesk.service
	unset PASSWORD

	RustDesk ID:		'$RUSTDESK_ID'
	Persistent password:	'$RUSTDESK_PW'
	Config BASE64:		'$CONFIG_BASE64' 
	Config JSON:		"$CONFIG_JSON"
	Config JSON pretty:
	$CONFIG_JSON_PRETTY 

	Please make sure to trust the person on the other end!
	Stay focused and ready.
	[TALK AND] BE EXCELLENT TO EACH OTHER!

	We wish you a pleaseant experience.
EOH
