#!/usr/bin/bash
# zmsetup - This wizard ported from Mageia (thanks)
#
# Description:
# This is a setup wizard for the blackPanther OS installation of ZoneMinder.
# It assumes a default installation using mysql (mariadb) and apache.
# It will check for and if necessary install mysql, start mysql, set up a
# mysql root password and create the ZoneMinder database if
# required, or update an existing one, setting required db permissions.
# It will check the password strength of any passwords created.
# It will set the date.timezone information in php.ini which is required for
# ZoneMinder to run.
# When all is ready it will start Mysql, Apache, and ZoneMinder and if all is
# well it will give the url of the running ZoneMinder server.
#
# Use:-
# After installation of ZoneMinder run this script as root and answer any questions.
# $ rootmod
# # zmsetup
#===================================

confirm()
# User query interface.
{
par=("$@")
rval=3
while [[ $rval > 2 ]]; do
    echo -n ${par[0]}" "${par[1]}" "
    ans= ; rval=
    read ans
    if [[ -z $ans ]] || [[ ${#ans} > 1 ]]; then
        rval=3
    else
        case $ans in
            [${par[2]}]*)
                rval=0
                ;;
            [${par[3]}]*)
                rval=1
                ;;
            [${par[4]}]*)
                rval=2
                ;;
            *)
                rval=3
                ;;
        esac
    fi
done
    return $rval
}

#-----------------------
chkpasswd() {
pw="$1"
result=$(echo "$pw"|/usr/sbin/cracklib-check|cut -d: -f2)
if echo $result|grep OK; then
	return 0
else
	messg="The password is not strong enough, "$result"."
	return 1
fi
}

#-----------------------
getdbver() {
dbver=$(mysql zm -u root -p$passwd  -se "SELECT Value FROM Config WHERE Name = 'ZM_DYN_DB_VERSION'")
}

