#!/bin/bash
# vim:ts=2 sts=2 sw=2 et ai
# shellcheck disable=SC2119 disable=2016
#
# SPDX-License-Identifier: AGPL-3.0-or-later
# SPDX-FileCopyrightText: 2022 grommunio GmbH
# SPDX-FileCopyrightText: 2023-2025 eryx12o45, crpb
# Interactive grommunio setup

# Exit on error - prevents untoward surprises happening
set -e

if [ "$(id -u)" -ne 0 ]; then
  exec sudo "${BASH_SOURCE[0]}"
fi

# Source set up variables and setup-include.sh
. /usr/share/grommunio-pkg-bits/scripts/setup-grommunio-setup

CFG_FILE='/etc/grommunio-setup/grommunio-setup.conf'
PKGED_CFG_FILE='/etc/grommunio-setup/packaged.conf'
PROGNAME=`basename "$0"`

setup_options_debconf () {
	# Appliance setup script, behave like a Debian system
	GSETUP_AUTO_CONFIG="true"
	GSETUP_ADMIN_PASSWORD="$ADMIN_PASS"
	GSETUP_SITE_FQDN="$FQDN"
	GSETUP_DB_HOST="$MYSQL_HOST"
	GSETUP_DB_NAME="$MYSQL_DB"
	GSETUP_DB_USER="$MYSQL_USER"
	GSETUP_DB_PASSWORD="$MYSQL_PASS"
	[ ! "${DEBIAN_HAS_FRONTEND:-}" ] && \
		. /usr/share/grommunio-pkg-bits/scripts/debconf-communicate.sh
	gsetup_preseed
	db_get grommunio-setup/setup-options-select
	local OPT_SELECT="$RET"
	OPT_SELECT=$(echo "$OPT_SELECT" | perl -pe 's/,//')
	# reset dialog questions back to defaults - done here so that
	# debconf choices can be pre-seeded
	setup_debconf_reset
	[ ! "${DEBIAN_HAS_FRONTEND:-}" ] && db_stop

	# Stuff to do things goes here
	local PKG_FIRST=''
	local PKG_SELECT=''
	calc_option_pkg_select -s "$OPT_SELECT" PKG_SELECT PKG_FIRST
	[ -n "$PKG_FIRST" ] && install_packages -S -L "${LOGFILE}" ${PKG_FIRST}
	sleep 3
	if [ -n "$PKG_SELECT" ]; then
		clear # clear screen
		install_packages -A ${PKG_SELECT}
	fi
	GSETUP_OPT_SELECT="${PKG_SELECT}"
}

grommunio_setup_usage () {
	local BLAH="
  $PROGNAME: [-abDhqxX] [-f frontend] [-n db-name] [-p priority] [-t db-host] [-u db-user] [-s pkg-selection] [-z site-fqdn]

"
	echo -n "$BLAH" 1>&2
}

grommunio_setup_vusage () {
	local BLAH="
         -a  --admin-password     Prompt for admin password via /dev/tty
                                  Set GSETUP_ADMIN_PASSWORD to bypass this.
             --acme-server-url    Set the ACME server URL for Lets Encrypt certbot
         -b  --db-password        Prompt for grommunio DB password via /dev/tty
                                  Set GSETUP_DB_PASSWORD to bypass this.
         -D  --no-def-priority    Show all questions, not just default debconf
                                  priority or higher
         -f  --frontend           select debconf frontend to use
         -h  --help               print this help
         -n  --db-name            preseed the shared/grommunio/db-name setting
         -p  --priority           show questions of this priority or higher
         -q  --quiet              quieter apt output, no progress info
         -s  --option-select      option packages to be operated on, comma separated
         -t  --db-host            preseed the shared/grommunio/db-host setting
         -u  --db-user            preseed the shared/grommunio/db-user setting
         -x  --repo-setup         setup up package repository definition
         -X  --no-repo-setup      don't setup package repository definition
         -z  --site-fqdn          preseed the site-fqdn debconf setting

         Debconf frontends available: 'dialog', 'readline', 'noninteractive',
                                      'gnome', 'kde', 'editor', 'web'
         Question priorities: 'criticial', 'high', 'medium' 'low'
         If no question priority is selected all questions are shown (ie
         priority 'low' or higher)

"
	grommunio_setup_usage
	echo -n "$BLAH" 1>&2
}

# setable settings here
NO_APT_SETUP=0
[ -e "$CFG_FILE" ] && . "$CFG_FILE"
# override various settings for packaged setup script
[ -e "$PKGED_CFG_FILE" ] && . "$PKGED_CFG_FILE"
# convert to new variables
GSETUP_REPO_SETUP='true'
[ $NO_APT_SETUP -ne 0 ] && GSETUP_REPO_SETUP='false'

CMD_MODE='setup' CMD_SHORT_ARGS='abDhqxXf:n:p:s:t:u:z:' \
CMD_LONG_ARGS='admin-password,acme-server-url:,db-host:,db-name:,db-password,db-user:,no-def-priority,frontend:,help,,option-select:,priority:,quiet,repo-setup,no-repo-setup,site-fqdn:' \
grommunio_cmd_args "$@"

# Establish lock file if first process
#lock_gsetup_file || true
# set up lock file processing
setup_gsetup_lock_file 'grommunio-setup'

DATADIR="${0%/*}"
if [ "${DATADIR}" = "$0" ]; then
  DATADIR="/usr/share/grommunio-setup"
else
  DATADIR="$(readlink -f "$0")"
  DATADIR="${DATADIR%/*}"
  DATADIR="$(readlink -f "${DATADIR}")"
fi
#APT_EXTRA_ARGS='-qq'
APT_LOGFILE="/var/log/apt/term.log"
LOGFILE="/var/log/grommunio-setup.log"
if ! test -e "$LOGFILE"; then
  true >"$LOGFILE"
  chmod 0600 "$LOGFILE"
fi

apt-get() {
# Remove any stray '-y' as we re-add them below when needed
local  clean_args=()
for arg in "$@"; do
  if [[ "$arg" != "-y" ]]; then
    clean_args+=("$arg")
  fi
done
set -- "${clean_args[@]}"
if [ "$1" = "update" ]; then
  shift
  if ! command apt-get update -qq -y "$@" >> "${LOGFILE}" 2>&1; then
    echo "APT: Update failed."|tee -a "${LOGFILE}"
    echo "Please check the logfile: ${LOGFILE}"|tee -a "${LOGFILE}"
  fi
elif [ "$1" = "dist-upgrade" ]; then
  shift
  if ! command apt-get dist-upgrade -qq -y >/dev/null 2>&1; then
    echo "APT: Dist-Upgrade failed."|tee -a "${LOGFILE}"
    echo "Please check the logfile: ${APT_LOGFILE}"|tee -a "${LOGFILE}"
  fi
elif [ "$1" = "install" ]; then
  shift
  install_packages -S -L "${LOGFILE}" "$@"
fi
}

apt-get update
apt-get install dialog

# shellcheck source=common/helpers
. "${DATADIR}/common/helpers"
# shellcheck source=./common/dialogs
. "${DATADIR}/common/dialogs"
TMPF=$(mktemp /tmp/setup.sh.XXXXXXXX)
trap 'rm -f "$TMPF"' EXIT

writelog "Welcome dialog"
dialog_welcome

# Prevent Apache-Installation
cat <<END > /etc/apt/preferences.d/no-apache
Package: apache2
Pin: release *
Pin-Priority: -1

Package: apache2-bin
Pin: release *
Pin-Priority: -1

Package: libapache2-mod-php
Pin: release *
Pin-Priority: -1
END

writelog "Installing dependencies..."

# make sure necessary packages are installed and up-to-date.
apt-get update
apt-get dist-upgrade
echo "postfix	postfix/mailname string $DOMAIN" | debconf-set-selections
echo "postfix	postfix/main_mailer_type string 'Internet Site'" | debconf-set-selections
SYSTEM_PACKAGES=(mariadb-server mariadb-client redis nginx postfix postfix-lmdb
  postfix-mysql php php-igbinary php-redis sqlite3 php php-fpm curl fetchmail
  rspamd certbot python3-certbot-nginx libsasl2-2 libsasl2-modules sasl2-bin
  jq firewalld clamav clamav-freshclam clamav-daemon ssl-cert
  libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static gpg)
