#!/bin/bash

#set -e

PROGS="/usr/bin/fly-run /usr/bin/fly-menuedit /usr/bin/fly-dtedit /usr/bin/fly-randr /usr/bin/twm"
TERMINALS=`ls /usr/bin/*term*`

USAGE=$(cat <<EOF
Usage: sudo fly-kiosk [options]
Locks user in kioks mode.

OPTIONS
    -h --help      display this help and exit
    -u --user      set user name
    -a --action    set action: unlock|lock
    -p --prog      set programm to use in single application mode
    -j --home      use non-standart HOME location for user
    -d --default   use default Fly configuration in kiosk mode
    -s --status    see status

Example: fly-kiosk -u user --home /home/user --action lock -p firefox

If you want to switch user to kiosk mode, you have to authenticate this user at least once.
If you want to switch user, which has mandate access control level enabled you have to authenticate this user on each access level at least once. Then run fly-kiosk once for each access level. Let's say for example we have user named user with mandate access levels 1 and 2.
fly-kiosk -u user --action lock
fly-kiosk -u user --action lock --home /home/.pdp/user/l1i0c0x0t0x0
fly-kiosk -u user --action lock --home /home/.pdp/user/l2i0c0x0t0x0
Same for exiting kiosk mode.
fly-kiosk -u user --action unlock
fly-kiosk -u user --action unlock --home /home/.pdp/user/l1i0c0x0t0x0
fly-kiosk -u user --action unlock --home /home/.pdp/user/l2i0c0x0t0x0
If user has access levels except 0 then you shouldn't use fly-admin-smc to setup kiosk mode for that user.
EOF
)

USAGE_RU=$(cat <<EOF
Запуск: sudo fly-kiosk [options]
Запирает пользовател в режиме киоска.

OPTIONS
    -h --help      Показать справку и выйти
    -u --user      Имя пользователя
    -a --action    Действие с пользователем: unlock|lock
    -p --prog      Название программы для использования в режиме с единственной программой
    -j --home      использовать нестандартное расположение домашней директории пользователя
    -d --default   в режиме киоска использовать настройки по умолчанию для среды Fly
    -s --status    Вывод текущего состояния

Пример: fly-kiosk -u user --home /home/user --action lock -p firefox

Если вы хотите перевести пользователя в режим киоска, то сначала надо хоть раз авторизоваться этим пользователем.
Если пользователю предоставлен доступ к мандатным уровням и категориям отличным от 0, то надо хоть раз авторизоваться на каждом уровне доступа. После чего запустить fly-kiosk для каждого уровня с соответствующим значением --home и без --home. Например для пользователя user с уровнями 1 и 2 нужно запустить
fly-kiosk -u user --action lock
fly-kiosk -u user --action lock --home /home/.pdp/user/l1i0c0x0t0x0
fly-kiosk -u user --action lock --home /home/.pdp/user/l2i0c0x0t0x0
Аналогично для выхода из режима киоска
fly-kiosk -u user --action unlock
fly-kiosk -u user --action unlock --home /home/.pdp/user/l1i0c0x0t0x0
fly-kiosk -u user --action unlock --home /home/.pdp/user/l2i0c0x0t0x0
Настройка режима киоска с помощью программы fly-admin-smc возможно только для пользователя который не имеет доступа к мандатным уровням и категориям отличным от 0.
EOF
)

usage () {
    if echo $LANG | grep -q "ru" ; then
        echo "${USAGE_RU}"
    else
        echo "${USAGE}"
    fi
}

is_locked()
{
    local user=$1
    id --groups --name ${user} 2>/dev/null | grep -qP '(^| )lock( |$)'
    return $?
}

is_logged()
{
    local user=$1
    while read LINE; do
        if [ "$user" == "$LINE" ]; then
            return 0
        fi
    done < <(who | awk '{print $1}')
    return 1
}

add_to_group_lock()
{
    local user=$1
    grep -q '^lock' /etc/group || groupadd lock
    usermod -a -G lock ${user}
}

remove_from_group_lock()
{
    local user=$1
    local prog_name=$2

    gpasswd -d ${user} lock
    grep -q '^lock:.*:$' /etc/group && groupdel lock
}

