#!/bin/bash
##
## This is the linux fwcontrol script created to deal with Server and Booster version 4.1.1
## Created by Steve Lind on Dec 12 2010
##
INITSCRIPT="/usr/local/etc/filewave/fw-server"
BOOSTER_INITSCRIPT="/usr/local/etc/filewave/fw-booster"

if [[ "$(uname)" = "Darwin" ]]; then
    IS_OSX=t
    APACHE_USER=www
else
    APACHE_USER=apache
fi


# Check that $LANG is set. Django 1.4 will complain if it is not the case.
if [ -z $LANG ]; then
    if [ -z $IS_OSX ] ; then
	export LANG="`locale -a | grep -i en_us | tail -n 1`"
	echo "No LANG set. Using '$LANG' as the default." >&2
    else
        if [ `whoami` == "root" ]; then
		export LANG="`sudo -u $USER defaults read NSGlobalDomain AppleLocale 2>/dev/null  || echo en_US | cut -d@ -f1`.UTF-8"
        else
		export LANG="`(defaults read NSGlobalDomain AppleLocale 2>/dev/null  || echo en_US) | cut -d@ -f1`.UTF-8"
	fi
	if [ -z `locale -ck LC_CTYPE | grep "UTF-8"` ]; then
		export LANG='en_US.UTF-8'
	fi
	echo "No LANG set. Using '$LANG' as the default." >&2
    fi
fi

###############
###Functions###
###############

## MacOS/Booster-specific
function launchOrStart()
{
	LABEL="$1"
	PLIST="$2"

	# if the LABEL item is already loaded in launchctl, then attempt to simply start it
	if launchctl list "$LABEL" >/dev/null 2>&1; then
		launchctl start "$LABEL"
	else
		launchctl load "$PLIST"
		launchctl start "$LABEL"
	fi
}


function getBoosterPid
{
	fpid=`ps -ax | grep /usr/local/sbin/fwbooster | /usr/bin/grep -v grep | awk '{print $1}'`
	if [ -z "$fpid" ]; then
		echo "0"
	fi
	echo "$fpid"
}



function syntaxErr
{
	/bin/echo ""
	/bin/echo "|----------------------|"
	/bin/echo "| Welcome to fwcontrol |"
	/bin/echo "|----------------------|"
	/bin/echo ""
	/bin/echo "Usage: (sudo) fwcontrol <component> <command>"
	/bin/echo ""
	/bin/echo "Examples:"
	/bin/echo ""
	/bin/echo "sudo fwcontrol server stop"
	/bin/echo "sudo fwcontrol client start"
	/bin/echo "sudo fwcontrol booster restart"
	/bin/echo "sudo fwcontrol booster connectedclients"
	/bin/echo "sudo fwcontrol client version"
	/bin/echo "fwcontrol fwgui showKiosk"
    /bin/echo "fwcontrol dashboard start"
	/bin/echo ""
	/bin/echo "MDM:"
	/bin/echo ""
	/bin/echo "sudo fwcontrol mdm adduser [new_user_name]"
	/bin/echo "sudo fwcontrol mdm adddeuser [new_user_name] [realm (default is \"Enroll IOS Device\")]"
	/bin/echo "sudo fwcontrol mdm adddepuser [new_user_name] [realm (default is \"Enroll IOS Device\")]"
	/bin/echo "sudo fwcontrol mdm addadminuser"
	/bin/echo ""
	/bin/echo "Additional Commands:"
	/bin/echo ""
	/bin/echo "sudo fwcontrol server dbcompact"
	/bin/echo "sudo fwcontrol server restore [version]"
	/bin/echo "sudo fwcontrol server resetinventory"
	/bin/echo "sudo fwcontrol server generateSelfSignedCert --create --cn=fqdn [--country COUNTRY] [--state STATE] [--locality LOCALITY] [--organization ORGANIZATION] [--ou ORGANIZATIONAL_UNIT] [--email EMAIL] [--ignore_name_mismatch]"
	/bin/echo "sudo fwcontrol server generateSelfSignedCert --show-pending"
    /bin/echo "sudo fwcontrol server generateSelfSignedCert --install"
	/bin/echo "sudo fwcontrol client status"
	/bin/echo "sudo fwcontrol apache start|stop|restart"
	/bin/echo "sudo fwcontrol postgres start|stop|restart"
	/bin/echo "sudo fwcontrol redis start|stop|restart"
	/bin/echo "sudo fwcontrol nats start|stop|restart"
	/bin/echo "sudo fwcontrol scheduler start|stop|restart"
	/bin/echo "sudo fwcontrol client_monitor start|stop|restart"
	/bin/echo "sudo fwcontrol model_update_service start|stop|restart"
	/bin/echo ""
}

