#!/bin/bash

# Mit diesem Skript lässt sich auf einem Ubuntu-System eine OrderSprinter-System bestehend aus Kernapplikation,
# Javaprinter, TSEConnector (Simulationsmodus) sowie nächtlichem Backup auf einem angeschlossenen USB-Stick 
# einrichten.
# Das Skript sollte auf einem frischen Ubuntu-System ausgeführt werden, da es bestehende Daten und Konfigurationen
# ändert.

# Allgemeine Zugangsdaten zur Datenbank. Diese Werte können frei geändert werden. Allerdings darf das Passwort keine
# Zeichen enthalten, die in der URL als Argumenttrenner verwendet werden (?,&). Die Passwörter werden dem Intaller
# im Klartext übergeben und landen in der Regel im Log des Webservers. 
dbadminpassword="anadminpass_1"
db="ordersprinter"
dbuser="os_"
dbuserpassword="dbpass"
tabprefix="os_"
remoteaccesscode="please_change"

# Dies ist der Geräteadresse (USB-Port) des Speichermediums (z.B. USB-Stick, SD-Karte, SSD/HDD), auf den das
# nächtliche Backup geschrieben werden soll. Um diese Adresse herauszufinden, kann man das Speichermedium anstecken
# und über das Kommando "df" diese Adresse herausfinden. Wichtig ist, dass man nicht den Adresse der TSE eingibt,
# denn die TSE sollte unter keinen Umständen direkt beschrieben werden.
# Wenn man die Device-Adresse (sdxx) statt einem Label (Name des Mediums bei dessen Formatierung) angibt, darf man
# den Stick später nicht in einen anderen USB-Port stecken!
# ACHTUNG: Statt "/" muss ein "\/" eingetragen werden:
backupdevice="\/dev\/sdb1"

# Währung
currency="Euro"

# TSEConnector-Einstellungen:
# ---------------------------

# Nach dem Einstecken der TSE zeigt sich diese wie ein normales Laufwerk, der üblicherweise in /mnt eingebunden wird.
# Aber um das Skript möglichst einfach an andere Linux-Distros anpassen zu können, kann der Mountpoint hier eingestellt
# werden. Manche Distros nutzen z.B. /media zum Einbinden. Zudem können zukünftige TSEs andere Namen haben.
tsemountpoint="/mnt/SWISSBIT"

# Die TSE kann vom TSEConnector simulatiert werden. In diesem Fall ist der tsemodus auf "simulate" zu setzen.
tsemodus="normal"

# Der TSEConnector ist als Webserver aufgesetzt, der auf den mit tseport festgelegten Port lauscht. Wenn dieser Wert
# geändert wird, so muss dies später in der Konfiguration der Kernapplikation händisch angepasst werden.
# Dieser Port muss auf dem System möglicherweise in den Firewalleinstellungen erst freigeschaltet werden, damit
# Kernapplikation und TSEConnector miteinander kommunizieren können.
tseport=8000

##########################################################################################
#
#   Ende des Bereichs, in dem ein unerfahrener Anwender Anpassungen vornehmen sollte.
#
#########################################################################################

# OrderSprinter-Version
version="2_3_6"

# Warnhinweis an den Anwender mit der Möglichkeit des Abbruchs
echo "Dieses Skript ist für die Ausführung auf einem frisch aufgesetzten"
echo "Ubuntu-System 20.04 geschrieben worden. Bei anderen Ubuntu-Versionen"
echo "müssen möglicherweise Pfade im Skript angepasst werden!"
echo "Man kann es auch auf einem bereits in Benutzung befindlichen Ubuntu-"
echo "System verwenden, allerdings kann es dabei zu Datenverlust kommen:"
echo ""
echo "Das Installationsskript löscht möglicherweise bereits vorhandene Daten"
echo "im Dokumentenverzeichnis des Webservers. Außerdem werden Daten in"
echo "verschiedene Verzeichnisse geschrieben (z.B. /usr/local/bin) und"
echo "Konfigurationsdateien abgeändert (z.B. php.ini), und Services"
echo "angelegt."
echo "Es wird eine Datenbank angelegt und eine möglicherweise bereits"
echo "DB-Konfiguration sowie eine Datenbank mit Namen '$db'"
echo "überschrieben!"
echo ""
echo "Es können andere als die vordefinierten Zugangsdaten zur Datenbank"
echo "verwendet werden. Dazu sind die Werte für die Variablen in diesem "
echo "Skript anzupassen (dbadminpassword,db,dbuser,dbusertpassword,"
echo "tabprefix)."
echo "Außerdem ist vermutlich die Voreinstellung für die Geräteadresse des"
echo "Backup-Mediums anzupassen."
echo ""
echo "Das Skript muss als root ausgeführt werden!"
echo ""

