#!/bin/bash
#------- ABSCHNITT : Modul Identifikation -------------------------------------
#
# Modul Name       : elsterupgrade.sh
# .     Funktion   : Elster (ERiC) Upgrade
# .     Verwendung : 
# Autor            : male
# Verantwortlich   : male
# Kontrolle        : sd
# Beratungspflicht : nein
# Copyright        : (c)1990-2012 ABAS Software AG
#
#------- ABSCHNITT : Modul Beschreibung ---------------------------------------
#
#
#
#------------------------------------------------------------------------------

#------- ABSCHNITT : Defines, Prozeduren, Typen und Daten ---------------------
DEVNULL=${DEVNULL:-/dev/null}; export DEVNULL
name=$(basename $0)
whoami=$(id -un | sed 's/^.*\\//')  # wg. Windows: DOMAIN\user -> user
pwd=$(pwd)
DEBUG=0
unset rmdir  # rmdir von Aufrufern nicht uebernehmen

ELSTER_HOMEDIR=${ELSTER_HOMEDIR:-"$HOMEDIR/elster"}

#------------------------------------------------------------------------------
# Exit-Prozedur zum kontrollierten Beenden incl. Aufraeumen
# Im Fehlerfall ($1 != 0) wird $rmdir aufgehoben
# Wenn die globale Variable rm_rmdir auf 1 steht, wird $rmdir auch bei $1 != 0
# weggeworfen
# Parameter
#     $1 = Exit status
#     $2 = Fehlermeldung
#------------------------------------------------------------------------------
rm_rmdir=1 
myexit()
{
  exitcode=$1
  errmsg=$2
  cd $pwd
  # Temp-Verzeichnis loeschen
  if [ -n "$rmdir" ];then
     if [ $rm_rmdir -eq 1 -o \( $DEBUG -eq 0 -a $exitcode -eq 0 \) ];then
        if [ -z "$IS_WINDOWS" ];then
            rm -rf $rmdir
        else
            rm -rf $rmdir 2>$DEVNULL # Auf windoof kommt's immer wieder zu
              # Fehlermeldungen, da Filehandle nach Prozessende noch belegt.
        fi
     else
        echo "rmdir aufbewahrt: $rmdir" >&2
     fi
  fi
  if [ -n "$errmsg" ];then
      echo $name: "$errmsg" >&2
  fi
  exit $1
}

isroot()
{
  username=${1:-root}
  userid=`id -u $username`
  myid=`id -u`
  if [ x$myid = x$userid ]; then
    return 0
  else
   echo "`id` ist nicht $username" >&2
   return 1
  fi
}

pause()
{
  if [ ! "$batch_mode" = "1" ]; then
    echo -n "- weiter mit <return> ..." >&2
    read x
  fi
}

user_exists()
{
  id -un $1 1>$DEVNULL 2>&1
  return $?
}

# Fuehrt $1 als $2 aus
call_as()
{
  ret=1
  if user_exists $2; then
    if isroot $2 2>$DEVNULL; then
      sh -c "UNATTENDED=\"$UNATTENDED\" EKSPASSWORT=\"$EKSPASSWORT\" $1"
      ret=$?
    else
      echo "Authentifizieren Sie sich ggf. als Benutzer $2."
      /bin/su $2 -c "TMP=\"$TMP\" PATH=\"$PATH\" LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH\" LIBPATH=\"$LIBPATH\" UNATTENDED=\"$UNATTENDED\" EKSPASSWORT=\"$EKSPASSWORT\" $1"
      ret=$?
    fi
  else
    echo "Der Benutzer $2 existiert nicht!" 1>&2
    ret=2
  fi
  return $ret
}

prompt_read()
{
   echo -n "$1: " >&2
   read xread
   ret=$?
   echo "" >&2
   return $ret
}

getpassword()
{
   echo -n "$1: " >&2
   stty -echo > $DEVNULL 2>&1
   read xread
   ret=$?
   stty echo > $DEVNULL 2>&1
   echo "" >&2
   return $ret
}

set_reinstall()
{
  reinstall_jn="nein"
  [ "$reinstall" = "1" ] && reinstall_jn="ja"
}

get_current_version()
{
  current_version="-"
  if [ -f $ELSTER_HOMEDIR/refU/elster/patch-version ] ; then
    current_version=$(head -1 $ELSTER_HOMEDIR/refU/elster/patch-version 2>${DEVNULL})
  fi
}