create_dotfly()
{
    local user=$1
    sudo -u ${user} fly-wm -d :none 2>&1 >/dev/null
}

programm_is_forbidden()
{
    local prog=${1}
    local result=1
    echo $PROGS | grep -q $(readlink -f $(which $prog)) && result=0
    readlink -f $(which $prog) | grep 'term' | grep -q '/usr/bin/' && result=0
    return $result
}

show_status()
{
    local username=$1
    if [ -z ${username} ]; then
        local users_in_group=$(getent group lock)
        if [ -n ${users_in_group} ];then
            printf "These users are in kiosk mode: "
            echo ${users_in_group} | sed 's/.*://'
        else
            echo "There are no users in kiosk mode."
        fi
    else
        # Single user
        if id ${username} 1>&2 >/dev/null; then
            if is_locked ${username}; then
                # Locked
                if [[ -s ${HOME_DIR}/.fly/lock ]]; then
                    local prog_name=`cat ${HOME_DIR}/.fly/lock`
                    echo "User ${username} is locked in single application kiosk mode."
                    echo "Application: ${prog_name}"
                else
                    echo "User ${username} is locked in kiosk mode."
                fi
            else
                # Common. Not locked.
                echo "User ${username} is not locked in kiosk mode."
            fi
        else
            echo "No such user ${username}"
            exit 6
        fi
    fi
}

sed_i() #Workaround for "sed -i" not working in mandated environments
{
    local script="$1"
    local file=$2

    tmp=$(mktemp)
    sed "$script" $file > $tmp
    cat $tmp > ${file}
    rm -f $tmp
}