if [[ $EUID -ne 0 ]]; then
    echo "Das Skript wurde nicht mit root-Rechten gestartet. Die Ausführung muss abgebrochen werden."
    exit 1
fi


# Frage wegen Installationsumfang
installcore=0
echo "Kernapplikation installieren? Alle anderen Installationsoptionen basieren"
echo "darauf, dass die Kernapplikation so aufgesetzt ist, wie im Skript festgelegt."
read -p "Soll das Skript die Kernapplikation installieren (j/n)?" installcore
case "$installcore" in
  j|J ) installcore=1;;
  * ) installcore=0;;
esac

installprintserver=0
read -p "Soll das Skript den Javaprintserver installieren (j/n)?" installprintserver
case "$installprintserver" in
  j|J ) installprintserver=1;;
  * ) installprintserver=0;;
esac

insertsamplecontent=0
read -p "Beispieldaten einfügen (Benutzer, Raumplan usw.). Beispieldaten sollten nur in eine frischen Installation eingefügt werden, z.B. im Zusammenhang mit einer Installation des Kernsystems. Einfügen? (j/n)?" samplecontent
case "$samplecontent" in
  j|J ) insertsamplecontent=1;;
  * ) insertsamplecontent=0;;
esac

# Frage Benutzer, ob das TSE-Modul installiert werden soll
install_tse=0
read -p "TSEConnector einrichten (j/n)?" choice
case "$choice" in
  j|J ) install_tse=1;;
  * ) install_tse=0;;
esac

# Frage Benutzer, ob regelmäßiges Backup auf einen angeschlossenen USB-Stick stattfinden soll
autobackup=0
read -p "Regelmäßiges nächtliches Backup um 4 Uhr auf angeschlossenen USB-Stick (j/n)?" dobackup
case "$dobackup" in
  j|J ) autobackup=1;;
  * ) autobackup=0;;
esac

# Calculate availabe RAM that can be assigned to PHP process
ramsize=$(eval "free -t | grep -oP '\d+' | sed '1!d'")
avail=$((ramsize/1000-500))M
echo "Assigning $avail of memory for PHP processes"

# Download der OrderSprinter-Applikation und Entpacken in ein temporäres Verzeichnis
echo "Download der OrderSprinter-Suite ($version)"
rm -rf /tmp/ordersprinter 2> /dev/null
mkdir /tmp/ordersprinter

# Get the path in which the script is located.
scriptpath="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"