## nats (booster or server)

function natsIsRunning
{
	echo `ps -ax | /usr/bin/egrep -i "/usr/local/sbin/nats-server|/usr/local/filewave/nats/nats-server" | egrep -v 'grep' | wc -l`
}


function stopNats()
{
    if [ -e "$INITSCRIPT" ]; then
         "$INITSCRIPT" stopNats
    fi
    if [ -e "$BOOSTER_INITSCRIPT" ]; then
         "$BOOSTER_INITSCRIPT" stopNats
    fi
    if [ -e /Library/LaunchDaemons/com.filewave.nats-booster.plist ]; then
        NUMPROCS=`natsIsRunning`
        if [ $NUMPROCS -ne 0 ]; then
            /bin/echo "Stopping NATS Daemon"
            /bin/launchctl unload /Library/LaunchDaemons/com.filewave.nats-booster.plist &>/dev/null || true
        fi
    fi
}

function startNats()
{
    if [ -e "$INITSCRIPT" ]; then
         "$INITSCRIPT" startNats
    fi
    if [ -e "$BOOSTER_INITSCRIPT" ]; then
         "$BOOSTER_INITSCRIPT" startNats
    fi
    if [ -e /Library/LaunchDaemons/com.filewave.nats-booster.plist ]; then
        NUMPROCS=`natsIsRunning`
        if [ $NUMPROCS -eq 0 ]; then
            /bin/echo "Starting NATS Daemon"
            launchOrStart com.filewave.nats-booster /Library/LaunchDaemons/com.filewave.nats-booster.plist
        fi
    fi
}

function restartNats()
{
    if [ -e "$INITSCRIPT" ]; then
         "$INITSCRIPT" restartNats
    fi
    if [ -e "$BOOSTER_INITSCRIPT" ]; then
         "$BOOSTER_INITSCRIPT" restartNats
    fi
    if [ -e /Library/LaunchDaemons/com.filewave.nats-booster.plist ]; then
        /bin/launchctl unload /Library/LaunchDaemons/com.filewave.nats-booster.plist &>/dev/null || true
	launchOrStart com.filewave.nats-booster /Library/LaunchDaemons/com.filewave.nats-booster.plist
    fi
}


##Postgres

startPostgres()
{
    if [ ! -z $IS_OSX ]; then
        FOUND=`/usr/bin/dscl . -search /Users RecordName postgres`
 	if [ -z "$FOUND" ]; then
            printf "Creating new user account postgres as alias to _postgres\n"
            /usr/bin/dscl . -merge Users/_postgres RecordName postgres
 	fi
    fi

    "$INITSCRIPT" startPostgres
}

stopPostgres()
{
	"$INITSCRIPT" stopPostgres
}

restartPostgres()
{
	"$INITSCRIPT" restartPostgres
}

## Client Monitor

function startClientMonitor()
{
    "$INITSCRIPT" startClientMonitor
}

function stopClientMonitor()
{
    "$INITSCRIPT" stopClientMonitor
}

function restartClientMonitor()
{
    "$INITSCRIPT" restartClientMonitor
}

## Model Update

function startModelUpdateService()
{
    	"$INITSCRIPT" startModelUpdateService
}

function stopModelUpdateService()
{
    	"$INITSCRIPT" stopModelUpdateService
}

