#!/usr/bin/env bash

# Author:   Zhang Huangbin (zhb _at_ iredmail.org)

#---------------------------------------------------------------------
# This file is part of iRedMail, which is an open source mail server
# solution for Red Hat(R) Enterprise Linux, CentOS, Debian and Ubuntu.
#
# iRedMail is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# iRedMail is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with iRedMail.  If not, see <http://www.gnu.org/licenses/>.
#---------------------------------------------------------------------

export PROG_NAME='iRedMail'
export PROG_NAME_LOWERCASE='iredmail'
export PROG_VERSION='0.8.7'

export DATE="$(/bin/date +%Y.%m.%d.%H.%M.%S)"

# For perl and run-time locale setting.
export LC_ALL=C

# Debug mode: YES, NO.
export IREDMAIL_DEBUG="${IREDMAIL_DEBUG:=NO}"

# -----------------
# ---- Generic ----
# -----------------

# Maildir format: Maildir. Mbox format was deprecated since version 0.7.3.
export MAILBOX_FORMAT='Maildir'

# Maildir style: hashed, normal.
export MAILDIR_STYLE='hashed'

# Current storage node.
export STORAGE_NODE='vmail1'

# Enabled backends.
export ENABLE_BACKEND_OPENLDAP='YES'
export ENABLE_BACKEND_MYSQL='YES'
export ENABLE_BACKEND_PGSQL='YES'
# MariaDB
export ENABLE_BACKEND_MARIADB='NO'
# OpenBSD built-in LDAP daemon
export ENABLE_BACKEND_LDAPD='NO'

# For better distributed deployment
#
# IP address of localhost.
# Usually it's 127.0.0.1, but not in FreeBSD Jail.
export LOCAL_ADDRESS="${LOCAL_ADDRESS:=127.0.0.1}"

# Hostname or IP address used in MySQL GRANT command (allow remote access from
# this hostname/IP).
# Usually it's 'localhost', but not in FreeBSD Jail (use ${LOCAL_ADDRESS} or
# hostname of Jail instead).
if [ X"${LOCAL_ADDRESS}" == X'127.0.0.1' ]; then
    # Pre-define MYSQL_GRANT_HOST while running iRedMail to use a remote MySQL
    # server. For example:
    # MYSQL_GRANT_HOST='192.168.1.2' bash iRedMail.sh
    export MYSQL_GRANT_HOST="${MYSQL_GRANT_HOST:=localhost}"
else
    export MYSQL_GRANT_HOST="${LOCAL_ADDRESS}"
fi

# LDAP server
export LDAP_SERVER_HOST="${LDAP_SERVER_HOST:=${LOCAL_ADDRESS}}"
export LDAP_SERVER_PORT="${LDAP_SERVER_PORT:=389}"
# MySQL server
export MYSQL_SERVER="${MYSQL_SERVER:=${LOCAL_ADDRESS}}"
export MYSQL_SERVER_PORT="${MYSQL_SERVER_PORT:=3306}"
export MYSQL_ROOT_USER="${MYSQL_ROOT_USER:=root}"
# PGSQL server
export PGSQL_SERVER="${PGSQL_SERVER:=${LOCAL_ADDRESS}}"
export PGSQL_SERVER_PORT="${PGSQL_SERVER_PORT:=5432}"

export USE_LOCAL_MYSQL_SERVER='YES'
if [ X"${MYSQL_SERVER}" != X"${LOCAL_ADDRESS}" ]; then
    export USE_LOCAL_MYSQL_SERVER='NO'
fi

# Dovecot: POP3, IMAP, managesieve
export IMAP_SERVER="${LOCAL_ADDRESS}"
export MANAGESIEVE_BIND_HOST="${LOCAL_ADDRESS}"
export MANAGESIEVE_PORT='4190'
# SMTP server (Postfix)
export SMTP_SERVER="${LOCAL_ADDRESS}"
# Amavisd
export AMAVISD_SERVER="${LOCAL_ADDRESS}"
# Policyd or Cluebringer
export POLICYD_BIND_HOST="${LOCAL_ADDRESS}"
export CLUEBRINGER_BIND_HOST="${LOCAL_ADDRESS}"
# ClamAV
export CLAMD_BIND_HOST="${LOCAL_ADDRESS}"
# iRedAPD
export IREDAPD_BIND_HOST="${LOCAL_ADDRESS}"

# For managesieve service and software.
export USE_MANAGESIEVE='YES'    # Use managesieve service.

# vmail user/group name, uid and gid.
export VMAIL_USER_NAME='vmail'
export VMAIL_GROUP_NAME='vmail'

