#!/bin/bash
#
#   install: Installation script for Appweb
#
#   Copyright (c) Embedthis Software LLC, 2003-2013. All Rights Reserved.
#
################################################################################

HOME=`pwd`
FMT=
SITE=localhost
PAGE=/index.html

HOSTNAME=`hostname`
COMPANY="${settings.company}"
PRODUCT="${settings.product}"
NAME="${settings.title}"
VERSION="${settings.version}"
NUMBER="${settings.buildNumber}"
OS="${platform.os}"
CPU="${platform.arch}"
DIST="${platform.dist}"

ROOT_PREFIX="${prefixes.root}"
BASE_PREFIX="${prefixes.base}"
STATE_PREFIX="${prefixes.state}"
APP_PREFIX="${prefixes.app}"
VAPP_PREFIX="${prefixes.vapp}"
BIN_PREFIX="${prefixes.bin}"
SBIN_PREFIX="${prefixes.sbin}"
ETC_PREFIX="${prefixes.etc}"
INC_PREFIX="${prefixes.inc}"
LIB_PREFIX="${prefixes.lib}"
MAN_PREFIX="${prefixes.man}"
WEB_PREFIX="${prefixes.web}"
LOG_PREFIX="${prefixes.log}"
SPL_PREFIX="${prefixes.spool}"
CACHE_PREFIX="${prefixes.cache}"

ABIN="${VAPP_PREFIX}/bin"
AINC="${VAPP_PREFIX}/in"

installbin=Y
runDaemon=Y
headless=${HEADLESS:-0}
HTTP_PORT=80
SSL_PORT=443

PATH="$PATH:/sbin:/usr/sbin"
unset CDPATH
export CYGWIN=nodosfilewarning
CYGWIN=nodosfilewarning

###############################################################################