function restartModelUpdateService()
{
    	"$INITSCRIPT" restartModelUpdateService
}

##Server

#
# the following functions 'echo' their output, rather than returning it - since
# PID values can be greater than 128 (the limit of values sent via 'return')
#

function startServer
{
	"$INITSCRIPT" start
}

function stopServer
{
	"$INITSCRIPT" stop
}

function restartServer
{
	"$INITSCRIPT" restart
}

function openServerFirewall()
{
	"$INITSCRIPT" openfirewall
}

function closeServerFirewall()
{
	"$INITSCRIPT" closefirewall
}

function dbCompact
{
	"$INITSCRIPT" compact
}

function dbMigrate
{
	"$INITSCRIPT" migrate
}

restoreModel()
{
	/usr/local/sbin/fwxserver -restore $1
}

dbResetInventory()
{
    /usr/local/sbin/fwxserver -resetInventory
}

function versionServer
{
	"$INITSCRIPT" version
}


# MDM

function addMDMUser()
{
	if [ ! -e '/usr/local/filewave/apache/passwd/passwords' ]; then
		touch '/usr/local/filewave/apache/passwd/passwords'
	fi

	/usr/local/filewave/apache/bin/htpasswd /usr/local/filewave/apache/passwd/passwords $1
}

function addDEUser()
{
	[ -e '/usr/local/filewave/apache/passwd/passwords.digest' ] || PARAMS="-c"

	REALM=$2
	[ ! -z $REALM ] || REALM="Enroll IOS Device" #default value

	/usr/local/filewave/apache/bin/htdigest $PARAMS /usr/local/filewave/apache/passwd/passwords.digest "$REALM" $1
}

function addDjangoUser()
{
	/usr/local/filewave/python/bin/python /usr/local/filewave/django/manage.pyc createsuperuser
}

function restartMDMGracefully()
{
	/usr/local/filewave/apache/bin/apachectl graceful
	restartClientMonitor
}

## Booster

function startBooster
{
    if [ -z $IS_OSX ]; then
	$BOOSTER_INITSCRIPT start
    else
	if [ $EUID -ne 0 ]; then
		echo "Superuser credentials needed. Try with sudo. FileWave Booster not started."
		return
	fi
	/bin/echo "Starting FileWave Booster..."

	if [ -e /private/var/FWBooster/Data\ Folder ]; then
		fpid=`getBoosterPid`
	    	if [ $fpid -eq 0 ]; then
			launchOrStart com.filewave.fwbooster /Library/LaunchDaemons/com.filewave.fwbooster.plist
			launchOrStart com.filewave.pushprox-client /Library/LaunchDaemons/com.filewave.pushprox-client.plist
			startNats
			for i in {1..50}; do
				if [ -f "/Library/Preferences/com.filewave.Booster.plist" ]; then
					launchOrStart com.filewave.node-exporter /Library/LaunchDaemons/com.filewave.node-exporter.plist
				fi
			done
		else
    			/bin/echo "FileWave Booster is already running"
    		fi
	else
		/bin/echo "Error: No \"/private/var/FWBooster/Data Folder\". FileWave Booster did not start"
	fi
    fi
}

function stopBooster()
{
    if [ -z $IS_OSX ]; then
	$BOOSTER_INITSCRIPT stop
    else
	/bin/echo "Stopping FileWave Booster ..."
	RUNNING=0
	fpid=`getBoosterPid`
	if [ $fpid -ne 0 ]; then
		/bin/launchctl unload /Library/LaunchDaemons/com.filewave.fwbooster.plist &>/dev/null
		/bin/launchctl unload /Library/LaunchDaemons/com.filewave.pushprox-client.plist &>/dev/null
		stopNats
        	/bin/launchctl unload /Library/LaunchDaemons/com.filewave.node-exporter.plist &>/dev/null
		RUNNING=1
	fi
	rm -f /private/var/run/fwbooster.pid
    fi
}

function restartBooster()
{
    if [ -z $IS_OSX ]; then
	$BOOSTER_INITSCRIPT restart
    else
	/bin/echo "Restarting FileWave Booster"
	stopBooster
	/bin/sleep 3
	startBooster
    fi
}