#-----------------------
# Special case for update from versions < 1.27.0
struc127updt() {
for dir in events images; do
if [[ -d /var/www/html/zm/$dir ]]; then
  if [[ -d /var/lib/zoneminder/$dir ]]; then
    rm -rf /var/lib/zoneminder/$dir/*
  fi
  echo "Moving $dir - this may take some time ..."
  mv /var/www/html/zm/$dir/* /var/lib/zoneminder/$dir
else
  echo "/var/www/html/zm/$dir was already removed"
fi
done
echo "Removing remaining obsolete zoneminder files/folders from web root ..."
rm -rf /var/www/html/zm
echo "Updating cgi path in database ..."
cgipath=$(mysql zm -u root -p$passwd  -se "SELECT Value FROM Config WHERE Name= 'ZM_PATH_ZMS';")
if echo $cgipath | grep -q "zmcgi"; then
   mysql zm -u root -p$passwd  -se "UPDATE Config SET Value = '/zm/cgi-bin/nph-zms' WHERE Name = 'ZM_PATH_ZMS';"
fi
echo "Updating log path in database ..."
logpath=$(mysql zm -u root -p$passwd  -se "SELECT Value FROM Config WHERE Name= 'ZM_PATH_LOGS';")
if [[ "$logpath" != "/var/log/zm" ]]; then
   mysql zm -u root -p$passwd  -se "UPDATE Config SET Value = '/var/log/zm' WHERE Name = 'ZM_PATH_LOGS';"
fi
}

#------------------------
check_mysqld()
{
if [[ $(systemctl status mysqld.service|head -n3|grep Loaded:|tr -s ' '|cut -s -d' ' -f3) != loaded ]]; then
if confirm "mysql is not installed, would you like to install it now?" "[y/n]" "Yy" "Nn"; then
urpmi mysql --no-suggests || { echo "Installation failed - please check network and media sources and re-run zmsetup"; exit 0; }
else
echo "You will need to provide a mysql database yourself - aborting zmsetup"
exit 0
fi
fi
if [[ $(systemctl status mysqld.service|head -n3|grep Active:|tr -s ' '|cut -s -d' ' -f3) != active ]]; then
systemctl start mysqld.service
fi

[[ $(systemctl status mysqld.service|head -n3|grep Active:|tr -s ' '|cut -s -d' ' -f3) = active ]] || \
{ echo -e "Aborting zmsetup, see status message :-\n"; systemctl status mysqld.service; exit 0; } 
}

#------------------------
closeall()
{
systemctl stop zoneminder.service > /dev/null 2>&1
systemctl stop httpd.service > /dev/null 2>&1
systemctl stop mysqld.service > /dev/null 2>&1
}

#------------------------
pass() {
passw=
passw2=
    while true; do  
	read -s -p "New password: " passw
	echo
	chkpasswd $passw || { echo $messg; messg= ; continue; }
	read -s -p  "Repeat password: " passw2
	echo
	[[ "$passw" = "$passw2" ]] || { echo "Passwords differ, please start again"; continue; }
	break
    done
}

#-----------------------
change_mysqld_root_pw() {
new_password="$1"

# Stop mysqld
systemctl stop mysqld

# Start mysqld_safe
echo "Starting mysqld_safe - please wait..."
mysqld_safe  --skip-grant-tables --skip-networking &

RET=1
while [[ RET -ne 0 ]]; do
    sleep 5
    mysql -u root -e "status" > /dev/null 2>&1
    RET=$?
done
echo "mysqld_safe is running"

# Change password
echo "Changing password"
mysql -u root mysql -se "FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED BY '$new_password';"

# Stop mysqld_safe
echo "Stopping mysqld_safe"
[[ -f /var/run/mysqld/mysqld.pid ]] && kill $(cat /var/run/mysqld/mysqld.pid)

# Restart mysqld
systemctl start mysqld.service
}

#-------------------------
getrootpass() {
if mysql -u root -e 'SELECT 1;' > /dev/null 2>&1 ; then
echo -e "You do not appear to have a mysql root password set.\n"
echo -e $messg1
set=0
while [[ $set = 0 ]]; do
pass
passwd=$passw
      if confirm "Set new password now - confirm - OK?" "[y/n]" "Yy" "Nn"; then
	echo "Please wait ..."
    mysql -u root mysql -se "ALTER USER 'root'@'localhost' IDENTIFIED BY '$passwd'; flush privileges;"
	systemctl restart mysqld.service
	set=1
      else
	set=0
      fi
done
else # Root password is already set so ask for it
badpass=0
while true ; do
	read -s -p "Please enter your mysql root password: " passwd
	echo
	[[ ${#passwd} = 0 ]] && continue
	mysql -u root -p$passwd -e 'SELECT 1;' > /dev/null 2>&1
	[[ $? = 0 ]] && break
	badpass=$((badpass+1))
	if [[ $badpass = 1 ]]; then
		echo "After 2 more failed attempts you will be given the option to set a new password"
	fi
	if [[ $badpass > 2 ]] && confirm "Forgotten it? Set a new mysql root password now?" "[y/n]" "Yy" "Nn"; then
	    passw=
		pass
		change_mysqld_root_pw $passw
		passwd=
		badpass=0
		echo -e "\nPassword is now changed"
	fi
done
fi
mysqlpass="-p$passwd"
mysqlrpass="$passwd"
}

updtsql() {
echo -e "Checking mysql database is current, please wait...\n"

mysql_upgrade -u root $mysqlpass || { echo "zmupdate halted due to above error"; exit 1; }
}

#----------------------------
get_cfg() {
if [[ -f /etc/zm/conf.d/03-mga.conf ]]; then
zm_db_name=$(cat /etc/zm/conf.d/03-mga.conf | grep ZM_DB_NAME | cut -d= -f2)
	if [[ ${#zm_db_name} = 0 ]]; then
		zm_db_name=$(cat /etc/zm/zm.conf | grep ZM_DB_NAME | cut -d= -f2)
	fi	
zm_db_user=$(cat /etc/zm/conf.d/03-mga.conf | grep ZM_DB_USER | cut -d= -f2)
		if [[ ${#zm_db_user} = 0 ]]; then
		zm_db_user=$(cat /etc/zm/zm.conf | grep ZM_DB_USER | cut -d= -f2)
	fi
zm_db_pass=$(cat /etc/zm/conf.d/03-mga.conf | grep ZM_DB_PASS | cut -d= -f2)
	if [[ ${#zm_db_pass} = 0 ]]; then
		zm_db_pass=$(cat /etc/zm/zm.conf | grep ZM_DB_PASS | cut -d= -f2)
	fi
fi

}

#----------------------------
chkzmpass()
{
if ! chkpasswd $zm_db_pass; then
echo "Checking the current ZM_USER_PASSWORD..."
echo $messg
messg=
echo -e $messg1
pass
zmpasswd=$passw
passw=
sed -i "s/$zm_db_pass/$zmpasswd/" /etc/zm/conf.d/03-mga.conf
zm_db_pass=$zmpasswd
fi
}

#----------------------------
chkdb()
{
if mysql -u root $mysqlpass $zm_db_name -e 'SELECT 1;' > /dev/null 2>&1 ; then
echo "You already have a ZoneMinder database installed"
zmdb=1
else
zmdb=0
fi

if [[ $zmdb = 1 ]] && confirm "Do you want to re-use it?" "[y/n]" "Yy" "Nn"; then
    getdbver
    if [[ $dbver < 1.27 ]]; then
echo -e "Your ZoneMinder database is at version $dbver.\n\n\
You have recently installed a version of ZoneMinder at or above version 1.27.\n\
The default file structure of ZoneMinder in blackPanther OS changed at version 1.27.\n\
To continue to use your existing database and access stored events, the file structure\n\
needs to be updated.\n\
Before continuing make backups of any important data that may otherwise be lost if this\n\
process fails, which may happen, especially if your file structure is non-standard.\n\
If your events or images folders are mount points then unmount the devices before continuing\n\
as you will need to manually re-configure your fstab.\n\
Read /usr/share/doc/zoneminder/README for more details about the new file layout."
      if confirm "Would you like to read README now?" "[y/n]" "Yy" "Nn"; then
	clear
	cat /usr/share/doc/zoneminder/README.1.27.bP
      fi
      if confirm "Continue to update?" "[y/n]" "Yy" "Nn"; then
	struc127updt
      else
	exit 0
      fi
    fi
    if [[ $dbver < 1.28 ]]; then
	echo "Updating sock path in database ..."
        sockpath=$(mysql zm -u root -p$passwd  -se "SELECT Value FROM Config WHERE Name= 'ZM_PATH_SOCKS';")
        if echo $sockpath | grep -q "/tmp/zm"; then
            mysql zm -u root -p$passwd  -se "UPDATE Config SET Value = '/run/zm' WHERE Name = 'ZM_PATH_SOCKS';"
        fi
        echo "Updating swap path in database ..."
        swappath=$(mysql zm -u root -p$passwd  -se "SELECT Value FROM Config WHERE Name= 'ZM_PATH_SWAP';")
        if echo $swappath | grep -q "/tmp/zm"; then
            mysql zm -u root -p$passwd  -se "UPDATE Config SET Value = '/run/zm' WHERE Name = 'ZM_PATH_SWAP';"
        fi
    fi
echo "Updating database structure where necessary ..."
updt=1
else
reuse=0
fi

if ([[ $zmdb = 1 ]] && [[ $reuse = 0 ]]); then
if confirm "Delete existing ZoneMinder database? OK?"  "[y/n]" "Yy" "Nn"; then
mysql -u root $mysqlpass -e "DROP DATABASE $zm_db_name;"
zmdb=0
else
echo "You must delete the old database before creating a new one - aborting"
exit 0
fi
fi

if [[ $zmdb = 0 ]]; then
echo "Installing a new ZoneMinder database ..."
mysql -u root $mysqlpass < /usr/share/zoneminder/db/zm_create.sql
setperms
fi

[[ $updt = 1 ]] && updtdb
}

setperms()
{
mysql -u root $mysqlpass -e "USE mysql; SET GLOBAL log_bin_trust_function_creators = 1; GRANT ALL PRIVILEGES ON zm.* TO \"$zm_db_user\"@localhost IDENTIFIED BY \"$zm_db_pass\";"
}

updtdb()
{
setperms

zmupdate.pl -u root -p $mysqlrpass
}

chkphp() {
if ! $(grep "^date\.timezone =" /etc/php.d/05_date.ini >/dev/null 2>&1) \
  && ! $(grep "^date\.timezone =" /etc/php.ini >/dev/null 2>&1); then
	echo "You do not appear to have a timezone set for php."
	echo -e "This is required for the Web-UI to work.\n"
	if [[ -f /etc/sysconfig/clock ]]; then
                tz=$(grep "ZONE" /etc/sysconfig/clock|cut -d= -f2)
                if [[ -f /etc/php.d/05_date.ini ]]; then
		  echo "date.timezone = $tz" >> /etc/php.d/05_date.ini
		  echo -e "Added timezone $tz to /etc/php.d/05_date.ini \n"
		else 
		  echo "date.timezone = $tz" >> /etc/php.ini
		  echo -e "Added timezone $tz to /etc/php.ini \n"
		fi
	else
	        echo -e "Automatic timezone detection failed, so you need to \n\
add a line like 'date.timezone = Europe/London' to /etc/php.d/05_date.ini\n\
See http://php.net/manual/en/timezones.php for the full list.\n\n\
Aborting zmsetup - Re-run it after fixing php timezone."
	        exit 1
	fi
fi
}

http_conf() {
if [[ -e /etc/httpd/conf/httpd.conf ]]; then
   cat /etc/httpd/conf/httpd.conf |sed -e 's/^[[:space:]]*//'|grep -v "^#" |grep -wq  ^ScriptAlias > /dev/null 2>&1
      if [[ $? = 0 ]]; then
	echo -e "\nNOTE: You may need to comment out or edit the line beginning 'ScriptAlias' in\n\
in /etc/httpd/httpd.conf if you cannot view streams and see cgi errors in the log.\n\n\
Note that the cgi-bin ScripAlias for ZoneMinder is already set in\n\
/etc/httpd/conf/sites.d/zoneminder.conf\n"
      fi
fi
}

