#!/bin/bash
#
# vmail-stack
# https://git.stack-source.com/msb/vmail-stack
# Copyright (c) 2022 Matthew Saunders Brown <matthewsaundersbrown@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#
# vmail include file, used by other vmail bash scripts

# constants
readonly VMAIL_DIR=/var/vmail
readonly MYSQL_CONNECTION_INFO_FILE=$VMAIL_DIR/.my.cnf

# switch to required user
if [[ $(basename $0) == "vmail-dkim-"* ]]; then
  if [[ "$USER" != "Debian-exim" ]]; then
    exec sudo -u Debian-exim -g ssl-cert $0 "$@"
  fi
elif [[ $(basename $0) == "vmail-purge-spool.sh" ]]; then
  if [[ "$USER" != "Debian-exim" ]]; then
    exec sudo -u Debian-exim $0 "$@"
  fi
else
  if [[ "$USER" != "vmail" ]]; then
    exec sudo -u vmail $0 "$@"
  else
    # check that MYSQL_CONNECTION_INFO_FILE exists and is readable
    if [ ! -f "$MYSQL_CONNECTION_INFO_FILE" ]; then
      echo "ERROR: MySQL connection info file ($MYSQL_CONNECTION_INFO_FILE) does not exist or is not readable."
      exit 1
    fi
  fi
fi

# functions

# crude but good enough domain name format validation
function vmail::validate_domain () {
  local my_domain=$1
  if [[ $my_domain =~ ^(([a-zA-Z0-9](-?[a-zA-Z0-9])*)\.)+[a-zA-Z]{2,}$ ]] ; then
    return 0
  else
    return 1
  fi
}

# yesno prompt
#
# Examples:
# loop until y or n:  if vmail::yesno "Continue?"; then
# default y:          if vmail::yesno "Continue?" Y; then
# default n:          if vmail::yesno "Continue?" N; then
function vmail::yesno() {

  local prompt default reply

  if [ "${2:-}" = "Y" ]; then
    prompt="Y/n"
    default=Y
  elif [ "${2:-}" = "N" ]; then
    prompt="y/N"
    default=N
  else
    prompt="y/n"
    default=
  fi

  while true; do

    read -p "$1 [$prompt] " -n 1 -r reply

    # Default?
    if [ -z "$reply" ]; then
      reply=$default
    fi

    # Check if the reply is valid
    case "$reply" in
      Y*|y*) return 0 ;;
      N*|n*) return 1 ;;
    esac

  done

}

function vmail:getoptions () {
  local OPTIND
  while getopts "ha:b:d:e:f:gj:cp:q:r:s:tk:gl:m:o:u:vx" opt ; do
    case "${opt}" in
        h ) # display help and exit
          help
          exit
          ;;
        a ) # alias
          alias=${OPTARG,,}
          if [[ $alias =~ "@" ]] ; then
            domain=${alias##*@}
            if vmail::validate_domain $domain; then
              alias=${alias%@*}
            else
              echo "ERROR: $domain is not a valid domain name."
              exit 1
            fi
          fi
          ;;
        b ) # body - Body for Autoresponder emails
          body="${OPTARG}"
          ;;
        c ) # cvs - output in cvs format
          cvs="| sed 's/\t/,/g'"
          ;;
        d ) # domain name (virtualhost) to act on
          domain=${OPTARG,,}
          if ! vmail::validate_domain $domain; then
            echo "ERROR: $domain is not a valid domain name."
            exit 1
          fi
          ;;
        e ) # email address
          email=${OPTARG,,}
          if [[ $email =~ "@" ]] ; then
            mbox=${email%@*}
            domain=${email##*@}
            if [ -z $mbox ] ; then
              echo "ERROR: No local part in $email."
              exit 1
            elif [ -z $domain ] ; then
              echo "ERROR: No domain in $email."
              exit 1
            elif ! vmail::validate_domain $domain; then
              echo "ERROR: $domain is not a valid domain name."
              exit 1
            fi
          else
            echo "ERROR: $email is not a valid email."
            exit 1
          fi
          ;;
        f ) # forward to email address
          forward=${OPTARG,,}
          if [[ $forward =~ "@" ]] ; then
            forward_mbox=${forward%@*}
            forward_domain=${forward##*@}
            if [ -z $forward_mbox ] ; then
              echo "ERROR: No local part in $forward."
              exit 1
            elif [ -z $forward_domain ] ; then
              echo "ERROR: No domain in $forward."
              exit 1
            elif ! vmail::validate_domain $forward_domain; then
              echo "ERROR: $forward_domain is not a valid domain name."
              exit 1
            fi
          else
            echo "ERROR: $forward is not a valid email."
            exit 1
          fi
          ;;
        g ) # glob (wildcard) search
          glob=${OPTARG,,}
          ;;
        j ) # Filter Junk
          filter=${OPTARG}
          ;;
        k ) # keep
          keep=${OPTARG}
          if [[ $keep != "0" ]] && [[ $keep != "1" ]]; then
            echo "ERROR: Invalid save keep setting: -k $keep."
            exit 1
          fi
          ;;
        l ) # limit
          limit=${OPTARG}
          ;;
        m ) # mbox
          mbox=${OPTARG}
          ;;
        p ) # password
          password=${OPTARG}
          ;;
        o ) # mode for autoresponder - must be Vacation or Autoresponder
          mode=${OPTARG,,} # first force lower case
          mode=${mode^} # then capitlize first letter
          if [[ $mode != "Vacation" ]] && [[ $mode != "Autoresponder" ]]; then
            echo "ERROR: Invalid mode setting: -o $mode. Must be either Vacation or Autoresponder"
            exit 1
          fi
          ;;
        q ) # quota
          quota=${OPTARG}
          ;;
        r ) # ratelimit - hourly limit for sending, multiplied by 10 for daily limit
          ratelimit=${OPTARG}
          ;;
        s ) # status - 0 or 1 or 2
          status=${OPTARG}
           if [[ $status != "0" ]] && [[ $status != "1" ]] && [[ $status != "2" ]]; then
            echo "ERROR: Invalid status setting: -s $status"
            exit 1
          fi
          ;;
        t ) # tab - Use tabs instead of tables for output, do not display column headers
          tab=true
          ;;
        u ) # subject - Subject for Autoresponder emails
          subject="${OPTARG}"
          ;;
        n ) # dry-run
          dryrun=true
          ;;
        v ) # verbose
          verbose=true
          ;;
        w ) # write - store data in file
          write=true
          ;;
        x ) # eXecute - don't prompt for confirmation
          execute=true
          ;;
        \? )
          echo "Invalid option: $OPTARG"
          exit 1
          ;;
        : )
          echo "Invalid option: $OPTARG requires an argument"
          exit 1
        ;;
    esac
  done
  shift $((OPTIND-1))
}