# Specify UID/GID for system accounts: vmail, iredadmin, iredapd.
# Required by cluster environment. e.g. GlusterFS.
export VMAIL_USER_UID='2000'
export VMAIL_USER_GID='2000'
export IREDADMIN_USER_UID='2001'
export IREDADMIN_USER_GID='2001'
export IREDAPD_DAEMON_USER_UID='2002'
export IREDAPD_DAEMON_USER_GID='2002'

# Default SQL database name used to store mail accounts.
export VMAIL_DB='vmail'
export VMAIL_DB_BIND_USER='vmail'
export VMAIL_DB_ADMIN_USER='vmailadmin'

# Default virtual domain admin name without domain name (@example.com).
export DOMAIN_ADMIN_NAME='postmaster'

# Tools.
export CONFIG_VIA_DIALOG="${DIALOG_DIR}/config_via_dialog.sh"
# Note: config file will be sourced in file 'conf/core', function 'check_env()'.
export IREDMAIL_CONFIG_FILE="${ROOTDIR}/config"
export TIP_FILE="${ROOTDIR}/${PROG_NAME}.tips"
export DOC_FILE="${ROOTDIR}/Documentations"
export STATUS_FILE="${ROOTDIR}/.status"

# Output flag.
export _INFO_FLAG="< INFO >"
export _SKIP_FLAG="< SKIP >"
export _ERROR_FLAG="< ERROR >"
export _QUESTION_FLAG="< Question >"
export _BACKUP_FLAG="+ < Backup >"
export _DEBUG_FLAG="+ < DEBUG >"

export CONF_MSG="#
# File generated by ${PROG_NAME} (${DATE}):
#
# Version:  ${PROG_VERSION}
# Project:  http://www.iredmail.org/
#
# Community: http://www.iredmail.org/forum/
#
"

# TERM.
if [ X"${TERM}" == X"" ]; then
    export TERM='xterm'
fi

# Logrotate configuration directory.
export LOGROTATE_DIR='/etc/logrotate.d'

# Kernel name, in upper cases.
export KERNEL_NAME="$(uname -s | tr '[a-z]' '[A-Z]')"

# Hostname.
if [ X"${KERNEL_NAME}" == X'OPENBSD' ]; then
    export HOSTNAME="$(hostname)"
    export RANDOM_STRING='eval echo $RANDOM | md5'
else
    export HOSTNAME="$(hostname -f)"

    # Genrate a random string.
    # Usage:
    #   str="$(${RANDOM_STRING})"
    export RANDOM_STRING='eval </dev/urandom tr -dc A-Za-z0-9 | (head -c $1 &>/dev/null || head -c 30)'
fi

# command: dialog.
export BIN_DIALOG="dialog"
export PKG_DIALOG="dialog"

# command: bzip2.
export BIN_BZIP2='bzip2'
export PKG_BZIP2='bzip2'

# Shells
export SHELL_NOLOGIN='/sbin/nologin'
export SHELL_BASH='/bin/bash'

# Check hardware architecture.
arch="$(uname -m)"
case $arch in
    i[3456]86) export OS_ARCH='i386' ;;
    x86_64|amd64) export OS_ARCH='x86_64' ;;
    armv6l)
        # Debian ARM platform and Raspberry Pi.
        export OS_ARCH='armhf' ;;
    *)
        echo "Your architecture is not supported yet: ${arch}."
        echo "Both i386 and x86_64 are supported by ${PROG_NAME}."
        exit 255
        ;;
esac