messg1="Passwords should have at least eight characters with no dictionary\n\
words or common sequences.\n\
Please enter a new one now. (hint: write it down first as it will not be displayed)"

# Script main body starts here ================================
clear
# Check we are root
((UID)) && { echo "Sorry, you must run this as root."; exit 1; }
echo -e "*** Welcome to ZoneMinder Setup ***"
# Get some data from zm.conf and/or 03-mga.conf
get_cfg

# Check that a non-default zm user password has been set
chkzmpass

echo "Please wait a moment..."

# Check that mysql is installed and enabled
check_mysqld

# Stop apache mysql and zoneminder services
closeall

# Start mysql
systemctl start mysqld.service

# Check if a mysql root password is set or set one, or replace forgotten one
getrootpass

# Run mariadb_upgrade in case it has been updated
updtsql

# Check for existing zm database and create new or update existing one
chkdb

# Check timezone is set in /etc/php.d/05_date.ini or zm won't run
chkphp

# Warn about ScriptAlias in default httpd.conf
http_conf

# Rename /etc/zm/conf.d/zmcustom.conf if it was created by zmupdate.pl we don't need it
[[ -f /etc/zm/conf.d/zmcustom.conf ]] && mv /etc/zm/conf.d/zmcustom.conf /etc/zm/conf.d/zmcustom.bak

# Start Apache and Zoneminder
systemctl start httpd.service > /dev/null 2>&1 || { echo "Problem starting Apache"; exit 1; }
systemctl start zoneminder.service || { echo "Problem starting ZoneMinder"; exit 1; }
# If we got this far then congratulations are in order!
echo -e "Congratulations - ZoneMinder is now running on your blackPanther OS!\nYou should be able to \
access the ZM Console in your browser using :-\nhttp://$(hostname)/zm" 
