#!/bin/bash -e
#
#This program is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#
# Copyright 2011-2019
# authors: Amalu Obinna <amaluobinna@aol.com>
#          Brady Miller <brady.g.miller@gmail.com>
#
# Debian package pre-installation script steps:
#  1) Create log file
#  2) New install or Upgrade
#    -Install
#      a) If OpenEMR web directory already exist, then attempt an upgrade.
#    -Upgrade (also works for multisite module, so can be mutliple databases)
#      a) Ensure OpenEMR web directory does exist
#      b) Collect package version and ensure appropriate upgrade
#      c) Collect webpath and sql settings from current version
#      d) Verify the mysql user(s)/database(s) exist
#      e) Backup the current version mysql database(s)
#      f) Backup the current version web folder
#      g) Clear the cache directories in current version
#  3) Create config file
#
#  Output log file:
#   /var/log/openemr/install
#
#
# summary of how this script can be called:
#        * <new-preinst> `install'
#        * <new-preinst> `install' <old-version>
#        * <new-preinst> `upgrade' <old-version>
#        * <old-preinst> `abort-upgrade' <new-version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package

# Source debconf library.
. /usr/share/debconf/confmodule

#constants and paths
LOGDIR=/var/log/openemr
LOG=$LOGDIR/install
CONFIGDIR=/etc/openemr
CONFIG=$CONFIGDIR/openemr.conf
TMPDIR=/tmp/openemr-tmp
WEB=/var/www
OPENEMR=$WEB/openemr
SITEDIR=$OPENEMR/sites
#hardcoded mysql user and database for install (not pertinent for upgrading)
# upgrading can use whatever is found in openemr/library/sqlconf.php
INSTALL_USER=openemr
INSTALL_DATABASE=openemr

#Standardized echo function to send to only log file
#  requires one parameter (string)
log_only () {
   echo "`date`: $1" >> $LOG
}

#Standardized exit function to be used when unable to install the openemr package
#  requires one parameter (string with reason for exiting)
unable_exit () {
   echo "`date`: $1" >> $LOG
   echo "`date`: EXITING.........." >> $LOG
   exit 1
}

#function to prompt for input
# 1st param is name, 2nd param is priority, 3rd param is where result gets sent back in
# return the input
prompt_input () {
   db_set "$1" ""
   db_fset "$1" seen false
   db_input "$2" "$1" || true
   db_go || true
   db_get "$1"
   local input_value="$RET"
   db_set "$1" ""
   db_fset "$1" seen false
   local __result=$3
   eval $__result="'$input_value'"
}

#function to check mysql for selected databases
# 1st param is password, 2nd param database, 3rd param is host (optional), 4th param is user (optional)
check_mysql () {
   if [ -n "$3" ]; then
      HOST=$3
   else
      HOST=localhost
   fi
   if [ -n "$4" ]; then
      USE=$4
   else
      USE=root
   fi

   if [ "`mysql -u "$USE" -h "$HOST" --password="$1" -e 'show databases' 2>/dev/null | awk '{ print $1}' | grep "^$2$"`" == "$2" ]; then
      return 0
   else
      return 1
   fi
}

#function to collect variables from config files
# 1st param is variable name, 2nd param is filename
collect_var () {
   echo `grep -i "^[[:space:]]*$1[[:space:]=]" $2 | cut -d \= -f 2 | cut -d \; -f 1 | sed "s/[ 	'\"]//gi"`
}

#function to check database before preparing to upgrade
# 1st param is the directory of database configuration script
# no return, but will exit the upgrade if database check fails
upgrade_check_database () {

   #Collect the path of database configuration script
   DATABASE_PATH="$1"

   #Collect variables
   SQL_LOCATION=$(collect_var \$host $DATABASE_PATH/sqlconf.php)
   SQL_USER=$(collect_var \$login $DATABASE_PATH/sqlconf.php)
   SQL_PASSWORD=$(collect_var \$pass $DATABASE_PATH/sqlconf.php)
   SQL_DATABASE=$(collect_var \$dbase $DATABASE_PATH/sqlconf.php)

   #ensure the mysql database and user exist
   if check_mysql "$SQL_PASSWORD" "$SQL_DATABASE" "$SQL_LOCATION" "$SQL_USER"; then
      log_only "For upgrade, confirmed that the mysql database ($SQL_DATABASE) and mysql user ($SQL_USER) exist"
   else
      prompt_input openemr/upgrade_not_database critical ret_result
      unable_exit "MySQL '$SQL_DATABASE' database does not exist (or can't be accessed), unable to upgrade."
   fi
}