# Check distribution.
#   - DISTRO
#   - DISTRO_VERSION
#   - DISTRO_CODENAME
#
# UNSUPPORTED_RELEASE will be set to 'YES' if current Linux/BSD release is
# an old release and unsupported anymore.
if [ X"${KERNEL_NAME}" == X"LINUX" ]; then
    # Directory of RC scripts.
    export DIR_RC_SCRIPTS='/etc/init.d'

    if [ -f /etc/redhat-release ]; then
        # RHEL/CentOS
        export DISTRO='RHEL'

        # Get distribution version
        if grep '\ 6' /etc/redhat-release &>/dev/null; then
            # version 6.x
            export DISTRO_VERSION='6'
        else
            export UNSUPPORTED_RELEASE='YES'
        fi

        # Get distribution name as DISTRO_CODENAME
        if grep '^Red' /etc/redhat-release &>/dev/null; then
            # RHEL
            export DISTRO_CODENAME='rhel'
        elif grep '^CentOS' /etc/redhat-release &>/dev/null; then
            # CentOS
            export DISTRO_CODENAME='centos'
        elif grep '^Scientific' /etc/redhat-release &>/dev/null; then
            # Scientific Linux
            export DISTRO_CODENAME='scientific'
        else
            export UNSUPPORTED_RELEASE='YES'
        fi

        export PKG_ARCH=".${OS_ARCH}"
        if [ X"${OS_ARCH}" == X"i386" ]; then
            export PKG_ARCH=''
        fi

    elif [ -f /etc/lsb-release ]; then
        # Ubuntu
        export DISTRO='UBUNTU'

        # Ubuntu version number and code name:
        #   - 12.04: precise (Long Term support by Ubuntu)
        #   - 14.04: trusty
        export DISTRO_ID="$(grep 'DISTRIB_ID' /etc/lsb-release | awk -F'=' '{print $2}')"
        export DISTRO_VERSION="$(grep 'DISTRIB_RELEASE' /etc/lsb-release | awk -F'=' '{print $2}')"
        export DISTRO_CODENAME="$(grep 'DISTRIB_CODENAME' /etc/lsb-release | awk -F'=' '{print $2}')"

        # Unsupported releases: 12.10, 13.04, 13.10
        if echo "${DISTRO_VERSION}" | grep -E '^(12\.10|13\.04|13\.10)' &>/dev/null ; then
            export UNSUPPORTED_RELEASE='YES'
        fi
    elif [ -f /etc/debian_version ]; then
        # Debian
        export DISTRO='DEBIAN'

        # Get major release version number
        export DISTRO_VERSION="$(cat /etc/debian_version)"

        # Set distro code name and unsupported releases.
        if grep '^7' /etc/debian_version &>/dev/null || \
            grep -i '^wheezy' /etc/debian_version &>/dev/null; then
            export DISTRO_VERSION='7'
            export DISTRO_CODENAME='wheezy'
        else
            export UNSUPPORTED_RELEASE='YES'
        fi

        # Override settings.
        export SHELL_NOLOGIN='/usr/sbin/nologin'
    else
        export UNSUPPORTED_RELEASE='YES'
    fi
elif [ X"${KERNEL_NAME}" == X"FREEBSD" ]; then
    export DISTRO='FREEBSD'
    export DISTRO_VERSION="$(uname -r |awk -F'[.-]' '{print $1}')"

    # Directory of RC scripts.
    export DIR_RC_SCRIPTS='/usr/local/etc/rc.d'

    # Unsupported releases: 7, 8.
    if echo "${DISTRO_VERSION}" | grep '^[78]' &>/dev/null ; then
        export UNSUPPORTED_RELEASE='YES'
    fi

    export SHELL_BASH='/usr/local/bin/bash'
elif [ X"${KERNEL_NAME}" == X'OPENBSD' ]; then
    export DISTRO='OPENBSD'
    export DISTRO_VERSION="$(uname -r)"

    # Directory of RC scripts.
    export DIR_RC_SCRIPTS='/etc/rc.d'
    export RC_CONF_LOCAL='/etc/rc.conf.local'
    export SHELL_BASH='/usr/local/bin/bash'

    # Unsupported release: 5.1, 5.2, 5.3.
    if echo "${DISTRO_VERSION}" | grep '^5.[123]' &>/dev/null ; then
        export UNSUPPORTED_RELEASE='YES'
    fi
else
    # Not support *BSD and other distrobutions yet.
    echo "Error: Your OS is not supported yet."
    exit 255
fi

# Exit and prompt to use a supported Linux/BSD distribution
if [ X"${UNSUPPORTED_RELEASE}" == X'YES' ]; then
    cat <<EOF
********* ERROR *********
Release version of the operating system on this server is unsupported by
iRedMail, please access below link to get the latest iRedMail and a list
of supported Linux/BSD distributions and release versions.

http://www.iredmail.org/download.html

*************************
EOF

    exit 255
fi