function startDashboard()
{
    $INITSCRIPT startDashboard		
}

function stopDashboard()
{
    $INITSCRIPT stopDashboard
}

function restartDashboard()
{
    $INITSCRIPT restartDashboard
}


function startGrafana()
{
    $INITSCRIPT startGrafana
}

function stopGrafana()
{
    $INITSCRIPT stopGrafana
}

function restartGrafana()
{
	  stopGrafana
		startGrafana
}



function versionBooster
{
    if [ -z $IS_OSX ]; then
	$BOOSTER_INITSCRIPT version
    else
        /usr/local/sbin/fwbooster -V
    fi
}

function statusBooster
{
    if [ -z $IS_OSX ]; then
        $BOOSTER_INITSCRIPT status
    else
	booster_Pid=`ps -ax | grep /usr/local/sbin/fwbooster | /usr/bin/grep -v grep | awk '{print $1}'`
        if [ -z "$booster_Pid" ]; then
                echo "not running"
        else
        	echo "running"
        fi
    fi
}

function openBoosterFirewall()
{
	$BOOSTER_INITSCRIPT openfirewall
}

function closeBoosterFirewall()
{
	$BOOSTER_INITSCRIPT closefirewall
}

connectedClients()
{
    if [ -z $IS_OSX ]; then
	ss -an | grep 20014
    else
	netstat -an | grep 20014
    fi
}