if test -d "${scriptpath}/../webapp"; then
        # script is not moved out of the download, i.e. there is no need to download the software again
        cp -R ${scriptpath}/../* /tmp/ordersprinter
else
        # Script is standalone
        echo "Download der OrderSprinter Programmsuite..."
        wget -O /tmp/ordersprinter/os.zip 2>>/dev/null "https://www.ordersprinter.de/ordersprinter-${version}.zip?edition=ubuntu"

	cd /tmp/ordersprinter
	echo "Entpacken der OrderSprinter-Suite"
	unzip -q os.zip
fi

if [[ $installcore -eq 1 ]]
then
	# Installation der Umgebung
	echo "Update der Umgebung. Dies wird eine Zeitlang dauern..."
	echo "Paketlisten neu einlesen und aktualisieren..."
	apt-get -y update
	echo "Neue Versionen von Paketen installieren, falls Aktualisierungen vorhanden sind..."
	apt-get -y upgrade
	echo "Installation von Webserver und Datenbank..."
	apt-get -qq -y install unzip apache2 libapache2-mod-php php mariadb-server php-mysql php-gd php-curl php-zip php-xml default-jre
	mysqladmin -u root password $dbadminpassword 

	# Konfigurationswerte
	PHPVERSION=$(ls /etc/php)
	echo "Anpassen einiger Konfigurationswerte"
	sed -i -e "s/memory_limit.*/memory_limit = $avail/" /etc/php/${PHPVERSION}/apache2/php.ini
	sed -i -e "s/max_execution_time.*/max_execution_time = 600/" /etc/php/${PHPVERSION}/apache2/php.ini
	sed -i -e "s/post_max_size.*/post_max_size = 10000M/" /etc/php/${PHPVERSION}/apache2/php.ini
	sed -i -e "s/upload_max_filesize.*/upload_max_filesize = 10000M/" /etc/php/${PHPVERSION}/apache2/php.ini
	service apache2 reload
	sleep 3s

	echo "Create database"
	mysql -uroot -p$dbadminpassword -e "DROP DATABASE IF EXISTS $db";
	mysql -uroot -p$dbadminpassword -e "CREATE DATABASE $db DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci";
	mysql -uroot -p$dbadminpassword -e "DROP USER IF EXISTS $dbuser@localhost";
	mysql -uroot -p$dbadminpassword -e "CREATE USER $dbuser@localhost IDENTIFIED BY '$dbuserpassword'";
	mysql -uroot -p$dbadminpassword -e "GRANT ALL ON $db.* TO $dbuser@localhost";

	echo "Copy files to webserver doc directory"
	rm -r /var/www/html/index.html
	cp -R /tmp/ordersprinter/webapp/* /var/www/html/
	chown -R www-data:www-data /var/www/html 
	chmod -R u+w /var/www/html
	cd /var/www/html/php

	echo "Konfiguration des Datenbankzugangs"
	sed -i -e "s/defined('MYSQL_USER').*/defined('MYSQL_USER') || define ('MYSQL_USER', '$dbuser');/" config.php
	sed -i -e "s/defined('MYSQL_PASSWORD').*/defined('MYSQL_PASSWORD') || define ('MYSQL_PASSWORD', '$dbuserpassword');/" config.php
	sed -i -e "s/defined('MYSQL_DB').*/defined('MYSQL_DB') || define ('MYSQL_DB', '$db');/" config.php
	sed -i -e "s/defined('TAB_PREFIX').*/defined('TAB_PREFIX') || define ('TAB_PREFIX', '$tabprefix');/" config.php
	echo "Default-Installation der Kernapplikation"
	wget -O /tmp/loginstall.txt 2>>/dev/null "http://localhost/install/installer.php?command=defaultinstall&db=${db}&dbuser=${dbuser}&dbpass=${dbuserpassword}&prefix=${tabprefix}"

	# Währung
	mysql -uroot -p$dbadminpassword -e "UPDATE $db.${tabprefix}config SET setting='${currency}' WHERE name='currency'";
	mysql -uroot -p$dbadminpassword -e "UPDATE $db.${tabprefix}histconfig SET setting='${currency}' WHERE setting='Euro'";
fi

if [[ $insertsamplecontent -eq 1 ]]
then
    echo "Beispieldaten einfügen"
    wget -O /tmp/logsamplecontent.txt 2>>/dev/null "http://localhost/install/installer.php?command=defaultinsertsamplecontent&db=${db}&dbuser=${dbuser}&dbpass=${dbuserpassword}&prefix=${tabprefix}"
fi

echo "Löschen des Installationsverzeichnisses"
rm -r /var/www/html/install

if [[ $installprintserver -eq 1 ]]
then
	echo "Druckserver einrichten"
	cp -R /tmp/ordersprinter/printserver/javaprinter /usr/local/bin
	echo "#!/bin/sh" > /usr/local/bin/javaprinter.bat  
	echo "/usr/bin/java -jar /usr/local/bin/javaprinter/javaprinter.jar -configfile=/usr/local/bin/javaprinter/config.json &" >> /usr/local/bin/javaprinter.bat
	chmod +x /usr/local/bin/javaprinter.bat

	printf "[Unit]\n" > /etc/systemd/system/javaprinter.service
	printf "Description=OrderSprinter-Javaprinter\n\n" >> /etc/systemd/system/javaprinter.service
	printf "[Service]\n" >> /etc/systemd/system/javaprinter.service
	printf "Type=forking\n" >> /etc/systemd/system/javaprinter.service
	printf "ExecStart=/usr/local/bin/javaprinter.bat\n\n" >> /etc/systemd/system/javaprinter.service
	printf "[Install]\n" >> /etc/systemd/system/javaprinter.service
	printf "WantedBy=multi-user.target\n" >> /etc/systemd/system/javaprinter.service

	systemctl enable javaprinter.service
	systemctl start javaprinter
fi