lock_user()
{
    local username=$1
    local prog_name=$2
    local FLY_DIR="${HOME_DIR}/.fly"
    local CONFIG_DIR="${HOME_DIR}/.config"
    local DESKTOP_DIR="${HOME_DIR}/Desktops"

    local pdp_tag=$(pdp-ls -Mnd ${HOME_DIR} | awk '{print $5}')
    pdpl-file ${pdp_tag} ${FLY_DIR}
    pdpl-file ${pdp_tag} ${FLY_DIR}/toolbar

    printf "${prog_name}" > ${HOME_DIR}/.fly/lock

    #Don't let user run terminal emulators and some other programms.
    add_to_group_lock ${username}
    chown root:lock /dev/pts
    chmod g-rx /dev/pts
    #setfacl --modify user:${username}:- ${TERMINALS} || true
    setfacl --modify user:${username}:- ${PROGS} 2>/dev/null || true
    setfacl --modify user:${username}:- /usr/bin/fly-admin* || true

    #Doesn't work.
    #echo "- : ${username} : tty1 tty2 tty3 tty4 tty5 tty6" | sudo tee -a /etc/security/access.conf
    #sudo echo "-:ALL EXCEPT astra-admin shutdown sync:LOCAL" >> /etc/security/access.conf
    #sudo echo "session   required   pam_console.so" >> /etc/pam.d/login

    sed_i "s/^$username:\(.*\):\/bin\/bash/$username:\1:\/bin\/false/" /etc/passwd

    #Don't let user write something.
    #chown -R root:root ${HOME_DIR}
    chown -R root:root $FLY_DIR
    chown -R root:root $CONFIG_DIR
    chown -R root:root $DESKTOP_DIR
    setfacl --recursive --modify user:${username}:r-x ${FLY_DIR} || true
    setfacl --recursive --modify user:${username}:r-x ${CONFIG_DIR} || true
    setfacl --recursive --modify user:${username}:r-x ${DESKTOP_DIR} || true
    if [ -d $FLY_DIR.nonkiosk ]; then
        chown -R root:root $FLY_DIR.nonkiosk
        setfacl --recursive --modify user:${username}:r-x ${FLY_DIR}.nonkiosk
    fi
    setfacl             --modify user:${username}:r-- ${HOME_DIR}/.profile 2>/dev/null || true
    setfacl             --modify user:${username}:r-- ${HOME_DIR}/.bashrc  2>/dev/null || true
    setfacl             --modify user:${username}:- ${HOME_DIR}/.bash_profile  2>/dev/null || true
    setfacl             --modify user:${username}:- ${HOME_DIR}/.bash_login 2>/dev/null || true
    setfacl             --modify user:${username}:- ${HOME_DIR}/.xprofile 2>/dev/null || true
    setfacl             --modify user:${username}:- ${HOME_DIR}/.Xsession 2>/dev/null || true
    setfacl             --modify user:${username}:- ${HOME_DIR}/.xsession 2>/dev/null || true
    setfacl             --modify user:${username}:- ${HOME_DIR}/.xsessionrc 2>/dev/null || true

    #sudo find $DESKTOP_DIR -name *.desktop -exec rm -f {} \;

    #Add shutdown shortcut to toolbar.
    cp /usr/share/applications/fly-shutdown-dialog.desktop $FLY_DIR/toolbar/
    rm -f $FLY_DIR/toolbar/start.desktop
    rm -f $FLY_DIR/toolbar/switcher.desktop

    #sed_i 's/UseStartButton.*/UseStartButton=true/g' $FLY_DIR/theme/default.themerc
    sed_i 's/UsePager.*/UsePager=false/g' $FLY_DIR/theme/default.themerc
    sed_i 's/PagingSize.*/PagingSize=1x1/g' $FLY_DIR/theme/default.themerc
    #sed_i 's/UseStartButton.*/UseStartButton=true/g' $FLY_DIR/theme/current.themerc
    sed_i 's/UsePager.*/UsePager=false/g' $FLY_DIR/theme/current.themerc
    sed_i 's/PagingSize.*/PagingSize=1x1/g' $FLY_DIR/theme/current.themerc

    sed_i 's/\(.*\ =\ FLYWM_POPUP_START_MENU\)/;\1/' $FLY_DIR/keyshortcutrc

    if ! [ -f /etc/xdg/rusbitech/fly-fm.conf ]; then
        touch /etc/xdg/rusbitech/fly-fm.conf
        chmod 644 /etc/xdg/rusbitech/fly-fm.conf
    fi
    kwriteconfig5 --file /etc/xdg/rusbitech/fly-fm.conf --group Global --key "kiosk/${username}" true
    if ! [ -f /etc/xdg/rusbitech/fly-fm-vfs.conf ]; then
        touch /etc/xdg/rusbitech/fly-fm-vfs.conf
        chmod 644 /etc/xdg/rusbitech/fly-fm.conf
    fi
    kwriteconfig5 --file /etc/xdg/rusbitech/fly-fm-vfs.conf --group Network --key "Enabled" false

    ##Have to do something with context menu.
    # if [ -f ${HOME_DIR}/.fly/en.miscrc ]; then
    #     cp ${HOME_DIR}/.fly/en.miscrc ${HOME_DIR}/.fly/en.miscrc.orig
    # fi
    # if [ -f ${HOME_DIR}/.fly/ru_RU-UTF-8.miscrc ]; then
    #     cp ${HOME_DIR}/.fly/ru_RU-UTF-8.miscrc ${HOME_DIR}/.fly/ru_RU-UTF-8.miscrc.orig
    # fi
    # cp /usr/share/fly-mode-switch/en.miscrc.modified ${HOME_DIR}/.fly/en.miscrc
    # cp /usr/share/fly-mode-switch/ru_RU.UTF-8.miscrc.modified ${HOME_DIR}/.fly/ru_RU-UTF-8.miscrc
}

