#!/bin/bash

#
# Name:         changeftppass
# Version:      1.0.14
# Description:  Change virtual FTP user's password
#
# (c) 2016-2019, Rapidseedbox, alexey@rapidseedbox.com
#

export LANG=en_US

# Fix "bad" terminals
case "${TERM}" in
  "xterm" )
      export TERM="linux"
      ;;
esac

LOGFILE="/var/log/changeftppass.log"

function usage() {
    cat <<EOF
Usage: ${0} [USERNAME [Password] ]
EOF
}

# Quick checks before we allow bad things to happen
if [ -z "${BASH_VERSINFO}" ]; then
    echo "ERROR: You must execute this script with BASH"
    exit 1
fi

_uid=`id -u`
if [ ${_uid} -ne 0 ] ; then
    echo "Sorry."
    echo "'root' credentials required to run this script !"
    exit 1
fi

# Main return code for the script
retcode=0

# Define the dialog exit status codes
DIALOG_OK=0
DIALOG_CANCEL=1
DIALOG_HELP=2
DIALOG_EXTRA=3
DIALOG_ITEM_HELP=4
DIALOG_ESC=255


DIALOG_OPTS="--ascii-lines"

if [ "${1}" = "-h" -o "${1}" = "--help" ] ; then
    usage
    exit 0
fi


USERNAME="${1}"
PASSWORD="${2}"
[ -z "${PASSWORD}" ] && UI="yes" || UI="no"
[ ! -z "${PASSWORD}" -a "${PASSWORD}" = "RANDOM" ] \
    && PASSWORD=`apg -n 1 -m 8 -x 8 -M NCL`


# Store menu options selected by the user
INPUT="/tmp/changeftppass.in.$$"

# Storage file for displaying commands output
OUTPUT="/tmp/changeftppass.out.$$"

# Storage file for misc data
DATA="/tmp/changeftppass.data.$$"

# trap and delete temp files
trap "exit_func" SIGHUP SIGINT SIGTERM


# -------------------------------------------
# Logging functions
# -------------------------------------------
function ENTRY(){
    local cfn="${FUNCNAME[1]}"
    local tstamp=`date`
    local msg="> ${cfn} ${FUNCNAME}"
    echo -e "[${tstamp}] [DEBUG]\t${msg}" >> "${LOGFILE}"
}

function RETURN(){
    local cfn="${FUNCNAME[1]}"
    local tstamp=`date`
    local msg="< ${cfn} ${FUNCNAME}"
    echo -e "[${tstamp}] [DEBUG]\t${msg}" >> "${LOGFILE}"
}

function INFO()
{
    local msg="${1}"
    local tstamp=`date`
    echo -e "[${tstamp}] [INFO]\t${msg}" >> "${LOGFILE}"
}

function ERROR()
{
    local msg="${1}"
    local tstamp=`date`
    echo -e "[${tstamp}] [ERROR]\t${msg}" >> "${LOGFILE}"
}

function DEBUG()
{
    local msg="${1}"
    local tstamp=`date`
    echo -e "[${tstamp}] [DEBUG]\t${msg}" >> ${LOGFILE}
}


#
# Purpose - display output using msgbox 
#  $1 -> set msgbox height
#  $2 -> set msgbox width
#  $3 -> set msgbox title
#
function display_output()
{
    ENTRY
    local h=${1-10}                 # box height default 10
    local w=${2-41}                 # box width default 41
    local t=${3-Output}             # box title 

    if [ "${UI}" = "yes" ] ; then
        dialog ${DIALOG_OPTS} \
               --backtitle "ChangeFtpPass" \
	       --title "${t}" \
	       --clear \
	       --msgbox "$(<$OUTPUT)" ${h} ${w}
    fi
    RETURN
}