if [[ $install_tse -eq 1 ]]
then     
    # TSE
    echo "TSE Setup"
    cp -R /tmp/ordersprinter/tseconnector /usr/local/bin

    echo "#!/bin/sh" > /usr/local/bin/tseconnector.bat  
    echo "/usr/bin/java -Djava.library.path=/usr/local/bin/tseconnector/swissbit/nativelibs/linux64 -jar /usr/local/bin/tseconnector/swissbit/tseconnector.jar --pass=123 --port=${tseport} --supplier=swissbit --mountpoint=${tsemountpoint} --mode=${tsemodus} --loglevel=1 --showlog=1 --tarexportfile=/tmp/tse_export.tar &" >> /usr/local/bin/tseconnector.bat
    chmod +x /usr/local/bin/tseconnector.bat

    printf "[Unit]\n" > /etc/systemd/system/tseconnector.service
    printf "Description=OrderSprinter-TSEConnector\n\n" >> /etc/systemd/system/tseconnector.service
    printf "[Service]\n" >> /etc/systemd/system/tseconnector.service
    printf "Type=forking\n" >> /etc/systemd/system/tseconnector.service
    printf "ExecStart=/usr/local/bin/tseconnector.bat\n\n" >> /etc/systemd/system/tseconnector.service
    printf "[Install]\n" >> /etc/systemd/system/tseconnector.service
    printf "WantedBy=multi-user.target\n" >> /etc/systemd/system/tseconnector.service

    systemctl enable tseconnector.service
    systemctl start tseconnector

    # Lasst uns nun den TSEConnector aktivieren:
    mysql -uroot -p$dbadminpassword -e "UPDATE ${db}.${tabprefix}config SET setting='1' WHERE name='usetse'";
    # In Deutschland gibt es eine Bonausgabepflicht:
    mysql -uroot -p$dbadminpassword -e "UPDATE ${db}.${tabprefix}config SET setting='1' WHERE name='forceprint'";
fi

if [[ $autobackup -eq 1 ]]
then
    echo "Nächtliches Backup einrichten"
    cp /tmp/ordersprinter/scripts/backup-db-linux.sh /usr/local/bin/
    sed -i -e "s/Benutzer/$dbuser/" /usr/local/bin/backup-db-linux.sh
    sed -i -e "s/DasPasswort/$dbuserpassword/" /usr/local/bin/backup-db-linux.sh
    sed -i -e "s/123/$remoteaccesscode/" /usr/local/bin/backup-db-linux.sh
    sed -i -e "s/localhost\/ordersprinter/localhost/" /usr/local/bin/backup-db-linux.sh
    sed -i -e "s/mount=.*/mount=\"${backupdevice}\"/" /usr/local/bin/backup-db-linux.sh
    mysql -uroot -p$dbadminpassword -e "UPDATE ${db}.${tabprefix}config SET setting=MD5('$remoteaccesscode') WHERE name='remoteaccesscode'";

    # Passe die Crontab an, damit der Job jede Nacht um 4 Uhr läuft
    cp /etc/crontab /tmp/crontab
    # Entferne einen Eintrag von einem möglicherweise vorherigen Scriptlauf
    sed -i -e "/.*backup-db-linux.*/d" /tmp/crontab
    # Lösche letzte Zeile (sollte ein Hash sein)
    sed '$d' /tmp/crontab > /tmp/crontab_without_last_line; mv /tmp/crontab_without_last_line /tmp/crontab
    # Füge neuen Eintrag hinzu (nächtliche Sicherung um 4 Uhr)
    echo "0 4  * * * root /usr/local/bin/backup-db-linux.sh > /dev/null 2>&1" >> /tmp/crontab
    echo "#" >> /tmp/crontab
    cp /tmp/crontab /etc/crontab
fi

printf "\n\nInstallation abgeschlossen entsprechend der Auswahl der Komponenten:\n"
printf "======================================================================\n"
if [[ $installcore -eq 1 ]]
then
	printf "Installation der Kernkomponente:\n"
	printf " Aufruf der OrderSprinter-Applikation im Browser über http://localhost bzw. http://${HOSTNAME}\n"
	printf " Alle eingerichteten Benutzer haben das Passwort 123, ebenso ist der Kassenbon-Stornocode 123.\n"
fi
if [[ $installprintserver -eq 1 ]]
then
	printf "Der Druckserver ist eingerichtet und startet automatisch. Je nach Drucker und Anbindung kann\n"
	printf "eine weitere Konfiguration erforderlich sein.\n"
fi
if [[ $install_tse -eq 1 ]]
then 
	printf "Der TSEConnector befindet sich im normalen Arbeitsmodus. Für einen Simulationsbetrieb muss die\n"
	printf "Befehlszeile in /usr/local/bin/tseconnector.bat abgeändert werden (mode=simulate).\n"
fi
if [[ $autobackup -eq 1 ]]
then
	printf "Nächtliches Backup wurde eingerichtet für Gerät ${backupdevice}\n"
fi