unlock_user()
{
    local username=$1
    local FLY_DIR="${HOME_DIR}/.fly"
    local CONFIG_DIR="${HOME_DIR}/.config"
    local DESKTOP_DIR="${HOME_DIR}/Desktops"

    local pdp_tag=$(pdp-ls -Mnd ${HOME_DIR} | awk '{print $5}')
    pdpl-file ${pdp_tag} ${FLY_DIR}
    pdpl-file ${pdp_tag} ${FLY_DIR}/toolbar

    remove_from_group_lock ${username}
    grep -q '^lock' /etc/group || chown root:root /dev/pts && chmod g+rx /dev/pts

    #setfacl --remove user:${username} ${TERMINALS} || true
    setfacl --remove user:${username} ${PROGS} 2>/dev/null || true
    setfacl --remove user:${username} /usr/bin/fly-admin* || true

    #sed_i "s/.*${username}.*//g" /etc/security/access.conf
    #sed_i 's/.*astra-admin.*//g' /etc/security/access.conf
    sed_i "s/^${username}:\(.*\):\/bin\/false/${username}:\1:\/bin\/bash/" /etc/passwd

    #chown -R ${username}:${username} ${HOME_DIR}
    chown -R ${username}:${username} $FLY_DIR
    chown -R ${username}:${username} $CONFIG_DIR
    chown -R ${username}:${username} $DESKTOP_DIR
    setfacl --recursive --remove user:${username} ${FLY_DIR} || true
    setfacl --recursive --remove user:${username} ${CONFIG_DIR} || true
    setfacl --recursive --remove user:${username} ${DESKTOP_DIR} || true
    if [ -d ${FLY_DIR}.nonkiosk ]; then
        setfacl --recursive --remove user:${username} ${FLY_DIR}.nonkiosk || true
    fi
    setfacl             --remove user:${username} ${HOME_DIR}/.profile 2>/dev/null || true
    setfacl             --remove user:${username} ${HOME_DIR}/.bashrc 2>/dev/null || true
    setfacl             --remove user:${username} ${HOME_DIR}/.bash_profile 2>/dev/null || true
    setfacl             --remove user:${username} ${HOME_DIR}/.bash_login 2>/dev/null || true
    setfacl             --remove user:${username} ${HOME_DIR}/.xprofile 2>/dev/null || true
    setfacl             --remove user:${username} ${HOME_DIR}/.Xsession 2>/dev/null || true
    setfacl             --remove user:${username} ${HOME_DIR}/.xsession 2>/dev/null || true
    setfacl             --remove user:${username} ${HOME_DIR}/.xsessionrc 2>/dev/null || true

    rm -f $FLY_DIR/toolbar/fly-shutdown-dialog.desktop
    cp -f /usr/share/fly-wm/toolbar/start.desktop $FLY_DIR/toolbar/
    cp -f /usr/share/fly-wm/toolbar/switcher.desktop $FLY_DIR/toolbar/

    #sed_i 's/UseStartButton.*/UseStartButton=false/g' $FLY_DIR/theme/default.themerc
    sed_i 's/UsePager.*/UsePager=true/g' $FLY_DIR/theme/default.themerc
    sed_i 's/PagingSize.*/PagingSize=2x2/g' $FLY_DIR/theme/default.themerc
    #sed_i 's/UseStartButton.*/UseStartButton=false/g' $FLY_DIR/theme/current.themerc
    sed_i 's/UsePager.*/UsePager=true/g' $FLY_DIR/theme/current.themerc
    sed_i 's/PagingSize.*/PagingSize=2x2/g' $FLY_DIR/theme/current.themerc

    sed_i 's/;\(.* = FLYWM_POPUP_START_MENU\)/\1/' $FLY_DIR/keyshortcutrc

    if ! [ -f /etc/xdg/rusbitech/fly-fm.conf ]; then
        touch /etc/xdg/rusbitech/fly-fm.conf
        chmod 644 /etc/xdg/rusbitech/fly-fm.conf
    fi
    kwriteconfig5 --file /etc/xdg/rusbitech/fly-fm.conf --group Global --key "kiosk/${username}" false
    if ! [ -f /etc/xdg/rusbitech/fly-fm-vfs.conf ]; then
        touch /etc/xdg/rusbitech/fly-fm-vfs.conf
        chmod 644 /etc/xdg/rusbitech/fly-fm.conf
    fi
    kwriteconfig5 --file /etc/xdg/rusbitech/fly-fm-vfs.conf --group Network --key "Enabled" true

    if [ -f ${HOME_DIR}/.fly/en.miscrc.orig ]; then
        mv ${HOME_DIR}/.fly/en.miscrc.orig ${HOME_DIR}/.fly/en.miscrc
    fi
    if [ -f ${HOME_DIR}/.fly/ru_RU-UTF-8.miscrc.orig ]; then
        mv ${HOME_DIR}/.fly/ru_RU-UTF-8.miscrc.orig ${HOME_DIR}/.fly/ru_RU-UTF-8.miscrc
    fi

    rm -f ${HOME_DIR}/.fly/lock
}