#function to process database to prepare for upgrade
# 1st param is the directory of database configuration script
# 2nd param is the sitename
# returns(via echo) pertinent configuration file information
upgrade_prepare_database () {

   #Collect the path of database configuration script
   DATABASE_PATH="$1"

   #Collect the site name
   SITE_NAME="$2"

   #Collect variables
   SQL_LOCATION=$(collect_var \$host $DATABASE_PATH/sqlconf.php)
   SQL_USER=$(collect_var \$login $DATABASE_PATH/sqlconf.php)
   SQL_PASSWORD=$(collect_var \$pass $DATABASE_PATH/sqlconf.php)
   SQL_DATABASE=$(collect_var \$dbase $DATABASE_PATH/sqlconf.php)
   SQL_UTFFLAG=$(collect_var \$disable_utf8_flag $DATABASE_PATH/sqlconf.php)

   #if SQLUTFFLAG variable is empty, then make it false
   if [ "$SQL_UTFFLAG" == "" ]; then
      SQL_UTFFLAG="false"
   fi

   #write variables to config file string
   TEMP_SETTING=""
   TEMP_SETTING=$TEMP_SETTING$SITE_NAME"_sqllocation=$SQL_LOCATION\n"
   TEMP_SETTING=$TEMP_SETTING$SITE_NAME"_sqluser=$SQL_USER\n"
   TEMP_SETTING=$TEMP_SETTING$SITE_NAME"_sqlpassword=$SQL_PASSWORD\n"
   TEMP_SETTING=$TEMP_SETTING$SITE_NAME"_sqldatabase=$SQL_DATABASE\n"
   TEMP_SETTING=$TEMP_SETTING$SITE_NAME"_sqlutfflag=$SQL_UTFFLAG\n"

   #create the tmp sql directory
   mkdir -p "$TMPDIR/openemr_mysql_${OLD_VERSION}_${SITE_NAME}"

   #backup mysql database to tmp
   mysqldump -u "$SQL_USER" -h "$SQL_LOCATION" --password="$SQL_PASSWORD" "$SQL_DATABASE" > "$TMPDIR/openemr_mysql_${OLD_VERSION}_${SITE_NAME}/openemr_mysql_${OLD_VERSION}_${SITE_NAME}.sql"

   #return the settings (to be used for the config file passed to postinst
   echo $TEMP_SETTING
}