get_http_file_by_wget()
{
  url=$1
  if [ $use_ssl -eq 1 ]; then
    url=$(echo $url | sed 's/http:/https:/')
  fi
  site_user_arg=$(encode $site_user)
  site_pass_arg=$(encode $site_password)
  url="$url?loginusername=$site_user_arg&loginpassword=$site_pass_arg"
  if [ -n "$proxy_user" ]; then
    proxy_user_arg="--proxy-user=$proxy_user"
  else
    proxy_user_arg=
  fi
  if [ -n "$proxy_password" ]; then
    proxy_password_arg="--proxy-password=$proxy_password"
  else
    proxy_password_arg=
  fi
  if [ -n "$2" ]; then
    output_file_arg="-O $2"
    mkdir -p $(dirname $2) 2>${DEVNULL}
  else
    output_file_arg=
  fi
  wget --no-check-certificate --timeout=10 -t 3 $proxy_user_arg $proxy_password_arg "$url" $output_file_arg
  return $?
}

get_http_file_by_curl()
{
  url=$1
  if [ $use_ssl -eq 1 ]; then
    url=$(echo $url | sed 's/http:/https:/')
  fi
  if [ -n "$proxy_user" ]; then
    proxy_user_arg="--proxy-user $proxy_user"
  else
    proxy_user_arg=
  fi
  if [ -n "$proxy_password" ]; then
    proxy_user_arg="${proxy_user_arg}:${proxy_password}"
  fi
  if [ -n "$2" ]; then
    output_file_arg="-o $2"
    mkdir -p $(dirname $2) 2>${DEVNULL}
  else
    output_file_arg=
  fi
  curl --tlsv1.2 -k $CURL_OPTS --fail --connect-timeout 10 $proxy_user_arg $url --data-urlencode "loginusername=$site_user" --data-urlencode "loginpassword=$site_password" $output_file_arg
  rc=$?
  if [ $rc -eq 22 ]; then
    # HTTP-Fehler 4xx.
    echo "Bitte ueberpruefen Sie ggf. Benutzername und Passwort fuer den Proxy bzw. die Download-Seite." 1>&2
  fi
  return $rc
}

encode()
{
   echo -ne "$1" | xxd -plain | tr -d '\n' | sed 's/\(..\)/%\1/g'
}

get_http_file()
{
  if [ -z "$download_tool" ]; then
    which curl 1>${DEVNULL} 2>&1
    if [ $? -eq 0 ]; then
      download_tool="curl"
    fi
  fi
  if [ -z "$download_tool" ]; then
    which wget 1>${DEVNULL} 2>&1
    if [ $? -eq 0 ]; then
      download_tool="wget"
    fi
  fi
  if [ -z "$download_tool" ]; then
    echo "Weder curl noch wget gefunden. Download nicht moeglich." 1>&2
    return 1
  fi
  if [ "$download_tool" = "curl" ]; then
      get_http_file_by_curl "$@"
     return $?
  elif [ "$download_tool" = "wget" ]; then
     get_http_file_by_wget "$@"
     return $?
  else
    echo "Download tool $download_tool nicht unterstuetzt." 1>&2
    return 1
  fi
}

parse_version_info()
{
  while read -r line; do
    varname=$(echo $line| sed -e 's/\(.*\)=\(.*\)/\1/g' -e 's/^[[:space:]]*\(.*\)[[:space:]]*$/\1/')
    value=$(echo $line| sed -e 's/\(.*\)=\(.*\)/\2/g' -e 's/^[[:space:]]*\(.*\)[[:space:]]*$/\1/')
    [ "version" = "$varname" ] && latest_version="$value"
    [ "url" = "$varname" ] && latest_version_url="$value"
    [ "md5" = "$varname" ] && latest_version_md5="$value"
  done < $1
}

chk_latest_version()
{
  latest_version=
  latest_version_url=
  latest_version_md5=
  rm -f "$latest_info_dest"
  get_http_file "$latest_info_src" "$latest_info_dest"
  rc=$?
  if [ $rc -eq 0 ]; then
    if [ -f "$latest_info_dest" ]; then
      parse_version_info $latest_info_dest
    fi
  fi
  return $rc
}

version()
{
  echo "$1" | awk -F. '{ printf("%d%03d%03d\n", $1,$2,$3); }'
}

vcmp()
{
  v1=$(version $1)
  v2=$(version $2)
  if [ $v1 -gt $v2 ]; then
     return 11
  elif [ $v1 -lt $v2 ]; then
     return 9
  else
     return 10
  fi
}