# SCRIPT STARTS HERE. No function declarations below.

PROGRAM="fly-kiosk"
LONG_OPTIONS="help,user:,action:,prog:,home:,default,status"
LONG_OPTIONS="$(echo ${LONG_OPTIONS} | tr -d ' ')"
ARGUMENTS="$(getopt --longoptions ${LONG_OPTIONS} --name="${PROGRAM}" --options hu:a:p:j:ds --shell sh -- "${@}")"

if [ "${?}" != "0" ]; then
    echo "Terminating." >&2
    exit 1
fi

eval set -- "${ARGUMENTS}"

while true; do
    case "${1}" in
        -h|--help)
            SHOW_USAGE="true"
            usage
            exit 0
            ;;
        -u|--user)
            USER_NAME="${2}"
            shift 2
            ;;
        -a|--action)
            ACTION="${2}"
            shift 2
            ;;
        -p|--prog)
            PROG_NAME="${2}"
            shift 2
            ;;
        -j|--home)
            export HOME_DIR="${2}"
            shift 2
            ;;
        -d|--default)
            DEFAULT="true"
            shift
            ;;
        -s|--status)
            SHOW_STATUS="true"
            shift
            ;;
        --)
            shift
            break
            ;;
        *)
            echo "internal error %s" "${0}"
            exit 1
            ;;
    esac
done

if [ "${SHOW_USAGE}" == "true" ]; then
    usage
    exit 0
fi

if ! [ `id -u` = "0" ];then
    echo "Run fly-kiosk from root."
    usage
    exit 2
fi

if [ "${SHOW_STATUS}" == "true" ]; then
    show_status ${USER_NAME}
    exit 0
fi

if [ -z ${ACTION} ]; then
    echo "You should set action." >&2
    usage
    exit 7
fi

if [ -z ${USER_NAME} ]; then
    echo "You should set username." >&2
    usage
    exit 8
else
    if is_logged ${USER_NAME}; then
        echo "User should not be logged in." >&2
        exit 10
    fi
fi

if [ -z ${HOME_DIR} ]; then
    # Use default HOME_DIR location if not set
    export HOME_DIR="/home/${USER_NAME}"
fi

if ! id ${USER_NAME} 1>&1 >/dev/null; then
    echo "No such user ${USER_NAME}" >&2
    exit 9
fi

if ! [ -d ${HOME_DIR}/.fly ]; then
    create_dotfly ${USER_NAME}
fi

if [ "${ACTION}" = "lock" ];then
    if [ "${DEFAULT}" == "true" ]; then
        if is_locked; then
            rm -rf ${HOME_DIR}/.fly
        else
            if ! [ -d ${HOME_DIR}/.fly.nonkiosk ];then
                mv ${HOME_DIR}/.fly ${HOME_DIR}/.fly.nonkiosk
            fi
        fi
        create_dotfly ${USER_NAME}
    fi
    if [ -z $PROG_NAME ]; then
        lock_user ${USER_NAME}
    else
        if programm_is_forbidden ${PROG_NAME}; then
            echo "Programm ${PROG_NAME} could not be used in single application kiosk mode." >&2
            exit 15
        else
            if which ${PROG_NAME} >/dev/null; then
                lock_user ${USER_NAME} ${PROG_NAME}
            else
                echo "No such programm ${PROG_NAME}" >&2
                exit 5
            fi
        fi
    fi
elif [ "${ACTION}" = "unlock" ];then
    unlock_user ${USER_NAME}
    if [ -d ${HOME_DIR}/.fly.nonkiosk ];then
        mv ${HOME_DIR}/.fly.nonkiosk ${HOME_DIR}/.fly
        chown -R ${USER_NAME}:${USER_NAME} ${HOME_DIR}/.fly
    fi
else
    echo "Unknown action ${ACTION}" >&2
    usage
    exit 3
fi