#function to hold the upgrade code (allow more flexible upgrading)
# 1st param is the previous version,
# 2nd param is whether raw or package upgrade
upgrade_function () {

      #Check for /var/www/openemr. If does not exist, then exit.
      if ! [ -d "$OPENEMR" ]; then
         prompt_input openemr/upgrade_not_installed critical ret_result
         unable_exit "OpenEMR is not installed ($OPENEMR), so can not upgrade the OpenEMR Package."
      fi

      #collect previous version
      OLD_VERSION=$1

      #collect type of upgrade (either package or raw)
      UPGRADETYPE=$2

      #ensure version is appropriate for upgrade (if not, then exit!!)
      #
      # ONLY acceptable for raw is 3.0.0 or 3.0.0.1 or 3.1.0 or ...  (need to convert these)
      #
      if [ "$UPGRADETYPE" == "raw" ]; then
         if [ "$OLD_VERSION" == "3.0.0" ]; then
            OLD_VERSION="3.0.1-1"
         elif [ "$OLD_VERSION" == "3.0.0.1" ]; then
            OLD_VERSION="3.0.1-1"
         elif [ "$OLD_VERSION" == "3.0.1" ]; then
            OLD_VERSION="3.0.1-1"
         elif [ "$OLD_VERSION" == "3.1.0" ]; then
            OLD_VERSION="3.1.0-1"
         elif [ "$OLD_VERSION" == "3.2.0" ]; then
            OLD_VERSION="3.2.0-1"
         elif [ "$OLD_VERSION" == "3.2.0.1" ]; then
            OLD_VERSION="3.2.0-1"
         elif [ "$OLD_VERSION" == "4.0.0" ]; then
            OLD_VERSION="4.0.0-1"
         elif [ "$OLD_VERSION" == "4.1.0" ]; then
            OLD_VERSION="4.1.0-1"
         elif [ "$OLD_VERSION" == "4.1.1" ]; then
            OLD_VERSION="4.1.1-1"
         elif [ "$OLD_VERSION" == "4.1.2" ]; then
            OLD_VERSION="4.1.2-1"
         elif [ "$OLD_VERSION" == "4.2.0" ]; then
            OLD_VERSION="4.2.0-1"
         elif [ "$OLD_VERSION" == "4.2.1" ]; then
            OLD_VERSION="4.2.1-1"
         elif [ "$OLD_VERSION" == "4.2.2" ]; then
            OLD_VERSION="4.2.2-1"
         elif [ "$OLD_VERSION" == "5.0.0" ]; then
            OLD_VERSION="5.0.0-1"
         elif [ "$OLD_VERSION" == "5.0.1" ]; then
            OLD_VERSION="5.0.1-1"
         else
            prompt_input openemr/upgrade_not_supported critical ret_result
            unable_exit "Unable to upgrade from $OLD_VERSION version package with $UPGRADETYPE method, so can not upgrade the OpenEMR Package."
         fi
      fi
      #
      # ONLY acceptable package and converted raw is 3.0.1-1 or 3.1.0-1 or 3.2.0-1 or 4.0.0-1 or 4.1.0-1 or 4.1.1-1 or 4.1.2-1 or 4.1.2-2 or 4.1.2-3 or 4.2.0-1 or 4.2.0-2 or 4.2.1-1 or 4.2.1-2 or 4.2.2-1 or 5.0.0-1 or 5.0.0-2 or 5.0.1-1 or 5.0.1-2 or 5.0.1-3 or 5.0.1-4
      #
      if [ "$OLD_VERSION" != "3.0.1-1" ] && [ "$OLD_VERSION" != "3.1.0-1" ] && [ "$OLD_VERSION" != "3.2.0-1" ] && [ "$OLD_VERSION" != "4.0.0-1" ] && [ "$OLD_VERSION" != "4.1.0-1" ] && [ "$OLD_VERSION" != "4.1.1-1" ] && [ "$OLD_VERSION" != "4.1.2-1" ] && [ "$OLD_VERSION" != "4.1.2-2" ] && [ "$OLD_VERSION" != "4.1.2-3" ] && [ "$OLD_VERSION" != "4.2.0-1" ] && [ "$OLD_VERSION" != "4.2.0-2" ] && [ "$OLD_VERSION" != "4.2.1-1" ] && [ "$OLD_VERSION" != "4.2.1-2" ] && [ "$OLD_VERSION" != "4.2.2-1" ] && [ "$OLD_VERSION" != "5.0.0-1" ] && [ "$OLD_VERSION" != "5.0.0-2" ] && [ "$OLD_VERSION" != "5.0.1-1" ] && [ "$OLD_VERSION" != "5.0.1-2" ] && [ "$OLD_VERSION" != "5.0.1-3" ] && [ "$OLD_VERSION" != "5.0.1-4" ]; then
         prompt_input openemr/upgrade_not_supported critical ret_result
         unable_exit "Unable to upgrade from $OLD_VERSION version package with $UPGRADETYPE method, so can not upgrade the OpenEMR Package."
      fi

      #Initiate the config file string, which will pass info to postinst script
      #to continue upgrade process.
      SETTING="#Optional settings\n\
#(currently empty, plan to use in subsequent versions of OpenEMR)\n\
\n\
#Installation settings\n\
# (DO NOT EDIT below!!!)\n\
process=pending\n\
plan=upgrade\n\
previous_version=$OLD_VERSION\n"

      #collect openemr mysql data
      #(will need to look in sites directory if 4.0 or later)
      #Also supports multisite module, which can have multiple separate databases
      if [ "$OLD_VERSION" == "3.0.1-1" ] || [ "$OLD_VERSION" == "3.1.0-1" ] || [ "$OLD_VERSION" == "3.2.0-1" ]; then

         #check database (will exit upgrade if check fails)
         upgrade_check_database $OPENEMR/library

         #Prepare uprade of database and collect settings that will placed in the config file string
         DATABASE_CONFIG=$(upgrade_prepare_database $OPENEMR/library default)
         SETTING=$SETTING$DATABASE_CONFIG

      else
         for dir in $(find $SITEDIR/* -maxdepth 0 -type d ); do
            #collect sitename
            SITENAME=$(basename "$dir")

            #check database (will exit upgrade if check fails)
            upgrade_check_database $SITEDIR/$SITENAME

            #Prepare uprade of database and collect settings that will placed in the config file string
            DATABASE_CONFIG=$(upgrade_prepare_database $SITEDIR/$SITENAME $SITENAME)
            SETTING=$SETTING$DATABASE_CONFIG

            #clear the temporary smarty directories (no need to keep these during upgrade)
            if [ -d $SITEDIR/$SITENAME/documents/smarty/gacl ]; then
              rm -fr $SITEDIR/$SITENAME/documents/smarty/gacl/*
            fi
            if [ -d $SITEDIR/$SITENAME/documents/smarty/main ]; then
              rm -fr $SITEDIR/$SITENAME/documents/smarty/main/*
            fi
         done
      fi

      #create the tmp web directory
      mkdir -p $TMPDIR/openemr_web_$OLD_VERSION

      #backup web directory to tmp
      cp -fr $OPENEMR/* $TMPDIR/openemr_web_$OLD_VERSION/

      #clear the old temporary openemr cache directories if they still exist (no need to keep these during upgrade)
      if [ -d $OPENEMR/interface/main/calendar/modules/PostCalendar/pntemplates/compiled ]; then
        rm -fr $OPENEMR/interface/main/calendar/modules/PostCalendar/pntemplates/compiled/*
      fi
      if [ -d $OPENEMR/interface/main/calendar/modules/PostCalendar/pntemplates/cache ]; then
        rm -fr $OPENEMR/interface/main/calendar/modules/PostCalendar/pntemplates/cache/*
      fi
      if [ -d $OPENEMR/gacl/admin/templates_c ]; then
        rm -fr $OPENEMR/gacl/admin/templates_c/*
      fi

      log_only "Upgrading OpenEMR from $OLD_VERSION..."

      #Create the config file, which will pass info to postinst script
      #to continue upgrade process.
      mkdir -p $CONFIGDIR
      echo -e $SETTING > $CONFIG
}


case "$1" in
   install)

      #create the log file directory
      mkdir -p $LOGDIR

      #Check for /var/www/openemr, if exist then see if upgrade is possible
      if [ -d "$OPENEMR" ]; then

         #collect current version
         #(for post-4.0 release will need to look in version.php file for version)
         #(for post-4.0 release will need to use v_tag rather than tag)
         #(if version.php exists then look there, otherwise get from globals)
         if [ -e "$OPENEMR/version.php" ]; then
            v1=$(collect_var \$v_major $OPENEMR/version.php)
            v2=$(collect_var \$v_minor $OPENEMR/version.php)
            v3=$(collect_var \$v_patch $OPENEMR/version.php)
            v4=$(collect_var \$v_tag $OPENEMR//version.php)
         else
            v1=$(collect_var \$v_major $OPENEMR/interface/globals.php)
            v2=$(collect_var \$v_minor $OPENEMR/interface/globals.php)
            v3=$(collect_var \$v_patch $OPENEMR/interface/globals.php)
            v4=$(collect_var \$tag $OPENEMR/interface/globals.php)
         fi
         RAWVERSION="$v1.$v2.$v3$v4"

         #attempt upgrade, if user desires
         prompt_input openemr/upgrade_confirm critical ret_result
         if [ "$ret_result" == "no" ]; then
            prompt_input openemr/upgrade_no critical ret_result
            unable_exit "You have chosen to not install the OpenEMR package."
         fi
         upgrade_function $RAWVERSION "raw"

         exit 0
      fi

      #Create the config file to pass to the postinst script
      # to signal that this is a new install
      SETTING="#Optional settings\n\
#(currently empty, plan to use in subsequent versions of OpenEMR)\n\
\n\
#Installation settings\n\
# (DO NOT EDIT below!!!)\n\
process=pending\n\
plan=install"
      mkdir -p $CONFIGDIR
      echo -e $SETTING > $CONFIG

      exit 0
   ;;

   upgrade)

      upgrade_function $2 "package"

      exit 0
   ;;

   abort-upgrade)
      echo "preinst asked to do abort-upgrade"
      exit 0
   ;;

   *)
      echo "preinst called with unknown argument \`$1'" >&2
      exit 1
   ;;
esac