greater_version_available()
{
  if [ -n "$latest_version" ]; then
    if [ "-" = "$current_version" ]; then
      return 0;
    else
      vcmp "$current_version" "$latest_version"
      rc=$?
      if [ $rc -eq 9 ]; then
        return 0
      fi
      if [ $rc -eq 10 -a "$reinstall" = "1" ]; then
        return 0
      fi
    fi
  else
    echo "Bitte erst nach neuen Versionen suchen." 1>&2
  fi
  return 1
}

check_and_verify_download()
{
  if [ -n "$latest_version_url" ]; then
    filename=$(basename $latest_version_url)
    if [ ! -f "$download_dir/$filename" ]; then
      return 1
    fi
    chmod 777 "$download_dir/$filename" 2>${DEVNULL}
    if [ -n "$latest_version_md5" ]; then
      echo "$latest_version_md5 *$filename" > "$download_dir/$filename.md5"
      $(cd $download_dir && md5sum --status -c "$download_dir/$filename.md5")
      rc=$?
      if [ $rc -ne 0 ]; then 
        echo "Die Pruefsumme konnte nicht verifiziert werden." 1>&2
        echo "Der Download ist nicht vollstaendig." 1>&2
        rm -f "$download_dir/$filename"
      fi
      return $rc
    else
      return 0
    fi
  fi
  return 1
}

configure()
{
	menu_erg=1
	while true
	do clear
	   cd $HOMEDIR
	   menu -z -s $menu_erg -t " Bitte gewuenschte Funktion waehlen " -c "Elster Upgrade (Konfiguration)" \
                               "Reinstallation: $reinstall_jn" \
		                       "HTTP-Proxy: $http_proxy" \
		                       "FTP-Proxy: $ftp_proxy" \
		                       "Proxy User: $proxy_user" \
		                       "Proxy Passwort" \
		                       "Site User: $site_user" \
		                       "Site Passwort" \
		                       "Zurueck"
	   menu_erg=$?
	   case $menu_erg in
         0) return 0;;
         1) if [ "$reinstall" = "0" ]; then reinstall=1; else reinstall=0; fi; set_reinstall ;;
		 2) prompt_read "HTTP-Proxy" && export http_proxy=$xread ;;
		 3) prompt_read "FTP-Proxy" && export ftp_proxy=$xread ;;
		 4) prompt_read "Proxy User" && proxy_user=$xread ;;
		 5) getpassword "Proxy Passwort" && proxy_password=$xread ;;
		 6) prompt_read "Site User" && site_user=$xread ;;
		 7) getpassword "Site Passwort" && site_password=$xread ;;
         8) return 0;;
	   esac
	done
}

install_patch()
{
  # convenience
  if [ -z "$latest_inst_file" ]; then
    if greater_version_available && check_and_verify_download; then
      latest_inst_file="$download_dir/$filename"
    fi
  fi
  if [ -f "$latest_inst_file" ]; then
    call_as "$latest_inst_file" $s3user
    rc=$?
    if [ $rc -eq 0 ]; then
      echo "Fertig."
      unset latest_inst_file
      get_current_version
      return 0
    else
      echo "Es ist ein Fehler aufgetreten." 1>&2
      get_current_version
      return 1
    fi
  else
    echo "Nichts zu installieren." 1>&2
    if greater_version_available; then
      echo "Bitte zuerst verfuegbare Aktualisierung auf $latest_version herunterladen." 1>&2
    fi
    return 1
  fi
}

download()
{
  if greater_version_available; then
    check_and_verify_download
    rc=$?
    downloaded=0
    if [ $rc -ne 0 ]; then 
      filename=$(basename $latest_version_url)
      get_http_file "$latest_version_url" "$download_dir/$filename"
      rc=$?
      if [ $rc -ne 0 ]; then
        echo "Download fehlgeschlagen." 1>&2
      else
        downloaded=1
      fi
    fi
    if [ $rc -eq 0 ]; then
      if check_and_verify_download; then
        latest_inst_file="$download_dir/$filename"
        if [ $downloaded -eq 0 ]; then
          echo "Die Installationsdatei $latest_inst_file ist bereits vorhanden."
        fi
        return 0
      fi
    else
      return 1
    fi
  else
    echo "Es ist bereits die aktuellste Version installiert."
    return 0
  fi
}