# install_pkg: function used to install packages without confirm.
# remove_pkg: function used to remove packages without confirm.
# LIST_ALL_PKGS: command used to list all installed packages.
# LIST_FILES_IN_PKG: command used to list files installed by special package.
# enable_service: function (defined in conf/core) used to enable services.
# disable_service: function (defined in conf/core) used to disable services.
if [ X"${DISTRO}" == X"RHEL" ]; then
    # RHEL/CentOS.
    # System user: root. Note: not all OSes have group 'root'.
    export SYS_ROOT_USER='root'
    export SYS_ROOT_GROUP='root'

    # Package management.
    if [ X"${YUM}" != X"" ]; then
        export YUM="${YUM}"
    else
        export YUM="yum -d 2"
    fi
    export install_pkg='install_pkg_rhel'
    export remove_pkg="remove_pkg_rhel"
    export LIST_ALL_PKGS='rpm -qa'
    export LIST_FILES_IN_PKG='rpm -ql'

    # Service control. Defined in file: conf/core.
    export enable_service='enable_service_rh'
    export disable_service='disable_service_rh'

    # Syslog config file: rsyslog.
    export SYSLOG_CONF='/etc/rsyslog.conf'
    export SYSLOG_POSTROTATE_CMD='/bin/kill -HUP $(cat /var/run/syslogd.pid 2> /dev/null) 2> /dev/null || true'

    # Crontab related.
    export CRON_SPOOL_DIR='/var/spool/cron'

    # Directory /etc/sysconfig/ on RHEL/CentOS.
    export ETC_SYSCONFIG_DIR='/etc/sysconfig'

    # iptables rule file.
    export FIREWALL_RULE_CONF="${ETC_SYSCONFIG_DIR}/iptables"

    # Directory used to store SSL/TLS key/cert file.
    export SSL_FILE_DIR="/etc/pki/tls"

    # Yum repository related.
    export YUM_REPOS_DIR='/etc/yum.repos.d'
    export LOCAL_REPO_NAME="${PROG_NAME}"
    export LOCAL_REPO_FILE="${YUM_REPOS_DIR}/${LOCAL_REPO_NAME}.repo"

    # Override default value.
    export PKG_DIALOG="dialog${PKG_ARCH}"
    export PKG_BZIP2="bzip2${PKG_ARCH}"

elif [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ]; then
    # Ubuntu & Debian.
    export DEBIAN_FRONTEND='noninteractive'

    # System user: root. Note: not all OSes have group 'root'.
    export SYS_ROOT_USER='root'
    export SYS_ROOT_GROUP='root'

    # Package management.
    if [ X"${APTGET}" != X"" ]; then
        export APTGET="${APTGET}"
    else
        export APTGET="apt-get"
    fi
    # Package management.
    export install_pkg='install_pkg_debian'
    export remove_pkg='remove_pkg_debian'
    export LIST_ALL_PKGS="dpkg -l |awk '{print $2}'"
    export LIST_FILES_IN_PKG='dpkg -L'

    # Service control.
    export enable_service="enable_service_debian"
    export disable_service="disable_service_debian"

    if [ X"${DISTRO}" == X"UBUNTU" ]; then
        # Syslog config: rsyslog.
        # Ubuntu >= 9.10
        export SYSLOG_CONF='/etc/rsyslog.d/iredmail.conf'
        export SYSLOG_POSTROTATE_CMD='reload rsyslog >/dev/null 2>&1 || true'

        # MariaDB support requires Ubuntu >= 14.04
        if [ X"${DISTRO_CODENAME}" != X'precise' ]; then
            export ENABLE_BACKEND_MARIADB='YES'
        fi
    fi

    if [ X"${DISTRO}" == X"DEBIAN" ]; then
        export SYSLOG_CONF='/etc/rsyslog.conf'
        export SYSLOG_POSTROTATE_CMD='invoke-rc.d rsyslog reload > /dev/null'
    fi

    # Crontab related.
    export CRON_SPOOL_DIR='/var/spool/cron/crontabs'

    # Directory /etc/default/ on Debian/Ubuntu.
    export ETC_SYSCONFIG_DIR='/etc/default'

    # iptables rule file.
    export FIREWALL_RULE_CONF="${ETC_SYSCONFIG_DIR}/iptables"

    # Directory used to store SSL/TLS key/cert file.
    export SSL_FILE_DIR="/etc/ssl"

elif [ X"${DISTRO}" == X"FREEBSD" ]; then
    # System user: root.
    export SYS_ROOT_USER='root'
    export SYS_ROOT_GROUP='wheel'

    # Package management.
    if [ X"${PKGADD}" != X"" ]; then
        export PKGADD="${PKGADD}"
    else
        export PKGADD="pkg_add"
    fi

    # Package management.
    export install_pkg='install_pkg_freebsd'
    export remove_pkg='remove_pkg_freebsd'
    if [ X"${DISTRO_VERSION}" == X'9' ]; then
        export LIST_ALL_PKGS="pkg_info | awk '{print $1}'"
        export LIST_FILES_IN_PKG='pkg_info -L'
    else
        # use pkgng on FreeBSD 10 and later releases.
        export LIST_ALL_PKGS="pkg info | awk '{print $1}'"
        export LIST_FILES_IN_PKG='pkg query "%Fp"'
    fi

    # Port directory
    export PORT_WRKDIRPREFIX='/usr/ports'

    # Service control.
    export enable_service="enable_service_freebsd"
    export disable_service="disable_service_freebsd"

    # Syslog config: rsyslog.
    export SYSLOG_CONF='/etc/syslog.conf'
    export SYSLOG_POSTROTATE_CMD=''

    # Crontab related.
    export CRON_SPOOL_DIR='/var/cron/tabs'

    export ETC_SYSCONFIG_DIR='/etc/defaults'
    export FREEBSD_MAKE_CONF='/etc/make.conf'

    # IPFW rule file.
    export FIREWALL_RULE_CONF="${ETC_SYSCONFIG_DIR}/ipfw.rules"

    # Directory used to store SSL/TLS key/cert file.
    export SSL_FILE_DIR="/etc/ssl"

    # Logrotate directory.
    export LOGROTATE_DIR="/usr/local/etc/logrotate.d"