#
# Generic function - just get password string and store it in $DATA file
#
function get_password()
{

    ENTRY

    local _component
    local ret

    _component="$1" 
    # get password
    rm -vf "${DATA}" >> "${LOGFILE}" 2>&1
    dialog ${DIALOG_OPTS} \
           --title "Password" \
           --clear \
           --insecure \
           --extra-button \
           --extra-label "Generate" \
           --passwordbox "Enter new \"${_component}\" password for \"${USERNAME}\"" 9 45 2> "${DATA}"
    ret=$?
    # Generate random password if requested
    if [ ${ret} -eq ${DIALOG_EXTRA} ] ; then
        apg -n 1 -m 8 -x 8 -M NCL > "${DATA}"
        ret=0
    fi
    RETURN
}


#
# Perform cleanup and exit
#
function exit_func()
{
    ENTRY

    # if temp files found, delete them
    [ -f "${OUTPUT}" ] && rm -f "${OUTPUT}" >> "${LOGFILE}" 2>&1
    [ -f "${INPUT}" ] && rm -f "${INPUT}" >> "${LOGFILE}" 2>&1
    [ -f "${DATA}" ] && rm -f "${DATA}" >> "${LOGFILE}" 2>&1

    [ "${UI}" = "yes" ] && clear

    [ ! -z "${PASSWORD}" ] && echo "${PASSWORD}"

    RETURN

    exit ${retcode}
}


# --------------------------------------------------------------------- #
#   MAIN SECTION                                                        #
# --------------------------------------------------------------------- #

which pure-pw > /dev/null 2>&1
if [ $? -ne 0 ] ; then
    echo "'pure-pw': command not found!"
    echo "Can not continue..."
    exit 1
fi

pure-pw list > /dev/null 2>&1
if [ $? -ne 0 ] ; then
    echo "'pure-pw': no virtual FTP users found!"
    echo "Can not continue..."
    exit 1
fi

if [ ! -z "${USERNAME}" ] ; then
    pure-pw show ${USERNAME} > /dev/null 2>&1
    if [ $? -ne 0 ] ; then
        echo "'${USERNAME}': account not found!"
        echo "Can not continue..."
        exit 1
    fi
fi

#
# set infinite loop
#
while true ; do
    if [ ! -z "${USERNAME}" ] ; then
        user="${USERNAME}"
    else
        ar=()
        pure-pw list 2>/dev/null | awk '{print $1}' 2>/dev/null | sort -n -n -k 1.4 > "${DATA}"
        if [ ! -s "${DATA}" ] ; then
            echo "'pure-pw list': empty output!"
            retcode=1
            rm -f "${DATA}"
            exit 1
        fi
        while read -r s ; do
            ar+=("${s}" "")
        done < "${DATA}"
        # Count additional menu lines
        num=${#ar[@]}
        num=$((num/2))
        dialog ${DIALOG_OPTS} --clear  --backtitle "ChangeFtpPass" \
            --title " Choose FTP account " \
            --menu "You can use the UP/DOWN arrow keys" \
            15 50 10 \
            "${ar[@]}" 2>"${INPUT}"
        ret=$?
        if [ ${ret} -eq $DIALOG_CANCEL -o ${ret} -eq $DIALOG_ESC ] ; then
            break
        fi
        user=$(<"${INPUT}")
    fi
    if [ -z "${PASSWORD}" ] ; then
        get_password "User '${user}'"
        passwd=`cat "${DATA}"`
    else
        passwd="${PASSWORD}"
    fi
    echo -e "${passwd}\n${passwd}" | pure-pw passwd "${user}" > "${OUTPUT}" 2>&1
    if [ $? -eq 0 ] ; then
        pure-pw mkdb >> "${OUTPUT}" 2>&1
        echo "Password for '${user}' succesfully set" >> "${OUTPUT}"
        echo "New password: ${passwd}" >> "${OUTPUT}"
        INFO "Password for '${user}' succesfully set"
        INFO "New password: ${passwd}"
    else
        echo "!!! Error changing FTP password for '${user}'!!!" >> "${OUTPUT}"
        ERROR "!!! Error changing FTP password for '${user}'!!!"
    fi

    [ "${UI}" = "yes" ] && display_output 15 45 " FTP "

    [ ! -z "${USERNAME}" ] && break

done

exit_func