main_menu()
{
	menu_erg=1
	while true
	do clear
	   cd $HOMEDIR
	   menu -z -s $menu_erg -t " Bitte gewuenschte Funktion waehlen " -c "Elster Upgrade" \
		                       "Aktuell installierte Version ($current_version)" \
		                       "Verfuegbare Aktualisierung ermitteln ($latest_version)" \
		                       "Verfuegbare Aktualisierung herunterladen" \
		                       "Verfuegbare Aktualisierung installieren" \
		                       "Konfiguration" \
		                       "Abbruch"
	   menu_erg=$?
	   case $menu_erg in
		 0) myexit 0;;
		 1) echo "Aktuell installiert: $current_version"; pause ;;
		 2) chk_latest_version || pause ;;
		 3) download; pause ;;
		 4) install_patch; pause ;;
		 5) configure;;
		 6) myexit 0;;
	   esac
	done
}

#------------------------------------------------------------------------------
# zeigt die Usage an          
#------------------------------------------------------------------------------
usage()
{
  echo  "" >&2
  echo "usage: $name" >&2
  echo  "       * Option -b: Batch-Modus                         " >&2
  echo  "       * Option -r: Reinstallation erlauben             " >&2
  echo  "       * Option -d: debug                               " >&2
  echo  >&2
  echo  "Ausgewertete optionale Umgebungsvariablen:" >&2
  echo  >&2
  echo  "       http_proxy     : <host>[:port]     " >&2
  echo  "       proxy_user     : Benutzername      " >&2
  echo  "       proxy_password : Passwort          " >&2
  echo  "       site_user      : Benutzername      " >&2
  echo  "       site_password  : Passwort          " >&2
  echo  "       download_tool  : (wget|curl)       " >&2
  echo  "       EKSPASSWORT    : Passwort          " >&2
  echo  "       s3user         : S3-User           " >&2
  exit 1
}


#------- ABSCHNITT : Optionen -------------------------------------------------
# Options- und Nichtoptionsargumente koennen Blanks enthalten.

batch_mode=0

OPTSTR="bdr"
non_opt_args=""
non_opt_index=0

while [ $OPTIND -le $# ];do
    while getopts "$OPTSTR" arg
    do
       case $arg in
           b) batch_mode=1; UNATTENDED=1 ;;
           d) set -x; DEBUG=1 ;;
           r) reinstall=1 ;;
           *) usage ;;
       esac
    done
    # Jetzt steht OPTIND entweder auf einem Argument, das keine Option ist, 
    # oder auf $# + 1
    eval akt_arg='"${'$OPTIND'}"'
    # leere Argumente interessieren nicht
    if [ -n "$akt_arg" ];then
        non_opt_args[$non_opt_index]="$akt_arg"
        non_opt_index=$(expr $non_opt_index '+' 1)
    fi
    # Wenn nur noch 1 Argument uebrig ist, dann kann man aufhoeren (es ist ja
    # bereits in non_opt_args).
    if [ $# -eq 1 -o $OPTIND -ge $# ];then
        break
    fi
    # $* am ersten Argument hinter akt_arg beginnen lassen
    shift $OPTIND
    OPTIND=1
done

#------- ABSCHNITT : Hauptprogramm --------------------------------------------
# main
trap "myexit 1 Abbruch!!" 1 2 

TMP=${TMP:-/tmp}              # Setze TMP auf /tmp, falls TMP leer oder nicht
                              # existent
[ ! -d $TMP ] && TMP=/tmp
rmdir="$TMP/$$.${name}.${whoami}.d"
rm -rf $rmdir || myexit 1 "Kann Verzeichnis rmdir=$rmdir nicht loeschen"
mkdir $rmdir  || myexit 1 "Kann Verzeichnis rmdir=$rmdir nicht anlegen"

rm_rmdir=1 # $rmdir im Fehlerfall nicht wegwerfen.

[ -n "$HOMEDIR" ] || myexit 1 "\$HOMEDIR nicht gesetzt."

s3user=${s3user:-$(envmake -q MNAME -x $HOMEDIR)}
reinstall=${reinstall:-0}
set_reinstall
latest_info_file="patch-elster-latest"
use_ssl=1
update_site="http://extranet.abas.de/sub_de/download2"
latest_info_src="${update_site}/${latest_info_file}"
download_dir="${HOMEDIR}/rmdir/elster"
mkdir -p "$download_dir"
latest_info_dest="${download_dir}/${latest_info_file}"

if [ -n "$http_proxy" -a -z "$ftp_proxy" ]; then
  export ftp_proxy="$http_proxy"
fi

get_current_version

if [ "$batch_mode" = "1" ]; then
  chk_latest_version
  [ $? -eq 0 ] || myexit 1
  download
  [ $? -eq 0 ] || myexit 1
  install_patch
  [ $? -eq 0 ] || myexit 1
else
  main_menu
fi

myexit 0 # Nur mit myexit verlassen, wegen Aufraeumen des TMP-Verzeichnisses