elif [ X"${DISTRO}" == X'OPENBSD' ]; then
    export ENABLE_BACKEND_LDAPD='YES'

    # System user: root.
    export SYS_ROOT_USER='root'
    export SYS_ROOT_GROUP='wheel'

    # Package management.
    if [ X"${PKG_PATH}" == X"" ]; then
        # Reference: http://www.openbsd.org/faq/faq15.html#Easy
        export PKG_PATH="ftp://ftp.openbsd.org/pub/OpenBSD/$(uname -r)/packages/$(machine -a)/"
    fi

    # Package management.
    export install_pkg='pkg_add -i'
    export remove_pkg='pkg_delete'
    export LIST_ALL_PKGS="pkg_info -a | awk '{print $1}'"
    export LIST_FILES_IN_PKG='pkg_info -L'

    # Service control.
    export enable_service="enable_service_openbsd"
    export disable_service="disable_service_openbsd"

    # Syslog config: rsyslog.
    export SYSLOG_CONF='/etc/syslog.conf'
    export SYSLOG_POSTROTATE_CMD=''

    # Crontab related.
    export CRON_SPOOL_DIR='/var/cron/tabs'

    # PF rule file.
    export FIREWALL_RULE_CONF="/etc/pf.conf"

    # Directory used to store SSL/TLS key/cert file.
    export SSL_FILE_DIR="/etc/ssl"
else
    # Not support yet.
    echo "Your distrobution is not supported yet."
    exit 255
fi

# Use a seperated directory to store iRedMail certs/keys.
if [ X"${DISTRO}" == X'OPENBSD' ]; then
    export SSL_CERT_DIR="${SSL_FILE_DIR}"
    export SSL_KEY_DIR="${SSL_FILE_DIR}"
else
    export SSL_CERT_DIR="${SSL_FILE_DIR}/certs"
    export SSL_KEY_DIR="${SSL_FILE_DIR}/private"
fi

# SSL key.
export OPENSSL_CONF="${SSL_FILE_DIR}/openssl.cnf"
export SSL_CERT_FILE="${SSL_CERT_DIR}/iRedMail_CA.pem"
export SSL_KEY_FILE="${SSL_KEY_DIR}/iRedMail.key"
export TLS_COUNTRY='CN'
export TLS_STATE='GuangDong'
export TLS_CITY='ShenZhen'
export TLS_COMPANY="${HOSTNAME}"
export TLS_DEPARTMENT='IT'
export TLS_HOSTNAME="${HOSTNAME}"
export TLS_ADMIN="root@${HOSTNAME}"

# Default SSL key size in bits
export SSL_KEY_SIZE='2048'
default_ssl_key_size="$(grep '^default_bits' ${OPENSSL_CONF} 2>/dev/null | awk -F'=' '{print $2}' | awk '{print $1}')"
if [ -z ${default_ssl_key_size} ]; then
    :
elif [ ${default_ssl_key_size} -ge ${SSL_KEY_SIZE} ]; then
    export SSL_KEY_SIZE="${default_ssl_key_size}"
fi

# Location of sshd_config
export SSHD_CONFIG='/etc/ssh/sshd_config'

# SQL databases which need to be backed up.
export MYSQL_BACKUP_DATABASES=''
export PGSQL_BACKUP_DATABASES=''

# Command use to fetch source tarballs.
if [ X"${DISTRO}" == X'FREEBSD' -o X"${DISTRO}" == X'OPENBSD' ]; then
    # -i: Turns off interactive prompting during multiple file transfers.
    # -V: Disable verbose and progress
    FETCH_CMD='ftp -iV'
else
    # -c: Continue getting a partially-downloaded file.
    # -q: Turn off Wget's output.
    FETCH_CMD="wget -cq"
fi