export DEBIAN_FRONTEND=noninteractive
apt-get install "${SYSTEM_PACKAGES[@]}"
unset DEBIAN_FRONTEND

writelog "Disable PHP opcache"
phpdismod opcache >>"${LOGFILE}" 2>&1

if [ -e "/etc/grommunio-common/setup_done" ]; then
  DELCONFIRM=$(dialog --no-mouse --colors --backtitle "grommunio Setup" --title "grommunio Setup already completed" --cr-wrap --inputbox \
    'grommunio Setup was already run.

You can abort or delete all data and setup everything from scratch. If so, confirm this operation by typing "removealldata" to continue.

\Z1If you continue, ALL data wil be removed!\Z1' \
    0 0 3>&1 1>&2 2>&3) && STATUS=$? || STATUS=$?
  dialog_exit $STATUS
  if [ "${DELCONFIRM}" != "removealldata" ]; then
    writelog "Aborted deletion after detected existing installation"
    exit 0
	else
		writelog "Deleting existing installation after confirmation"
		echo "drop database grommunio;" | mysql
		# remove folders etc
		rm -Rf /var/lib/gromox/* \
			/etc/grommunio-common/ssl/* \
			/etc/grommunio-common/setup_done \
			/etc/apt/sources.list.d/grommunio.sources \
			/var/lib/grommunio-web/*

		# recreate them..
		mkdir -p /var/lib/gromox/{domain,user,queue/{cache,mess,save,timer}} \
			/var/lib/grommunio-web/{session,tmp/session,sqlite-index}

		# set permissions
		touch /var/lib/gromox/queue/token.ipc
		chown -Rf gromox:gromox /var/lib/gromox
		chmod -Rf 770 /var/lib/gromox
		chown -Rf groweb:groweb /var/lib/grommunio-web/{tmp,session}
		chown -Rf groindex:groweb /var/lib/grommunio-web/sqlite-index
		chmod -Rf 770 /var/lib/grommunio-web
	fi
fi

memory_check() {
  local HAVE
  HAVE=$(perl -lne 'print $1 if m{^MemTotal:\s*(\d+)}i' </proc/meminfo)
  # Install the threshold a little lower than what we ask, to account for
  # FW/OS (Vbox with 4194304 KB ends up with MemTotal of about 4020752 KB)
  local THRES=4000000
  local ASK=4096000
  if [ -z "${HAVE}" ] || [ "${HAVE}" -ge "${THRES}" ]; then
    return 0
  fi
  writelog "Memory check"
  memory_notice $((HAVE / 1024)) $((ASK / 1024))

}

memory_check

# Do optional package selection dialog
# Don't gsetup_preseed() here as values to be preseeded not yet set (-n)
# Source g-setup vars etc (-s setup-grommunio-setup)
do_debconf_config -x grommunio-setup -n -c /usr/share/grommunio-setup/scripts/grommunio-setup.config -p setup_debconf_preseed -s /usr/share/grommunio-pkg-bits/scripts/setup-grommunio-setup

unset MYSQL_DB
unset MYSQL_HOST
unset MYSQL_USER
unset MYSQL_PASS
unset ADMIN_PASS
unset FQDN
unset DOMAIN
unset X500
unset SSL_BUNDLE
unset SSL_KEY

writelog "Installation / update of packages"
user_management() {
  adduser postfix sasl
}
user_management >>"${LOGFILE}" 2>&1

# shellcheck source=common/repo
PACKAGES=(gromox grommunio-admin-api grommunio-admin-web grommunio-index
  grommunio-admin-common grommunio-common grommunio-web grommunio-sync
  grommunio-dav grommunio-dbconf nginx-module-vts)
. "${DATADIR}/common/repo"
if [ "$GSETUP_REPO_SETUP" = 'true' ]; then
  if ! setup_repo ; then
    writelog "Exiting - trying to set up apt repos when already defined"
    apt_already_setup_notice
    clear
    exit 2
  fi
fi
writelog "Installing Grommunio-Packages"
apt-get update
# Fix nginx not starting becuase of no SSL certs - use dummy snakeoil self-signed cert
apt-get install grommunio-common grommunio-admin-common --reinstall
cat >/etc/grommunio-common/nginx/ssl_certificate.conf <<EOF
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
EOF
if [ -e /etc/grommunio-admin-common/nginx-ssl.conf ]; then
  rm -f /etc/grommunio-admin-common/nginx-ssl.conf
fi
ln -s /etc/grommunio-common/nginx/ssl_certificate.conf /etc/grommunio-admin-common/nginx-ssl.conf

# reinstall in case of "removealldata"
apt-get install "${PACKAGES[@]}" --reinstall
# tickets are useless... grommunio-{dav,sync} -upsteam.conf's
rm -fv /usr/share/grommunio-common/nginx/upstreams.d/grom*upstream.conf
apt-get install -f

# fix run directory for php-fpm
echo "d /run/php-fpm 0755 www-data gromox - -" >/etc/tmpfiles.d/run-php-fpm.conf
systemd-tmpfiles --create >>"${LOGFILE}" 2>&1

MYSQL_HOST="localhost"
[ -n "$GSETUP_DB_HOST" ] && MYSQL_HOST="$GSETUP_DB_HOST"
MYSQL_USER="grommunio"
[ -n "$GSETUP_DB_USER" ] && MYSQL_USER="$GSETUP_DB_USER"
MYSQL_DB="grommunio"
[ -n "$GSETUP_DB_NAME" ] && MYSQL_DB="$GSETUP_DB_NAME"
MYSQL_PASS="$(randpw)"
[ -n "$GSETUP_DB_PASSWORD" ] && MYSQL_PASS="$GSETUP_DB_PASSWORD"

set_mysql_param() {

  writelog "Dialog: mysql configuration"
  dialog --no-mouse --colors --backtitle "grommunio Setup" --title "MariaDB/MySQL database credentials" --ok-label "Submit" \
    --form "Enter the database credentials." 0 0 0 \
    "Host:    " 1 1 "${MYSQL_HOST}" 1 17 25 0 \
    "User:    " 2 1 "${MYSQL_USER}" 2 17 25 0 \
    "Password:" 3 1 "${MYSQL_PASS}" 3 17 25 0 \
    "Database:" 4 1 "${MYSQL_DB}" 4 17 25 0 2>"${TMPF}" && STATUS=$? || STATUS=$?
  dialog_exit $STATUS

}

writelog "Dialog: mysql installation type"
MYSQL_INSTALL_TYPE=$(dialog --no-mouse --colors --backtitle "grommunio Setup" --title "grommunio Setup: Database" \
  --menu "Choose database setup type" 0 0 0 \
  "1" "Create database locally (default)" \
  "2" "Connect to existing database (advanced users)" 3>&1 1>&2 2>&3) && STATUS=$? || STATUS=$?
dialog_exit $STATUS

writelog "Selected MySQL installation type: ${MYSQL_INSTALL_TYPE}"

RETCMD=1
if [ "${MYSQL_INSTALL_TYPE}" = "2" ]; then
  while [ ${RETCMD} -ne 0 ]; do
    set_mysql_param "Existing database"
    MYSQL_HOST=$(sed -n '1{p;q}' "${TMPF}")
    MYSQL_USER=$(sed -n '2{p;q}' "${TMPF}")
    MYSQL_PASS=$(sed -n '3{p;q}' "${TMPF}")
    MYSQL_DB=$(sed -n '4{p;q}' "${TMPF}")
    if [ -n "${MYSQL_HOST}" ] && [ -n "${MYSQL_USER}" ] && [ -z "${MYSQL_PASS}" ] && [ -n "${MYSQL_DB}" ]; then
      echo "show tables;" | mysql -h"${MYSQL_HOST}" -u"${MYSQL_USER}" "${MYSQL_DB}" >/dev/null 2>&1 && RETCMD=$? || RETCMD=$?
      writelog "mysql -h${MYSQL_HOST} -u${MYSQL_USER} ${MYSQL_DB}"
    elif [ -n "${MYSQL_HOST}" ] && [ -n "${MYSQL_USER}" ] && [ -n "${MYSQL_PASS}" ] && [ -n "${MYSQL_DB}" ]; then
      echo "show tables;" | mysql -h"${MYSQL_HOST}" -u"${MYSQL_USER}" -p"${MYSQL_PASS}" "${MYSQL_DB}" >/dev/null 2>&1 && RETCMD=$? || RETCMD=$?
      writelog "mysql -h${MYSQL_HOST} -u${MYSQL_USER} -p${MYSQL_PASS} ${MYSQL_DB}"
    else
      failonme 1 && RETCMD=$? || RETCMD=$?
    fi
    if [ ${RETCMD} -ne 0 ]; then
      dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "MySQL database credentials" --msgbox 'No connection could be established with the database using the provided credentials. Verify that the credentials are correct and that a connection to the database is possible from this system.' 0 0 && STATUS=$? || STATUS=$?
      dialog_exit $STATUS
    fi
  done
else
  while [ ${RETCMD} -ne 0 ]; do
    set_mysql_param "Create database"
    MYSQL_HOST=$(sed -n '1{p;q}' "${TMPF}")
    MYSQL_USER=$(sed -n '2{p;q}' "${TMPF}")
    MYSQL_PASS=$(sed -n '3{p;q}' "${TMPF}")
    MYSQL_DB=$(sed -n '4{p;q}' "${TMPF}")
    if [ -n "${MYSQL_HOST}" ] && [ -n "${MYSQL_USER}" ] && [ -n "${MYSQL_PASS}" ] && [ -n "${MYSQL_DB}" ]; then
      echo "DROP DATABASE IF EXISTS ${MYSQL_DB}; CREATE DATABASE ${MYSQL_DB}; GRANT ALL ON ${MYSQL_DB}.* TO '${MYSQL_USER}'@'${MYSQL_HOST}' IDENTIFIED BY '${MYSQL_PASS}';" | mysql >/dev/null 2>&1 && RETCMD=$? || RETCMD=$?
    else
      failonme 1 && RETCMD=$? || RETCMD=$?
    fi
    if [ ${RETCMD} -ne 0 ]; then
      dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "MySQL connection failed" --msgbox 'Could not set up the database. Make sure it is reachable and re-run the creation process.' 0 0 && STATUS=$? || STATUS=$?
      dialog_exit $STATUS
    fi
  done
fi
writelog "MySQL configuration: Host: ${MYSQL_HOST}, User: ${MYSQL_USER}, Password: ${MYSQL_PASS}, Database: ${MYSQL_DB}"

if [ -z "$GSETUP_ADMIN_PASSWORD" ]; then
	dialog_adminpass
else
	ADMIN_PASS="$GSETUP_ADMIN_PASSWORD"
fi

set_fqdn() {

  writelog "Dialog: FQDN"
  dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "Fully Qualified Domain Name (FQDN)" --cr-wrap --inputbox \
    "Tell us this system's fully qualified domain name (FQDN). This is used, for example, by Outlook clients to connect.

Example: grommunio.example.com

This name will be part of the certificates later generated. / This name will have to be present in imported certificates." 0 0 "$1" 3>&1 1>&2 2>&3 \
	&& STATUS=$? || STATUS=$?
  dialog_exit $STATUS

}

FQDN="$(hostname -f)"
[ -n "$GSETUP_SITE_FQDN" ] && FQDN="$GSETUP_SITE_FQDN"
FQDN=$(set_fqdn "$FQDN")

# lower case FQDN, strip whitespace
FQDN=$(echo "${FQDN,,}"|xargs)

while [[ ${FQDN} =~ / ]]; do
  dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "Fully Qualified Domain Name (FQDN)" --msgbox 'The FQDN is invalid. Enter a valid FQDN.' 0 0
  FQDN=$(set_fqdn) && STATUS=$? || STATUS=$?
  dialog_exit $STATUS
  # lower case FQDN, strip whitespace
  FQDN=$(echo "${FQDN,,}"|xargs)
done
writelog "Configured FQDN: ${FQDN}"

set_maildomain() {

  DFL=$(hostname -d)
  if [ -z "${DFL}" ]; then
    DFL="${FQDN}"
  fi
  writelog "Dialog: mail domain"
  dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "Mail domain" --cr-wrap --inputbox \
    "Tell us the default mail domain this system serves up. This is used, for example, for Non-Delivery Reports and for generation of some simple TLS certificates. Specify ONLY ONE domain here.

Example: example.com" 0 0 "${DFL}" 3>&1 1>&2 2>&3 \
	&& STATUS=$? || STATUS=$?
  dialog_exit $STATUS

}

ORIGDOMAIN=$(set_maildomain)
DOMAIN=${ORIGDOMAIN,,}

while [[ ${DOMAIN} =~ / ]]; do
  dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "Mail domain" --msgbox 'The entered mail domain is invalid. Enter a valid mail domain.' 0 0 \
	  && STATUS=$? || STATUS=$?
  dialog_exit $STATUS
  ORIGDOMAIN=$(set_maildomain)
  DOMAIN=${ORIGDOMAIN,,}
done
writelog "Configured mail domain: ${FQDN}"

RELAYHOST=$(get_relayhost)
writelog "Got relayhost: ${RELAYHOST}"

X500="i$(printf "%llx" "$(date +%s)")"

[ -e "/etc/grommunio-common/ssl" ] || mkdir -p "/etc/grommunio-common/ssl"

# Configure config.json of admin-web
cat >/etc/grommunio-admin-common/nginx.d/web-config.conf <<EOF
location /config.json {
  alias /etc/grommunio-admin-common/config.json;
}
EOF

choose_ssl_install_type() {

  writelog "Dialog: ssl installation type"
  SSL_INSTALL_TYPE=$(dialog --no-mouse --colors --backtitle "grommunio Setup" --title "grommunio Setup: TLS" \
    --menu "Choose your TLS setup type" 0 0 0 \
    "0" "Create self-signed certificate" \
    "1" "Create own CA and certificate" \
    "2" "Import an existing TLS certificate from files" \
    "3" "Automatically generate Let's Encrypt certificate" 3>&1 1>&2 2>&3) \
    && STATUS=$? || STATUS=$?
  dialog_exit $STATUS

}

choose_ssl_install_type
writelog "Selected TLS installation type: ${SSL_INSTALL_TYPE}"

SSL_COUNTRY="XX"
SSL_STATE="XX"
SSL_LOCALITY="X"
SSL_ORG="grommunio Appliance"
SSL_OU="IT"
SSL_EMAIL="admin@${DOMAIN}"
SSL_DAYS=30
SSL_PASS="$(randpw)"

choose_ssl_fullca() {

  writelog "Dialog: data for Full CA"
  dialog --no-mouse --colors --backtitle "grommunio Setup" --title "TLS certificate (Full CA)" --ok-label "Submit" \
    --form "Enter TLS related data" 0 0 0 \
    "Country:        " 1 1 "${SSL_COUNTRY}" 1 17 25 0 \
    "State:          " 2 1 "${SSL_STATE}" 2 17 25 0 \
    "Locality:       " 3 1 "${SSL_LOCALITY}" 3 17 25 0 \
    "Organization:   " 4 1 "${SSL_ORG}" 4 17 25 0 \
    "Org Unit:       " 5 1 "${SSL_OU}" 5 17 25 0 \
    "E-Mail:         " 6 1 "${SSL_EMAIL}" 6 17 25 0 \
    "Validity (days):" 7 1 "${SSL_DAYS}" 7 17 25 0 2>"${TMPF}" \
    && STATUS=$? || STATUS=$?
  dialog_exit $STATUS

}

choose_ssl_selfprovided() {

  writelog "Dialog: data for self-provided TLS cert"
  dialog --no-mouse --colors --backtitle "grommunio Setup" --title "TLS certificate (self-provided)" --ok-label "Submit" \
    --form "Enter the paths to the TLS certificates" 0 0 0 \
    "PEM encoded certificate bundle:  " 1 1 "${SSL_BUNDLE}" 1 35 120 0 \
    "PEM encoded private key:         " 2 1 "${SSL_KEY}" 2 35 120 0 2>"${TMPF}" \
    && STATUS=$? || STATUS=$?
  dialog_exit $STATUS

}

set_letsencryptmail() {

  writelog "Dialog: Let's Encrypt"
  dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "TLS certificate (Let's Encrypt)" --cr-wrap --inputbox \
    "Specify an email adress that Let's Encrypt can contact for when there is an issue with the certificates

Example: ${SSL_EMAIL}" 0 0 "${SSL_EMAIL}" 3>&1 1>&2 2>&3 \
	&& STATUS=$? || STATUS=$?
  dialog_exit $STATUS

}

choose_ssl_letsencrypt() {

  writelog "Dialog: Let's Encrypt domains"
  LE_TERMS_URL=$(curl -Lsk https://acme-v02.api.letsencrypt.org/directory | grep termsOfService | sed 's#\(.*\)\(https://.*\)\",#\2#')
  if [ "${FQDN}" = "${DOMAIN}" ]; then
    dialog --no-mouse --colors --backtitle "grommunio Setup" --title "TLS certificate (Let's Encrypt)" --ok-label "Submit" \
      --checklist "Choose the Let's Encrypt certificates to request.\nBy requesting certificates from Let's Encrypt, you agree to the terms of service at ${LE_TERMS_URL}.\nThe DNS records should be set accordingly before proceeding." 0 0 0 \
      "${DOMAIN}" "recommended" on \
      "autodiscover.${DOMAIN}" "recommended" on \
      "mail.${DOMAIN}" "optional" off 2>"${TMPF}" \
      	|| dialog_exit $?
  else
    if [ "${FQDN}" = "mail.${DOMAIN}" ]; then
      dialog --no-mouse --colors --backtitle "grommunio Setup" --title "TLS certificate (Let's Encrypt)" --ok-label "Submit" \
        --checklist "Choose the Let's Encrypt certificates to request.\nBy requesting certificates from Let's Encrypt, you agree to the terms of service at ${LE_TERMS_URL}.\nThe DNS records should be set accordingly before proceeding." 0 0 0 \
        "${DOMAIN}" "recommended" on \
        "${FQDN}" "recommended" on \
        "autodiscover.${DOMAIN}" "recommended" off 2>"${TMPF}" \
	  || dialog_exit $?
    else
      dialog --no-mouse --colors --backtitle "grommunio Setup" --title "TLS certificate (Let's Encrypt)" --ok-label "Submit" \
        --checklist "Choose the Let's Encrypt certificates to request.\nBy requesting certificates from Let's Encrypt, you agree to the terms of service at ${LE_TERMS_URL}.\nThe DNS records should be set accordingly before proceeding." 0 0 0 \
        "${DOMAIN}" "recommended" on \
        "autodiscover.${DOMAIN}" "recommended" on \
        "${FQDN}" "recommended" on \
        "mail.${DOMAIN}" "optional" off 2>"${TMPF}" \
	  || dialog_exit $?
    fi
  fi

}

# shellcheck source=common/ssl_setup
. "${DATADIR}/common/ssl_setup"
RETCMD=1
if [ "${SSL_INSTALL_TYPE}" = "0" ]; then
  clear
  if ! selfcert; then
    dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "TLS certificate (self-signed)" --msgbox "Certificate generation not successful. See ${LOGFILE}.\nContinue installation or press ESC to abort setup." 0 0 \
	    && STATUS=$? || STATUS=$?
    dialog_exit $STATUS
  fi
elif [ "${SSL_INSTALL_TYPE}" = "1" ]; then
  while [ -z "${SSL_COUNTRY}" ] || [ -z "${SSL_STATE}" ] || [ -z "${SSL_LOCALITY}" ] || [ -z "${SSL_ORG}" ] || [ -z "${SSL_OU}" ] || [ -z "${SSL_EMAIL}" ] || [ -z "${SSL_DAYS}" ] || [ "${RETCMD}" = "1" ]; do
    choose_ssl_fullca
    RETCMD=0
  done
  SSL_COUNTRY=$(sed -n '1{p;q}' "${TMPF}")
  SSL_STATE=$(sed -n '2{p;q}' "${TMPF}")
  SSL_LOCALITY=$(sed -n '3{p;q}' "${TMPF}")
  SSL_ORG=$(sed -n '4{p;q}' "${TMPF}")
  SSL_OU=$(sed -n '5{p;q}' "${TMPF}")
  SSL_EMAIL=$(sed -n '6{p;q}' "${TMPF}")
  SSL_DAYS=$(sed -n '7{p;q}' "${TMPF}")
  fullca
  writelog "TLS configuration: Country: ${SSL_COUNTRY} State: ${SSL_STATE} Locality: ${SSL_LOCALITY} Organization: ${SSL_ORG} Org Unit: ${SSL_OU} E-Mail: ${SSL_EMAIL} Validity (days): ${SSL_DAYS}"
elif [ "${SSL_INSTALL_TYPE}" = "2" ]; then
  choose_ssl_selfprovided
  SSL_BUNDLE=$(sed -n '1{p;q}' "${TMPF}")
  SSL_KEY=$(sed -n '2{p;q}' "${TMPF}")
  while ! owncert; do
	  echo -n
  done
  writelog "TLS configuration: Bundle: ${SSL_BUNDLE} Key: ${SSL_KEY}"
elif [ "${SSL_INSTALL_TYPE}" = "3" ]; then
  choose_ssl_letsencrypt
  SSL_DOMAINS=$(sed 's# #,#g' "${TMPF}" | tr '[:upper:]' '[:lower:]')
  while [ -z "${SSL_DOMAINS}" ]; do
    dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "TLS certificate (Let's encrypt)" --msgbox "No valid domains have been chosen for the TLS certificates. Select valid domains." 0 0 \
      && STATUS=$? || STATUS=$?
    dialog_exit $STATUS
    choose_ssl_letsencrypt
    SSL_DOMAINS=$(sed 's# #,#g' "${TMPF}" | tr '[:upper:]' '[:lower:]')
  done

  SSL_EMAIL=$(set_letsencryptmail)
  while ! [[ ${SSL_EMAIL} =~ ^.*\@.*$ ]]; do
    dialog --no-mouse --clear --colors --backtitle "grommunio Setup" --title "TLS certificate (Let's Encrypt)" --msgbox "The provided email address is invalid. Enter a valid email address." 0 0
    SSL_EMAIL=$(set_letsencryptmail) \
    && STATUS=$? || STATUS=$?
    dialog_exit $STATUS
  done
  letsencrypt
  writelog "TLS configuration: Let's Encrypt ${SSL_EMAIL}"
fi

CONFIG_JSON=$(cat << EOF
{
  "mailWebAddress": "https://${FQDN}/web",
  "rspamdWebAddress": "https://${FQDN}:8443/antispam"
}
EOF
)
echo "$CONFIG_JSON" | jq > /tmp/config.json
progress 0

progress 10
writelog "Config redis for Grommunio"
{
  systemctl disable --now redis-server.service
  [ -d /var/lib/redis ] && su -m redis -c 'mkdir --mode=0750 -vp /var/lib/redis/default'
  env --chdir=/etc/redis ln -svf {,redis-}grommunio.conf
  systemctl enable --now redis-server@grommunio
 }  >>"${LOGFILE}" 2>&1

progress 15
writelog "Configure SSL Certificates for Grommunio"
cat >/etc/grommunio-common/nginx/ssl_certificate.conf <<EOF
ssl_certificate ${SSL_BUNDLE_T};
ssl_certificate_key ${SSL_KEY_T};
EOF
if [ -e /etc/grommunio-admin-common/nginx-ssl.conf ]; then
  rm -f /etc/grommunio-admin-common/nginx-ssl.conf
fi
ln -s /etc/grommunio-common/nginx/ssl_certificate.conf /etc/grommunio-admin-common/nginx-ssl.conf
chown -hfv gromox:gromox /etc/grommunio-common/ssl/* >>"${LOGFILE}" 2>&1

# set php version number 
PHPVER="$(apt-cache show php |awk '/^Depends:/ {sub("php","", $2);print$2}')"

writelog "Config stage: enable all services"
SERVICES=(redis-server@grommunio.service "php${PHPVER}-fpm.service" nginx.service
$(systemctl list-unit-files 'grom*' --no-legend|cut -d\  -f1 |grep -Pv 'snapshot|cleaner')
  clamav-freshclam.service clamav-daemon.service rspamd.service)
# shellcheck disable=SC2068
systemctl enable ${SERVICES[@]} >>"${LOGFILE}" 2>&1

progress 20
writelog "Config stage: start db"
systemctl enable --now mariadb >>"${LOGFILE}" 2>&1

# https://community.grommunio.com/d/447-debian-11-clean-install-script/37
mkdir -p /var/spool/postfix/run/mysqld >>"${LOGFILE}" 2>&1
# shellcheck disable=SC2028
if ! grep -qF -- "/run/mysqld" /etc/fstab; then
  echo -e "/run/mysqld\t/var/spool/postfix/run/mysqld\tbind\tdefaults,bind\t0\t0" | \
  tee -a /etc/fstab >>"${LOGFILE}" 2>&1
  mount /var/spool/postfix/run/mysqld >>"${LOGFILE}" 2>&1
fi
writelog "Config stage: put php files into place"
if [ -e "/etc/php/$PHPVER/fpm/php-fpm.conf.default" ]; then
  mv "/etc/php/$PHPVER/fpm/php-fpm.conf.default" "/etc/php/$PHPVER/fpm/php-fpm.conf" >>"${LOGFILE}" 2>&1
fi
if [ ! -e "/etc/php/$PHPVER/fpm/pool.d/gromox.conf" ]; then
  cp -vf "/usr/share/gromox/fpm-gromox.conf.sample" "/etc/php/$PHPVER/fpm/pool.d/gromox.conf" >>"${LOGFILE}" 2>&1
fi
if [ -e "/etc/php/$PHPVER/fpm/php-fpm.d/pool-grommunio-sync.conf" ] && [ ! -e "/etc/php/$PHPVER/fpm/pool.d/pool-grommunio-sync.conf" ]; then
  ln -vs "/etc/php/$PHPVER/fpm/php-fpm.d/pool-grommunio-sync.conf" "/etc/php/$PHPVER/fpm/pool.d/" >>"${LOGFILE}" 2>&1
fi
if [ -e "/etc/php/$PHPVER/fpm/php-fpm.d/pool-grommunio-dav.conf" ] && [ ! -e "/etc/php/$PHPVER/fpm/pool.d/pool-grommunio-dav.conf" ]; then
  ln -vs "/etc/php/$PHPVER/fpm/php-fpm.d/pool-grommunio-dav.conf" "/etc/php/$PHPVER/fpm/pool.d/" >>"${LOGFILE}" 2>&1
fi

if [ -f /etc/nginx/sites-enabled/default-site.conf ]; then
	writelog "Remove default nginx host config"
	rm -vf /etc/nginx/sites-enabled/default-site.conf >>"${LOGFILE}" 2>&1
fi

writelog "Config stage: gromox config"
setconf /etc/gromox/http.cfg listen_port 10080
setconf /etc/gromox/http.cfg http_support_ssl true
setconf /etc/gromox/http.cfg listen_ssl_port 10443
setconf /etc/gromox/http.cfg host_id "${FQDN}"

setconf /etc/gromox/smtp.cfg listen_port 24

writelog "Config stage: pam config"
progress 30
if [ -e /etc/pam.d/smtp ]; then
  cp -v /etc/pam.d/smtp /etc/pam.d/smtp.save
fi
cat >/etc/pam.d/smtp <<EOF
#%PAM-1.0
auth required pam_gromox.so
account required pam_permit.so service=smtp
EOF

writelog "Config stage: database creation"
progress 40
echo "CREATE DATABASE IF NOT EXISTS grommunio; GRANT ALL ON grommunio.* TO 'grommunio'@'localhost' IDENTIFIED BY '${MYSQL_PASS}';" | mysql
echo "# Do not delete this file unless you know what you do!" >/etc/grommunio-common/setup_done

writelog "Config stage: database configuration"
setconf /etc/gromox/mysql_adaptor.cfg mysql_username "${MYSQL_USER}"
setconf /etc/gromox/mysql_adaptor.cfg mysql_password "${MYSQL_PASS}"
setconf /etc/gromox/mysql_adaptor.cfg mysql_dbname "${MYSQL_DB}"
setconf /etc/gromox/mysql_adaptor.cfg schema_upgrade "host:${FQDN}"

# use system-timezone
TZ="$(readlink /etc/localtime)"
TZ="${TZ#/usr/share/zoneinfo/}"

writelog "Config stage: autodiscover configuration"
progress 50
cat >/etc/gromox/autodiscover.ini <<EOF
[database]
host = ${MYSQL_HOST}
username = '${MYSQL_USER}'
password = '${MYSQL_PASS}'
dbname = '${MYSQL_DB}'

[exchange]
organization = '${X500}'
hostname = ${FQDN}
mapihttp = 1

[default]
timezone = '${TZ}'

[system]

[http-proxy]
/var/lib/gromox/user = ${FQDN}
/var/lib/gromox/domain = ${FQDN}
EOF

cat >/etc/grommunio-admin-api/conf.d/database.yaml <<EOF
DB:
  host: '${MYSQL_HOST}'
  user: '${MYSQL_USER}'
  pass: '${MYSQL_PASS}'
  database: '${MYSQL_DB}'
EOF

writelog "Config stage: database initialization"
gromox-dbop -C >>"${LOGFILE}" 2>&1

writelog "Config stage: admin password set"
progress 60
grommunio-admin passwd --password "${ADMIN_PASS}" >>"${LOGFILE}" 2>&1

rspamadm pw -p "${ADMIN_PASS}" | sed -e 's#^#password = "#' -e 's#$#";#' >/etc/rspamd/local.d/worker-controller.inc

writelog "Add nginx config for rspamd"
cat >/etc/grommunio-admin-common/nginx.d/rspamd.conf <<'EOF'
location /rspamd/ {
    proxy_pass       http://localhost:11334/;
    proxy_set_header Host      $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
EOF

if ! [ -e /etc/gromox/spamrun.cfg ]; then
  cat << EOH > /etc/gromox/spamrun.cfg
# rspamd might run somewhere else and isn't configured as multi-instance
# see rspamc(1) for more options
# RSPAMC_OPTS=( -h a.b.c.d:1234 -P myverysecurepass )
RSPAMC_OPTS=()

# SPAM #
# Only scan messages which are older than n days.
# Default: SPAMRUN_DAYS=7
SPAMRUN_DAYS=7
# Delete the message after we scanned it? 
# Default: SPAMRUN_DELETE=false
SPAMRUN_DELETE=false

# HAM #
# Default: HAMRUN_FOLDER=NON-JUNK
HAMRUN_FOLDER=NON-JUNK
# Delete *copied* Mails which should be learned as HAM?
# Default: HAMRUN_DELETE=false
HAMRUN_DELETE=false
EOH
fi

writelog "Add grommunio-antispam service files"
cat >/lib/systemd/system/grommunio-spam-run.service <<'EOF'
[Unit]
Description=Spam classification, training and cleanup run

[Service]
ProtectSystem=full
ProtectHome=true
PrivateDevices=true
ProtectHostname=true
ProtectClock=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=true
RestrictRealtime=true
Type=oneshot
ExecStart=/usr/sbin/grommunio-spam-run
EOF

cat >/lib/systemd/system/grommunio-spam-run.timer <<'EOF'
[Unit]
Description=Daily spam classification, training and cleanup run

[Timer]
OnCalendar=daily
AccuracySec=12h
Persistent=true
RandomizedDelaySec=6000

[Install]
WantedBy=timers.target
EOF

cat >/usr/sbin/grommunio-spam-run <<'EOFSPAMRUN'
#!/bin/bash
# vim:ts=2 sts=2 sw=2 expandtab
# Auto Config if not present
if ! [ -e /etc/gromox/spamrun.cfg ]; then
  cat << EOF > /etc/gromox/spamrun.cfg
# rspamd might run somewhere else and isn't configured as multi-instance
# see rspamc(1) for more options
# RSPAMC_OPTS=( -h a.b.c.d:1234 -P myverysecurepass )
RSPAMC_OPTS=()

# Use soft-delete with gromox-mbop delmsg? 
SOFT_DELETE=true

# SPAM #
# Only scan messages which are older than n days.
# Default: SPAMRUN_DAYS=7
SPAMRUN_DAYS=7
# Delete the message after we scanned it? 
# Default: SPAMRUN_DELETE=false
SPAMRUN_DELETE=false

# HAM #
# Default: HAMRUN_FOLDER=TRAIN-HAM
HAMRUN_FOLDER=TRAIN-HAM
# Delete *copied* Mails which should be learned as HAM?
# Default: HAMRUN_DELETE=false
HAMRUN_DELETE=false
EOF
fi

RSPAMC_OPTS=()
SPAMRUN_DAYS=7
SPAMRUN_DELETE=false
if [ -r /etc/gromox/spamrun.cfg ]; then
  . /etc/gromox/spamrun.cfg
fi
if [ -z ${SPAMRUN_DAYS+x} ]; then
  SQLITE_QUERY='select message_id,mid_string from messages where parent_fid=0x17;'
else
read -r -d '' SQLITE_QUERY << EOSQL
SELECT m.message_id,m.mid_string
FROM messages m
INNER JOIN message_properties mp1
ON mp1.message_id = m.message_id
AND mp1.proptag = 235274304
AND (mp1.propval/10000000-11644473600) < unixepoch('now','-$SPAMRUN_DAYS days')
-- DON'T LOOK INTO SUBDIRECTORIES
WHERE m.parent_fid = 0x17
-- DON'T GET SOFTDELETED
AND m.is_deleted = 0
;
EOSQL

fi
# add "-d" to delete junk emails after they have been learned
if [ "$1" = "-d" ]
then
  SPAMRUN_DELETE=true
fi

MYSQL_CFG="/etc/gromox/mysql_adaptor.cfg"
if [ ! -e "${MYSQL_CFG}" ] ; then
  echo "MySQL configuration not found. ($MYSQL_CFG)"
  exit 1
fi
MYSQL_PARAMS="--skip-column-names --skip-line-numbers"
MYSQL_USERNAME=$(sed -ne 's/^mysql_username\s*=\s*\(.*\)/\1/p' ${MYSQL_CFG})
if [ -z "$MYSQL_USERNAME" ]; then
  MYSQL_USERNAME="root"
fi
MYSQL_PASSWORD=$(sed -ne 's/^mysql_password\s*=\s*\(.*\)/\1/p' ${MYSQL_CFG})
MYSQL_DBNAME=$(sed -ne 's/^mysql_dbname\s*=\s*\(.*\)/\1/p' ${MYSQL_CFG})
if [ -z "$MYSQL_DBNAME" ]; then
  MYSQL_DBNAME="grommunio"
fi
if [ "${MYSQL_DBNAME:0:1}" = "-" ]; then
  echo "Cannot use that dbname: ${MYSQL_DBNAME}"
  exit 1
fi
MYSQL_HOST=$(sed -ne 's/^mysql_host\s*=\s*\(.*\)/-h\1/p' ${MYSQL_CFG})
if [ -z "$MYSQL_HOST" ]; then
  MYSQL_HOST="localhost"
fi
MYSQL_QUERY="SELECT username,maildir from users where id <> 0 and maildir <> \"\";"

CONFIG_FILE=$(mktemp)
cat <<CONFFILE >"${CONFIG_FILE}"
[client]
user=${MYSQL_USERNAME}
password='${MYSQL_PASSWORD}'
host=${MYSQL_HOST}
database=${MYSQL_DBNAME}
CONFFILE

cleanup() { rm -f "$CONFIG_FILE" ; }
trap cleanup EXIT

MYSQL_CMD="mysql --defaults-file=${CONFIG_FILE} ${MYSQL_PARAMS}"
# shellcheck disable=SC2068
if ${MYSQL_CMD}<<<"exit"&>/dev/null; then
  ${MYSQL_CMD} --execute "${MYSQL_QUERY}" | while read -r USERNAME MAILDIR; do
  sqlite3 -tabs -noheader "${MAILDIR}/exmdb/exchange.sqlite3" "$SQLITE_QUERY" |
    while read -r MESSAGEID MIDSTRING; do
      MBOP_CMD="$(command -v gromox-mbop)"
      MBOP_CMD="$MBOP_CMD -u "$USERNAME" delmsg"
      if [ $SOFT_DELETE = "true" ]; then
        MBOP_CMD="$MBOP_CMD --soft"
      fi
      echo "Learning spam for user ${USERNAME}" | systemd-cat -t grommunio-spam-run -p info
      MSGFILE="$MAILDIR/eml/$MIDSTRING"
      if [[ ! -f "$MSGFILE" ]]; then
        gromox-exm2eml -u "${USERNAME}" "${MESSAGEID}" 2>/dev/null | rspamc ${RSPAMC_OPTS[@]} learn_spam | systemd-cat -t grommunio-spam-run -p debug
      else
        rspamc ${RSPAMC_OPTS[@]} --header 'Learn-Type: bulk' learn_spam "$MSGFILE" | systemd-cat -t grommunio-spam-run -p debug
      fi
      if [ "${SPAMRUN_DELETE}" = "true" ]; then
        $MBOP_CMD -f 0x17 "${MESSAGEID}" | systemd-cat -t grommunio-spam-run -p notice
      fi
    done
  done
else
  echo "MySQL-Connection couldn't be established, please check your configuration." | systemd-cat -t grommunio-spam-run -p err
fi
EOFSPAMRUN

chmod +x /usr/sbin/grommunio-spam-run

systemctl daemon-reload >>"${LOGFILE}" 2>&1
systemctl enable --now grommunio-spam-run.timer grommunio-spam-run.service >>"${LOGFILE}" 2>&1

writelog "Add grommunio-PROham service files"
cat >/lib/systemd/system/grommunio-ham-run.service <<'EOF'
[Unit]
Description=ham classification, training and cleanup run

[Service]
ProtectSystem=full
ProtectHome=true
PrivateDevices=true
ProtectHostname=true
ProtectClock=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=true
RestrictRealtime=true
Type=oneshot
ExecStart=/usr/sbin/grommunio-ham-run
EOF

cat >/lib/systemd/system/grommunio-ham-run.timer <<'EOF'
[Unit]
Description=Daily ham classification, training and cleanup run

[Timer]
OnCalendar=*:5/30
AccuracySec=1m
Persistent=true
RandomizedDelaySec=60

[Install]
WantedBy=timers.target
EOF

cat >/usr/sbin/grommunio-ham-run <<'EOFHAMRUN'
#!/bin/bash
# vim:ts=2 sts=2 sw=2 expandtab
# Auto Config if not present
if ! [ -e /etc/gromox/spamrun.cfg ]; then
  cat << EOF > /etc/gromox/spamrun.cfg
# rspamd might run somewhere else and isn't configured as multi-instance
# see rspamc(1) for more options
# RSPAMC_OPTS=( -h a.b.c.d:1234 -P myverysecurepass )
RSPAMC_OPTS=()

# Use soft-delete with gromox-mbop delmsg? 
SOFT_DELETE=true

# SPAM #
# Only scan messages which are older than n days.
# Default: SPAMRUN_DAYS=7
SPAMRUN_DAYS=7
# Delete the message after we scanned it? 
# Default: SPAMRUN_DELETE=false
SPAMRUN_DELETE=false

# HAM #
# Default: HAMRUN_FOLDER=TRAIN-HAM
HAMRUN_FOLDER=TRAIN-HAM
# Delete *copied* Mails which should be learned as HAM?
# Default: HAMRUN_DELETE=false
HAMRUN_DELETE=false
EOF
fi

RSPAMC_OPTS=()
HAMRUN_FOLDER="TRAIN-HAM"
HAMRUN_DELETE=false
if [ -r /etc/gromox/spamrun.cfg ]; then
  . /etc/gromox/spamrun.cfg
fi

# exmdb query
read -r -d '' SQLITE_QUERY << EOSQL
/* GET MESSAGES IN  HAM-FOLDER */
SELECT m.message_id,
m.mid_string,
f.folder_id
FROM messages m
JOIN folders f
ON m.parent_fid = f.folder_id
JOIN folder_properties fp
ON fp.folder_id = f.folder_id
-- SELECT TRAINFOLDER
WHERE lower(fp.propval) = lower('${HAMRUN_FOLDER}')
-- DON'T LOOK INTO SUBDIRECTORIES
AND f.parent_id = 9
-- DON'T GET SOFTDELETED
AND m.is_deleted = 0
;
EOSQL

MYSQL_CFG="/etc/gromox/mysql_adaptor.cfg"
if [ ! -e "${MYSQL_CFG}" ] ; then
  echo "MySQL configuration not found. ($MYSQL_CFG)"
  exit 1
fi
MYSQL_PARAMS="--skip-column-names --skip-line-numbers"
MYSQL_USERNAME=$(sed -ne 's/^mysql_username\s*=\s*\(.*\)/\1/p' ${MYSQL_CFG})
if [ -z "$MYSQL_USERNAME" ]; then
  MYSQL_USERNAME="root"
fi
MYSQL_PASSWORD=$(sed -ne 's/^mysql_password\s*=\s*\(.*\)/\1/p' ${MYSQL_CFG})
MYSQL_DBNAME=$(sed -ne 's/^mysql_dbname\s*=\s*\(.*\)/\1/p' ${MYSQL_CFG})
if [ -z "$MYSQL_DBNAME" ]; then
  MYSQL_DBNAME="grommunio"
fi
if [ "${MYSQL_DBNAME:0:1}" = "-" ]; then
  echo "Cannot use that dbname: ${MYSQL_DBNAME}"
  exit 1
fi
MYSQL_HOST=$(sed -ne 's/^mysql_host\s*=\s*\(.*\)/-h\1/p' ${MYSQL_CFG})
if [ -z "$MYSQL_HOST" ]; then
  MYSQL_HOST="localhost"
fi
MYSQL_QUERY="SELECT username,maildir from users where id <> 0 and maildir <> \"\";"

CONFIG_FILE=$(mktemp)
cat <<CONFFILE >"${CONFIG_FILE}"
[client]
user=${MYSQL_USERNAME}
password='${MYSQL_PASSWORD}'
host=${MYSQL_HOST}
database=${MYSQL_DBNAME}
CONFFILE

cleanup() { rm -f "$CONFIG_FILE" ; }
trap cleanup EXIT

MYSQL_CMD="mysql --defaults-file=${CONFIG_FILE} ${MYSQL_PARAMS}"
# shellcheck disable=SC2068
if ${MYSQL_CMD}<<<"exit"&>/dev/null; then
  ${MYSQL_CMD} --execute "${MYSQL_QUERY}" | while read -r USERNAME MAILDIR; do
  sqlite3 -noheader "${MAILDIR}/exmdb/exchange.sqlite3" "$SQLITE_QUERY" |
    while IFS='|' read -r MESSAGEID MIDSTRING FOLDERID; do
      MBOP_CMD="$(command -v gromox-mbop)"
      MBOP_CMD="$MBOP_CMD -u "$USERNAME" delmsg"
      if [ $SOFT_DELETE = "true" ]; then
        MBOP_CMD="$MBOP_CMD --soft"
      fi
      echo "Learning ham for user ${USERNAME}" | systemd-cat -t grommunio-ham-run -p info
      MSGFILE="$MAILDIR/eml/$MIDSTRING"
      if [[ ! -f "$MSGFILE" ]]; then
        gromox-exm2eml -u "${USERNAME}" "${MESSAGEID}" 2>/dev/null | rspamc ${RSPAMC_OPTS[@]} learn_ham | systemd-cat -t grommunio-ham-run -p debug
      else
        rspamc ${RSPAMC_OPTS[@]} --header 'Learn-Type: bulk' learn_ham "$MSGFILE" | systemd-cat -t grommunio-ham-run -p debug
      fi
      if [ "${HAMRUN_DELETE}" = "true" ]; then
        $MBOP_CMD -f "${FOLDERID}" "${MESSAGEID}" | systemd-cat -t grommunio-ham-run -p notice 
      else
        # At least mark it as read if we don't delete it.
        sqlite3 "${MAILDIR}/exmdb/exchange.sqlite3" "UPDATE messages SET read_state=1 WHERE message_id=$MESSAGEID;"
      fi
    done
  done
else
  echo "MySQL-Connection couldn't be established, please check your configuration." | systemd-cat -t grommunio-ham-run -p err
fi
EOFHAMRUN

chmod +x /usr/sbin/grommunio-ham-run

systemctl daemon-reload >>"${LOGFILE}" 2>&1
systemctl enable --now grommunio-ham-run.timer grommunio-ham-run.service >>"${LOGFILE}" 2>&1

writelog "Configure antivirus in antispam"
cat >/etc/rspamd/local.d/antivirus.conf <<EOF
# local.d/antivirus.conf

# multiple scanners could be checked, for each we create a configuration block with an arbitrary name
# More info: https://rspamd.com/doc/modules/antivirus.html
antivirus {
  # multiple scanners could be checked, for each we create a configuration block with an arbitrary name
  clamav {
    # If set force this action if any virus is found (default unset: no action is forced)
    # action = "reject";
    message = '${SCANNER}: virus found: "${VIRUS}"';
    # Scan mime_parts separately - otherwise the complete mail will be transferred to AV Scanner
    scan_mime_parts = true;
    # Scanning Text is suitable for some av scanner databases (e.g. Sanesecurity)
    scan_text_mime = false;
    scan_image_mime = false;
    # If max_size is set, messages > n bytes in size are not scanned
    #max_size = 20000000;
    # symbol to add (add it to metric if you want non-zero weight)
    symbol = "CLAM_VIRUS";
    # type of scanner: "clamav", "fprot", "sophos" or "savapi"
    type = "clamav";
    # For "savapi" you must also specify the following variable
    #product_id = 12345;
    # You can enable logging for clean messages
    #log_clean = true;
    # servers to query (if port is unspecified, scanner-specific default is used)
    # can be specified multiple times to pool servers
    # can be set to a path to a unix socket
    # Enable this in local.d/antivirus.conf
    servers = "127.0.0.1:3310";
    # if patterns is specified virus name will be matched against provided regexes and the related
    # symbol will be yielded if a match is found. If no match is found, default symbol is yielded.
    #patterns {
      # symbol_name = "pattern";
    #  JUST_EICAR = '^Eicar-Test-Signature$';
    #}
    #patterns_fail {
      # symbol_name = "pattern";
      #CLAM_PROTOCOL_ERROR = '^unhandled response';
    #}
    # whitelist points to a map of signature names. Hits on these signatures are ignored.
    whitelist = "/etc/rspamd/antivirus.wl";
  }
}
EOF

cat >/etc/rspamd/local.d/antivirus_group.conf <<EOF
group "antivirus" {
  symbol "CLAM_VIRUS" {
    weight = 4;
    description = "ClamAV found a Virus";
  }
}
EOF

writelog "Config stage: gromox tls configuration"
setconf /etc/gromox/http.cfg http_certificate_path "${SSL_BUNDLE_T}"
setconf /etc/gromox/http.cfg http_private_key_path "${SSL_KEY_T}"

setconf /etc/gromox/imap.cfg imap_support_starttls true
setconf /etc/gromox/imap.cfg listen_ssl_port 993
setconf /etc/gromox/imap.cfg imap_certificate_path "${SSL_BUNDLE_T}"
setconf /etc/gromox/imap.cfg imap_private_key_path "${SSL_KEY_T}"

setconf /etc/gromox/pop3.cfg pop3_support_stls true
setconf /etc/gromox/pop3.cfg listen_ssl_port 995
setconf /etc/gromox/pop3.cfg pop3_certificate_path "${SSL_BUNDLE_T}"
setconf /etc/gromox/pop3.cfg pop3_private_key_path "${SSL_KEY_T}"

# Domain and X500
writelog "Config stage: gromox domain and x500 configuration"
for SERVICE in http midb zcore imap pop3 smtp delivery; do
  setconf /etc/gromox/${SERVICE}.cfg default_domain "${DOMAIN}"
done
for CFG in midb.cfg zcore.cfg exmdb_local.cfg exmdb_provider.cfg exchange_emsmdb.cfg exchange_nsp.cfg; do
  setconf "/etc/gromox/${CFG}" x500_org_name "${X500}"
done

writelog "Config stage: postfix configuration"
progress 80

cat >/etc/postfix/grommunio-virtual-mailbox-domains.cf <<EOF
user = ${MYSQL_USER}
password = ${MYSQL_PASS}
hosts = ${MYSQL_HOST}
dbname = ${MYSQL_DB}
query = SELECT 1 FROM domains WHERE domain_status=0 AND domainname='%s'
EOF

cat >/etc/postfix/grommunio-virtual-mailbox-alias-maps.cf <<EOF
user = ${MYSQL_USER}
password = ${MYSQL_PASS}
hosts = ${MYSQL_HOST}
dbname = ${MYSQL_DB}
query = SELECT mainname FROM aliases WHERE aliasname='%s'
EOF

cat >/etc/postfix/grommunio-virtual-mailbox-maps.cf <<EOF
user = ${MYSQL_USER}
password = ${MYSQL_PASS}
hosts = ${MYSQL_HOST}
dbname = ${MYSQL_DB}
query = SELECT 1 FROM users WHERE username='%s'
EOF

postconf -e \
  myhostname="${FQDN}" \
  virtual_mailbox_domains="mysql:/etc/postfix/grommunio-virtual-mailbox-domains.cf" \
  virtual_mailbox_maps="mysql:/etc/postfix/grommunio-virtual-mailbox-maps.cf" \
  virtual_alias_maps="mysql:/etc/postfix/grommunio-virtual-mailbox-alias-maps.cf" \
  virtual_transport="smtp:[::1]:24" \
  relayhost="${RELAYHOST}" \
  inet_interfaces=all \
  smtpd_helo_restrictions=permit_mynetworks,permit_sasl_authenticated,reject_invalid_hostname,reject_non_fqdn_hostname \
  smtpd_sender_restrictions=reject_non_fqdn_sender,permit_sasl_authenticated,permit_mynetworks \
  smtpd_recipient_restrictions=permit_sasl_authenticated,permit_mynetworks,reject_unknown_recipient_domain,reject_non_fqdn_hostname,reject_non_fqdn_sender,reject_non_fqdn_recipient,reject_unauth_destination,reject_unauth_pipelining \
  smtpd_data_restrictions=reject_unauth_pipelining \
  smtpd_tls_security_level=may \
  smtpd_tls_auth_only=no \
  smtpd_tls_cert_file="${SSL_BUNDLE_T}" \
  smtpd_tls_key_file="${SSL_KEY_T}" \
  smtpd_tls_received_header=yes \
  smtpd_tls_session_cache_timeout=3600s \
  smtpd_tls_protocols='!SSLv2,!SSLv3,!TLSv1,!TLSv1.1' \
  smtpd_tls_mandatory_protocols='!SSLv2,!SSLv3,!TLSv1,!TLSv1.1' \
  tls_random_source=dev:/dev/urandom \
  smtpd_sasl_auth_enable=yes \
  broken_sasl_auth_clients=yes \
  smtpd_sasl_security_options=noanonymous \
  smtpd_sasl_local_domain= smtpd_milters=inet:localhost:11332 \
  milter_default_action=accept \
  milter_protocol=6
postconf -M tlsmgr/unix="tlsmgr unix - - n 1000? 1 tlsmgr"
postconf -M submission/inet="submission inet n - n - - smtpd"
postconf -P submission/inet/syslog_name="postfix/submission"
postconf -P submission/inet/smtpd_tls_security_level=encrypt
postconf -P submission/inet/smtpd_sasl_auth_enable=yes
postconf -P submission/inet/smtpd_relay_restrictions=permit_sasl_authenticated,reject
postconf -P submission/inet/milter_macro_daemon_name=ORIGINATING
postconf -e 'cyrus_sasl_config_path=/etc/postfix/sasl'
postconf -e 'smtpd_sasl_local_domain=$myhostname'

writelog "Configure sasl smtpd"
mkdir -p "/etc/postfix/sasl"
cat > /etc/postfix/sasl/smtpd.conf <<EOF
pwcheck_method: saslauthd
mech_list: CRAM-MD5 DIGEST-MD5 LOGIN PLAIN
EOF

writelog "Config stage: postfix enable and restart"
systemctl enable --now postfix.service >>"${LOGFILE}" 2>&1
systemctl restart postfix.service >>"${LOGFILE}" 2>&1

writelog "Update sasauthd defaults"
if ! grep -q START=yes /etc/default/saslauthd ; then
  sed -i '0,/^$/s//START=yes/' /etc/default/saslauthd
fi
sed -i '/^OPTIONS/ s/"-c -m \//"-r -c -m \//g' /etc/default/saslauthd
if ! /lib/systemd/systemd-sysv-install is-enabled saslauthd; then
  /lib/systemd/systemd-sysv-install enable saslauthd
fi
systemctl start saslauthd  >>"${LOGFILE}" 2>&1

writelog "Enable fetchmail and configure"
setconf /etc/default/fetchmail START_DAEMON yes
systemctl enable --now fetchmail.service >>"${LOGFILE}" 2>&1
systemctl restart --now fetchmail.service >>"${LOGFILE}" 2>&1

# Note: SSH is enabled by Default
writelog "Config stage: open required firewall ports"
{
  firewall-cmd --add-service=https --zone=public --permanent
  firewall-cmd --add-port=25/tcp --zone=public --permanent
  firewall-cmd --add-port=80/tcp --zone=public --permanent
  firewall-cmd --add-port=110/tcp --zone=public --permanent
  firewall-cmd --add-port=143/tcp --zone=public --permanent
  firewall-cmd --add-port=587/tcp --zone=public --permanent
  firewall-cmd --add-port=993/tcp --zone=public --permanent
  firewall-cmd --add-port=8080/tcp --zone=public --permanent
  firewall-cmd --add-port=8443/tcp --zone=public --permanent
  firewall-cmd --reload
} >>"${LOGFILE}" 2>&1

progress 90
writelog "Config stage: restart all required services"
# shellcheck disable=SC2068
systemctl restart saslauthd.service ${SERVICES[@]} >>"${LOGFILE}" 2>&1 || true

# grommunio-admin-api systemd-tmpfiles wrong user for nginx
cp -v /usr/lib/tmpfiles.d/grommunio-admin-api.conf /etc/tmpfiles.d/
sed -i 's/nginx/www-data/g' /etc/tmpfiles.d/grommunio-admin-api.conf
systemd-tmpfiles --create /etc/tmpfiles.d/grommunio-admin-api.conf >>"${LOGFILE}" 2>&1

mv /tmp/config.json /etc/grommunio-admin-common/config.json

# grommunio-admin-api logs
cat > /etc/grommunio-admin-api/conf.d/logs.yaml <<EOF
logs:
  PHP fpm:
    source: php$PHPVER-fpm.service
  Antispam:
    source: rspamd.service
EOF

writelog "Config stage: Install optional feature applications"
progress 95
setup_options_debconf

# grommunio-admin-api add rspamd.service
# sadly it seems we can't remove/overwrite grommunio-antispam.service 
# like with logs.yaml
# NOW WE CAN / or rather know how!
# first we need to clear the data of options.dashboard.services: {}
# https://community.grommunio.com/d/1845-manual-installation-vs-appliance/12
cat > /etc/grommunio-admin-api/conf.d/00-clear-dashboard.yaml <<EOF
options:
  dashboard:
    services: {}
EOF

cat > /etc/grommunio-admin-api/conf.d/services.yaml <<EOF
options:
  dashboard:
    services:
      - unit: gromox-delivery-queue.service
      - unit: gromox-delivery.service
      - unit: gromox-event.service
      - unit: gromox-http.service
      - unit: gromox-imap.service
      - unit: gromox-midb.service
      - unit: gromox-pop3.service
      - unit: gromox-timer.service
      - unit: gromox-zcore.service
      - unit: nginx.service
      - unit: php$PHPVER-fpm.service
      - unit: postfix.service
      - unit: redis-server@grommunio.service
      - unit: rspamd.service
EOF

if [ -n "$GSETUP_OPT_SELECT" ]; then
	for APP in ${OPT_SELECT}; do
	cat >> /etc/grommunio-admin-api/conf.d/services.yaml <<EOF
     - unit: ${APP}.service
EOF
	done
fi


systemctl restart grommunio-admin-api.service

# apt capture non-finished packages
apt-get install -f

progress 100
writelog "Config stage: completed"
setup_done