function generateSelfSignedCert()
{
	/usr/local/filewave/python/bin/python /usr/local/filewave/django/manage.pyc create_mdm_self_signed_cert "$@"
	RESULT=$?
	if [[ $RESULT -eq 0 && $@ == *"--install"* ]];
	then
    	echo "running restart apache command"
	    /usr/local/filewave/apache/bin/apachectl
	    restartClientMonitor
	fi
	# take care of permissions - certs and logs that may have been changed by sudo python
	chown $APACHE_USER:$APACHE_USER /usr/local/filewave/certs/* /usr/local/filewave/log/*
}

## fwgui (MacOS only)
function execForAllUsers
{
    local osMajorVersion=$(uname -r |cut -d '.' -f 1)
	for user_pid in $USER_SESSIONS; do
		current_user=$(echo $user_pid |cut -d ',' -f 1)
		loginwindow_pid=$(echo $user_pid |cut -d ',' -f 2)
		# Change to launchctl call from El Capitan onwards.
		# Note that quoting differs too.
		if [ "$osMajorVersion" -ge 15 ]
		then /bin/launchctl asuser $(id -u "$current_user") $*
		else /bin/launchctl bsexec "$loginwindow_pid" sudo -u "$current_user" $*
		fi
	done
}

function numfwGUIProcesses
{
	# the form: -o pid,comm is a Tiger only thing, command work on 10.3.9 as well
	NUM=`ps -ax -o pid,command | /usr/bin/grep -v grep | /usr/bin/grep -i 'MacOS/fwGUI' | wc -l`
	echo $NUM
}


function restartFWGUI
{
	# KeepAlive is true, the process will be restarted automatically by the OS
	killall "FileWave Kiosk" >/dev/null 2>&1
	#as fwGUI has KeepAlive set to true, we just need to kill the process and they will be restarted automatically
	killall fwGUI >/dev/null 2>&1
	sleep 3
	if [ `numfwGUIProcesses` -eq 0 ]; then
		# it seems it as unable to start the fwGUI processes again, so let's restart them manually
		execForAllUsers /bin/launchctl unload -S Aqua /Library/LaunchAgents/com.filewave.fwGUI.plist
		execForAllUsers /bin/launchctl load -S Aqua /Library/LaunchAgents/com.filewave.fwGUI.plist
	fi
}

function showKiosk
{
	if [ $EUID -eq 0 ]; then
		/bin/echo "This command cannot be run with the root user; try again without sudo."
	elif [ `numfwGUIProcesses` -eq 0 ]; then
		/bin/echo "The FileWave GUI process is not running, cannot show the Kiosk."
	else
		/usr/local/sbin/FileWave.app/Contents/Resources/fwGUI.app/Contents/MacOS/fwGUI -showKiosk &
	fi
}

## client ((MacOS only)
function getClientPid
{
	fpid=`ps -ax | /usr/bin/grep /MacOS/fwcld$ | /usr/bin/grep -v grep | awk '{print $1}'`

	if [ -z "$fpid" ]; then
		echo "0"
	fi

	echo "$fpid"
}

function startClient
{
    fpid=`getClientPid`

    if [ $fpid -eq 0 ]; then
        /bin/echo "Starting FileWave Client"
        launchOrStart com.filewave.fwcld /Library/LaunchDaemons/com.filewave.fwcld.plist
    else
        /bin/echo "FileWave Client is already running"
    fi
}

function stopClient
{
    fpid=`getClientPid`

    if [ $fpid -ne 0 ]; then

        /bin/echo "Stopping FileWave Client"

        /bin/launchctl unload /Library/LaunchDaemons/com.filewave.fwcld.plist
        /bin/sleep 2

        /usr/bin/killall fwcld >/dev/null 2>&1
        fpid=`getClientPid`
        if [ $fpid -ne 0 ]; then
            /bin/sleep 3
            fpid=`getClientPid`
            if [ $fpid -ne 0 ]; then
                /bin/echo "The FileWave Client Daemon could not be shut down gracefully in a timely manner.  Aborting fwcld..."
                /bin/kill -9 "$fpid" >/dev/null 2>&1
            fi
        fi
    fi
}

function restartClient
{
	stopClient
	/bin/sleep 3
	startClient
}

function versionClient
{
	/usr/local/sbin/FileWave.app/Contents/MacOS/fwcld -V
}

function clientStatus
{
	/usr/local/sbin/FileWave.app/Contents/MacOS/fwcld -s
}



##########################
##Command Interpretation##
##########################
if [ "$1" = "fwgui" ] && [ ! -z $IS_OSX ]; then
	case "$2"
	in
		"restart")
			echo "running restart GUI command"
			restartFWGUI
			;;
		"showKiosk")
			echo "attempting to show the FileWave Kiosk"
			showKiosk
			;;
		*) syntaxErr;;
	esac
elif [ "$1" = "client" ] && [ ! -z $IS_OSX ]; then

	if [ "$2" = "start" ]; then
		startClient
	elif [ "$2" = "stop" ]; then
		stopClient
	elif [ "$2" = "restart" ]; then
		restartClient
	elif [ "$2" = "version" ]; then
		versionClient
	elif [ "$2" = "status" ]; then
		clientStatus
	else
		syntaxErr
	fi
elif [ "$1" = "scheduler" ]; then
	case "$2"
	in
		"start")
			echo "running start scheduler command"
			$INITSCRIPT startScheduler
			;;
		"stop")
			echo "running stop scheduler command"
			$INITSCRIPT stopScheduler
			;;
		"restart")
			echo "running restart scheduler command"
			$INITSCRIPT restartScheduler
			;;
			*) syntaxErr
			;;
	esac
elif [ "$1" = "apache" ]; then
	case "$2"
	in
		"start")
			echo "running start apache command"
			$INITSCRIPT startApache
			;;
		"stop")
			echo "running stop apache command"
			$INITSCRIPT stopApache
			;;
		"restart")
			echo "running restart apache command"
			$INITSCRIPT restartApache
			;;
			*) syntaxErr
			;;
	esac
elif [ "$1" = "postgres" ]; then
	case "$2"
	in
		"start")
			echo "running start postgres command"
			startPostgres
			;;
		"stop")
			echo "running stop postgres command"
			stopPostgres
			;;
		"restart")
			echo "running restart postgres command"
			restartPostgres
			;;
		*) syntaxErr
			;;
	esac
elif [ "$1" = "redis" ]; then
	case "$2" in
		start)   "$INITSCRIPT" startRedis ;;
		stop)    "$INITSCRIPT" stopRedis ;;
		restart) "$INITSCRIPT" restartRedis ;;
		*) syntaxErr ;;
	esac
elif [ "$1" = "nats" ]; then
	case "$2" in
		start)   startNats ;;
		stop)    stopNats ;;
		restart) restartNats ;;
		*) syntaxErr ;;
	esac
elif [ "$1" = "client_monitor" ]; then
	if [ "$2" = "start" ]; then
		startClientMonitor
	elif [ "$2" = "stop" ]; then
		stopClientMonitor
	elif [ "$2" = "restart" ]; then
		restartClientMonitor
	else
		syntaxErr
	fi

elif [[ "$1" = "model_update_service" ]]; then
	if [ "$2" = "start" ]; then
		startModelUpdateService
	elif [ "$2" = "stop" ]; then
		stopModelUpdateService
	elif [ "$2" = "restart" ]; then
		restartModelUpdateService
	else
		syntaxErr
	fi
elif [ "$1" = "server" ]; then
	if [ -x "/usr/local/sbin/fwxserver" ]; then
		if [ "$2" = "start" ]; then
			startServer
		elif [ "$2" = "stop" ]; then
			stopServer
		elif [ "$2" = "restart" ]; then
			restartServer
		elif [ "$2" = "openfirewall" ]; then
			openServerFirewall
		elif [ "$2" = "closefirewall" ]; then
			closeServerFirewall
		elif [ "$2" = "version" ]; then
			versionServer
		elif [ "$2" = "dbcompact" ]; then
			dbCompact
		elif [ "$2" = "restore" -a ! -z "$3" ]; then
			restoreModel $3
		elif [ "$2" = "migrate" ]; then
			dbMigrate
		elif [ "$2" = "resetinventory" ]; then
			dbResetInventory
        elif [ "$2" = "generateSelfSignedCert" ]; then
            shift; shift;
            generateSelfSignedCert "$@"
		else
			syntaxErr
		fi
	else
		echo "The FileWave server is not installed."
	fi

elif [ "$1" = "mdm" ]; then
	if [ -x "/usr/local/filewave/apache/bin/httpd" ]; then
		if [ "$2" = "adduser" -a ! -z "$3" ]; then
			addMDMUser $3
		elif [ "$2" = "adddeuser" -a ! -z "$3" ]; then
			addDEUser $3 $4
		elif [ "$2" = "adddepuser" -a ! -z "$3" ]; then
			addDEUser $3 $4
		elif [ "$2" = "addadminuser" ]; then
			addDjangoUser $3
		elif [ "$2" = "graceful" ]; then
			restartMDMGracefully
		else
			syntaxErr
		fi
	else
		echo "The FileWave MDM server is not installed."
	fi

elif [ "$1" = "booster" ]; then
	if [ -x "/usr/local/sbin/fwbooster" ]; then
	if [ "$2" = "start" ]; then
		startBooster
	elif [ "$2" = "stop" ]; then
		stopBooster
	elif [ "$2" = "restart" ]; then
		restartBooster
	elif [ "$2" = "openfirewall" ]; then
		openBoosterFirewall
	elif [ "$2" = "closefirewall" ]; then
		closeBoosterFirewall
	elif [ "$2" = "version" ]; then
		versionBooster
	elif [ "$2" = "running" ]; then
		statusBooster
	elif [ "$2" = "connectedclients" ]; then
		connectedClients
	else
		syntaxErr
	fi
	else
	echo "The FileWave booster is not installed."
	fi
elif [ "$1" = "dashboard" ]; then
    case "$2"
    in
        "start")
            startDashboard
            ;;
        "stop")
            stopDashboard
            ;;
        "restart")
            restartDashboard
            ;;
        *) syntaxErr
            ;;
        esac
elif [ "$1" = "grafana" ]; then
	case "$2"
	in
		"start")
			startGrafana
			;;
		"stop")
			stopGrafana
			;;
		"restart")
			restartGrafana
			;;
			*) syntaxErr
			;;
	esac

else syntaxErr

fi