setup() {
    umask 022
    if [ $OS != windows -a `id -u` != "0" ] ; then
        echo "You must be root to install this product."
        exit 255
    fi
    #
    #   Headless install
    #
    if [ $# -ge 1 ] ; then
        if [ ! -f $1 ] ; then
            echo "Could not find installation config file \"$1\"." 1>&2
            exit 255
        else
            . $1 
            installFiles $FMT
            
            if [ "$installbin" = "Y" ] ; then
                appman stop disable uninstall >/dev/null 2>&1
                patchConfiguration
                appman install
                if [ "$runDaemon" = "Y" ] ; then
                    appman enable start
                fi
            fi

        fi
        exit 0
    fi
    sleuthPackageFormat
    getAccountDetails
    [ "$headless" != 1 ] && echo -e "\n$NAME ${VERSION}-${NUMBER} Installation\n"

}


getAccountDetails() {
    local g u
    #
    #   Select default username
    #
    for u in www-data _www nobody Administrator 
    do
        grep "$u" /etc/passwd >/dev/null
        if [ $? = 0 ] ; then
            username=$u
            break
        fi
    done
    if [ "$username" = "" ] ; then
        echo "Can't find a suitable username in /etc/passwd for $PRODUCT" 1>&2
        exit 255
    fi
    
    #
    #   Select default group name
    #
    for g in www-data _www nogroup nobody Administrators
    do
        grep "$g" /etc/group >/dev/null
        if [ $? = 0 ] ; then
            groupname=$g
            break
        fi
    done
    if [ "$groupname" = "" ] ; then
        echo "Can't find a suitable group in /etc/group for $PRODUCT" 1>&2
        exit 255
    fi
}

sleuthPackageFormat() {
    local name

    FMT=
    name=`createPackageName ${PRODUCT}-bin`
    if [ -x contents ] ; then
        FMT=tar
    else
        for f in deb rpm tgz ; do
            if [ -f ${name}.${f} ] ; then
                FMT=${f%.gz}
                break
            fi
        done
    fi
    if [ "$FMT" = "" ] ; then
        echo -e "\nYou may be be missing a necessary package file. "
        echo "Check that you have the correct $NAME package".
        exit 255
    fi
}

askUser() {
    local finished

    [ "$headless" != 1 ] && echo "Enter requested information or press <ENTER> to accept the default. "

    #
    #   Confirm the configuration
    #
    finished=N
    while [ "$finished" = "N" ]
    do
        [ "$headless" != 1 ] && echo
        installbin=`yesno "Install binary package" "$installbin"`
        if [ "$installbin" = "Y" ] ; then
            runDaemon=`yesno "Start $PRODUCT automatically at system boot" $runDaemon`
            HTTP_PORT=`ask "Enter the HTTP port number" "$HTTP_PORT"`
            SSL_PORT=`ask "Enter the SSL port number" "$SSL_PORT"`
            # username=`ask "Enter the user account for $PRODUCT" "$username"`
            # groupname=`ask "Enter the user group for $PRODUCT" "$groupname"`
        else
            runDaemon=N
        fi
    
        if [ "$headless" != 1 ] ; then
            echo -e "\nInstalling with this configuration:" 
            echo -e "    Install binary package: $installbin"
        
            if [ "$installbin" = "Y" ] ; then
                echo -e "    Start automatically at system boot: $runDaemon"
                echo -e "    HTTP port number: $HTTP_PORT"
                echo -e "    SSL port number: $SSL_PORT"
                # echo -e "    Username: $username"
                # echo -e "    Groupname: $groupname"
            fi
            echo
        fi
        finished=`yesno "Accept this configuration" "Y"`
    done
    [ "$headless" != 1 ] && echo
    
    if [ "$installbin" = "N" ] ; then
        echo -e "Nothing to install, exiting. "
        exit 0
    fi
}

createPackageName() {
    echo ${1}-${VERSION}-${NUMBER}-${DIST}-${OS}-${CPU}
}


# 
#   Get a yes/no answer from the user. Usage: ans=`yesno "prompt" "default"`
#   Echos 1 for Y or 0 for N
#
yesno() {
    local ans

    if [ "$headless" = 1 ] ; then
        echo "Y"
        return
    fi
    echo -n "$1 [$2] : " 1>&2
    while [ 1 ] 
    do
        read ans
        if [ "$ans" = "" ] ; then
            echo $2 ; break
        elif [ "$ans" = "Y" -o "$ans" = "y" ] ; then
            echo "Y" ; break
        elif [ "$ans" = "N" -o "$ans" = "n" ] ; then
            echo "N" ; break
        fi
        echo -e "\nMust enter a 'y' or 'n'\n " 1>&1
    done
}


# 
#   Get input from the user. Usage: ans=`ask "prompt" "default"`
#   Returns the answer or default if <ENTER> is pressed
#
ask() {
    local ans

    default=$2
    if [ "$headless" = 1 ] ; then
        echo "$default"
        return
    fi
    echo -n "$1 [$default] : " 1>&2
    read ans
    if [ "$ans" = "" ] ; then
        echo $default
    fi
    echo $ans
}


removeOld() {
    if [ -x "${ABIN}/uninstall" ] ; then
        appweb_HEADLESS=1 "${ABIN}/uninstall" </dev/null >/dev/null 2>&1
    fi
    rm -f "${APP_PREFIX}/latest"
}

installFiles() {
    local dir pkg doins NAME upper target

    [ "$headless" != 1 ] && echo -e "\nExtracting files ...\n"

    for pkg in bin ; do
        doins=`eval echo \\$install${pkg}`
        if [ "$doins" = Y ] ; then
            upper=`echo $pkg | tr '[:lower:]' '[:upper:]'`
            suffix="-${pkg}"
            NAME=`createPackageName ${PRODUCT}${suffix}`.$FMT
            if [ "$runDaemon" != "Y" ] ; then
                export APPWEB_DONT_START=1
            fi
            if [ "$FMT" = "rpm" ] ; then
                [ "$headless" != 1 ] && echo -e "rpm -Uhv $NAME"
                rpm -Uhv $HOME/$NAME
            elif [ "$FMT" = "deb" ] ; then
                [ "$headless" != 1 ] && echo -e "dpkg -i $NAME"
                dpkg -i $HOME/$NAME >/dev/null
            elif [ "$FMT" = "tar" ] ; then
                target=/
                [ $OS = windows ] && target=`cygpath ${HOMEDRIVE}/`
                [ $OS = windows ] && target=`cygpath ${HOMEDRIVE}/`
                (cd contents ; tar cf - . | (cd $target && tar xBf -))
            fi
        fi
    done

    if [ -f /etc/redhat-release -a -x /usr/bin/chcon ] ; then 
        if sestatus | grep enabled >/dev/nulll ; then
            for f in $ABIN/*.so ; do
                chcon /usr/bin/chcon -t texrel_shlib_t $f 2>&1 >/dev/null
            done
        fi
    fi
    [ "$headless" != 1 ] && echo -e "\nSetting file permissions ..."
    if [ $OS = windows ] ; then
        # Cygwin bug. Chmod fails to stick if not in current directory for paths with spaces
        home=`pwd` >/dev/null
        mkdir -p "$SPL_PREFIX" "$CACHE_PREFIX" "$LOG_PREFIX"
        chmod 777 "$SPL_PREFIX" "$ETC_PREFIX"
        chmod 755 "$WEB_PREFIX"
        cd "$ETC_PREFIX" ; chmod -R g+r,o+r . ; find . -type d -exec chmod 755 "{}" \;
        cd "$APP_PREFIX" ; chmod -R g+r,o+r . ; find . -type d -exec chmod 755 "{}" \;
        cd "$WEB_PREFIX" ; chmod -R g+r,o+r . ; find . -type d -exec chmod 755 "{}" \;
        cd "$ABIN" ; chmod 755 *.dll *.exe
        cd "$SPL_PREFIX" ; chmod 777 . ; chown $username .
        cd "$CACHE_PREFIX" ; chmod 777 . ; chown $username .
        cd "$LOG_PREFIX" ; chmod 777 . ; chown $username .
        cd "$ETC_PREFIX" ; chmod 777 . ; chown $username .
        cd "${home}" >/dev/null
    else
        mkdir -p "$SPL_PREFIX" "$CACHE_PREFIX" "$LOG_PREFIX"
        chown $username "$SPL_PREFIX" "$CACHE_PREFIX" "$LOG_PREFIX"
        chgrp $groupname "$SPL_PREFIX" "$CACHE_PREFIX" "$LOG_PREFIX"
        chmod 755 "$SPL_PREFIX" "$CACHE_PREFIX" "$LOG_PREFIX"
        if [ $OS = macosx ] ; then
            chown root.wheel /Library/LaunchDaemons/com.embedthis.appweb.plist
        fi
    fi
    [ "$headless" != 1 ] && echo
}


patchConfiguration() {
    if [ $OS = windows ] ; then
        echo -e "Documents web\nListen ${HTTP_PORT}\nListenSecure ${SSL_PORT}\nset LOG_DIR log\nset CACHE_DIR cache" >"${ETC_PREFIX}/install.conf"
    else
        echo -e "Documents ${WEB_PREFIX}\nListen ${HTTP_PORT}\nListenSecure ${SSL_PORT}\nset LOG_DIR ${LOG_PREFIX}\nset CACHE_DIR ${CACHE_PREFIX}" >"${ETC_PREFIX}/install.conf"
    fi
}


#
#   Not currently used
#
startBrowser() {
    if [ "$headless" = 1 ] ; then
        return
    fi
    #
    #   Conservative delay to allow appweb to start and initialize
    #
    sleep 5
    [ "$headless" != 1 ] && echo -e "Starting browser to view the $NAME Home Page."
    if [ $OS = windows ] ; then
        cygstart --shownormal http://$SITE:$HTTP_PORT$PAGE 
    elif [ $OS = macosx ] ; then
        open http://$SITE:$HTTP_PORT$PAGE >/dev/null 2>&1 &
    else
        for f in /usr/bin/htmlview /usr/bin/firefox /usr/bin/mozilla /usr/bin/konqueror 
        do
            if [ -x ${f} ] ; then
                sudo -H -b ${f} http://$SITE:$HTTP_PORT$PAGE >/dev/null 2>&1 &
                break
            fi
        done
    fi
}

#
#   Main program for install script
#
setup $*
askUser

if [ "$installbin" = "Y" ] ; then
    [ "$headless" != 1 ] && echo "Disable existing service"
    appman stop disable uninstall >/dev/null 2>&1
    if [ $OS = windows ] ; then
        "$ABIN/appwebMonitor" --stop >/dev/null 2>&1
    fi
fi
removeOld
installFiles $FMT

if [ "$installbin" = "Y" ] ; then
    "$ABIN/appman" stop disable uninstall >/dev/null 2>&1
    patchConfiguration
    "$ABIN/appman" install
    if [ "$runDaemon" = "Y" ] ; then
        "$ABIN/appman" enable
        "$ABIN/appman" start
    fi
fi
if [ $OS = windows ] ; then
    "$ABIN/appwebMonitor" >/dev/null 2>&1 &
else
    echo "Testing ${NAME} connectivity".
    sleep 3
    $ABIN/http -q 127.0.0.1:$HTTP_PORT/index.html >/dev/null 2>&1
    if [ $? != 0 ] ; then
        echo -e "\n${NAME} may not have successfully started. Check /var/log/syslog\n".
        exit 255
    fi
fi
if [ "$headless" != 1 ] ; then
    echo -e "$NAME installation successful."
fi
exit 0
