#!/bin/bash
# This custom AppRun template was modified to support detecting and loading libstdc++ and libgcc_s from a provided directory only if each library is newer than the version available on the system.
# it's fed into the app-builder used by electron-builder: https://github.com/develar/app-builder
# extracted from https://github.com/develar/app-builder/blob/master/pkg/package-format/appimage/templates/AppRun.sh
# combined with details from https://github.com/darealshinji/AppImageKit-checkrt/blob/master/AppRun.sh
set -e

if [ ! -z "$DEBUG" ] ; then
  env
  set -x
fi

THIS="$0"
# http://stackoverflow.com/questions/3190818/
args=("$@")
NUMBER_OF_ARGS="$#"

if [ -z "$APPDIR" ] ; then
  # Find the AppDir. It is the directory that contains AppRun.
  # This assumes that this script resides inside the AppDir or a subdirectory.
  # If this script is run inside an AppImage, then the AppImage runtime likely has already set $APPDIR
  path="$(dirname "$(readlink -f "${THIS}")")"
  while [[ "$path" != "" && ! -e "$path/$1" ]]; do
    path=${path%/*}
  done
  APPDIR="$path"
fi

export PATH="${APPDIR}:${APPDIR}/usr/sbin:${PATH}"
export XDG_DATA_DIRS="./share/:/usr/share/gnome:/usr/local/share/:/usr/share/:${XDG_DATA_DIRS}"
export LD_LIBRARY_PATH="${APPDIR}/usr/lib:${LD_LIBRARY_PATH}"
export XDG_DATA_DIRS="${APPDIR}"/usr/share/:"${XDG_DATA_DIRS}":/usr/share/gnome/:/usr/local/share/:/usr/share/
export GSETTINGS_SCHEMA_DIR="${APPDIR}/usr/share/glib-2.0/schemas:${GSETTINGS_SCHEMA_DIR}"

BIN="$APPDIR/Logic"

if [ -z "$APPIMAGE_EXIT_AFTER_INSTALL" ] ; then
  trap atexit EXIT
fi

isEulaAccepted=1

atexit()
{
  set_ld_lib_path
  is_no_sandbox_required
  if [ $isEulaAccepted == 1 ] ; then
    if [ $NUMBER_OF_ARGS -eq 0 ] ; then
      exec "$BIN" $NO_SANDBOX
    else
      exec "$BIN" "${args[@]}" $NO_SANDBOX
    fi
  fi
}

error()
{
  if [ -x /usr/bin/zenity ] ; then
    LD_LIBRARY_PATH="" zenity --error --text "${1}" 2>/dev/null
  elif [ -x /usr/bin/kdialog ] ; then
    LD_LIBRARY_PATH="" kdialog --msgbox "${1}" 2>/dev/null
  elif [ -x /usr/bin/Xdialog ] ; then
    LD_LIBRARY_PATH="" Xdialog --msgbox "${1}" 2>/dev/null
  else
    echo "${1}"
  fi
  exit 1
}

yesno()
{
  TITLE=$1
  TEXT=$2
  if [ -x /usr/bin/zenity ] ; then
    LD_LIBRARY_PATH="" zenity --question --title="$TITLE" --text="$TEXT" 2>/dev/null || exit 0
  elif [ -x /usr/bin/kdialog ] ; then
    LD_LIBRARY_PATH="" kdialog --title "$TITLE" --yesno "$TEXT" || exit 0
  elif [ -x /usr/bin/Xdialog ] ; then
    LD_LIBRARY_PATH="" Xdialog --title "$TITLE" --clear --yesno "$TEXT" 10 80 || exit 0
  else
    echo "zenity, kdialog, Xdialog missing. Skipping ${THIS}."
    exit 0
  fi
}

check_dep()
{
  DEP=$1
  if [ -z $(which "$DEP") ] ; then
    echo "$DEP is missing. Skipping ${THIS}."
    exit 0
  fi
}

if [ -z "$APPIMAGE" ] ; then
  APPIMAGE="$APPDIR/AppRun"
  # not running from within an AppImage; hence using the AppRun for Exec=
fi



# this section is taken with small modifications from https://github.com/darealshinji/AppImageKit-checkrt/blob/master/AppRun.sh
# the purpose of this is to support older linux distributions that do not have the minimum required version of the standard C++ library.
# our application uses a number of C++14 & C++17 features which makes it incompatible with older standard C++ libraries.
# However, we can't just use a packaged copy all the time. If the system copy of libstdc++ is newer than our provided copy, we can't use our provided version.
set_ld_lib_path()
{
# This moves us to the root of the loaded AppImage folder.
  pushd "$(dirname "$0")"
  # libstdc++
  # first, verify that we included a copy of libstdc++ with the AppImage.
  if [ -e "./resources/linux/optional/libstdc++/libstdc++.so.6" ]; then
    # extract from the system all known versions of libstdc++. this works bt running ldconfig -p, and sacanning the output for libstdc++. finally the awk command extracts the absolute path to the system's libstdc++
    lib="$(PATH="/sbin:$PATH" ldconfig -p | grep "libstdc++\.so\.6 (libc6,x86-64)" | awk 'NR==1{print $NF}')"
    # here we extract the version of the system copy of libstdc++
    sym_sys=$(tr '\0' '\n' < "$lib" | grep -e '^GLIBCXX_3\.4' | tail -n1)
    # here we extract the version of libstdc++ that we included in the 'optional' folder.
    sym_app=$(tr '\0' '\n' < "./resources/linux/optional/libstdc++/libstdc++.so.6" | grep -e '^GLIBCXX_3\.4' | tail -n1)
    # here, we determine if the system copy is greater than or equal to our 'optional' copy.
    # this is done by putting both versions into a string on different lines, and then sorting by version, and then checking to see if the higher version is the system copy or not.
    # specifically, if the system copy is the same or newer than the copy we included, it will be sorted to the bottom. we then read the last line using tail -1, and see if it equals the system version or not.
    if [ "$(printf "${sym_sys}\n${sym_app}"| sort -V | tail -1)" != "$sym_sys" ]; then
      cxxpath="${PWD}/resources/linux/optional/libstdc++:"
    fi
  fi
  # here, the process repeats itself for libgcc_s. Note that the only real difference is the regex string.
  if [ -e "./resources/linux/optional/libgcc/libgcc_s.so.1" ]; then
    lib="$(PATH="/sbin:$PATH" ldconfig -p | grep "libgcc_s\.so\.1 (libc6,x86-64)" | awk 'NR==1{print $NF}')"
    sym_sys=$(tr '\0' '\n' < "$lib" | grep -e '^GCC_[0-9]\.[0-9]' | tail -n1)
    sym_app=$(tr '\0' '\n' < "./resources/linux/optional/libgcc/libgcc_s.so.1" | grep -e '^GCC_[0-9]\.[0-9]' | tail -n1)
    if [ "$(printf "${sym_sys}\n${sym_app}"| sort -V | tail -1)" != "$sym_sys" ]; then
      gccpath="${PWD}/resources/linux/optional/libgcc:"
    fi
  fi

  # if either libgcc_s or libstdc++ is not new enough for our application, we add both files from our inlcuded 'optional' directory to the LD_LIBRARY_PATH environment variable.
  if [ -n "$cxxpath" ] || [ -n "$gccpath" ]; then
    export LD_LIBRARY_PATH="${cxxpath}${gccpath}${LD_LIBRARY_PATH}"
  fi
  popd
}

# This function determines if the application will run properly on the target system, or if the --no-sandbox option will be required.
# this code is lifted from here: https://github.com/gcascio/electron-uns-workaround/blob/master/scripts/ensure-uns-loader.sh
# this solves this issue for Debian users: https://github.com/electron/electron/issues/17972
is_no_sandbox_required()
{
  OS_RELEASE=`uname -r`
  OS_CONFIG="/boot/config-${OS_RELEASE}"
  UNPRIVILEGED_USERNS_CLONE_SWITCH="/proc/sys/kernel/unprivileged_userns_clone"

  # Assume that the user name space feature is disabled
  USER_NS=n
  UNPRIVILEGED_USERNS_CLONE=1

  # Check if the user name space feature is enabled in the kernel config
  if [ -f $OS_CONFIG ]; then
    USER_NS=`cat $OS_CONFIG | sed -n 's/^CONFIG_USER_NS=//p'`
  fi

  # Check the state of the user name space feature switch
  if [ -f $UNPRIVILEGED_USERNS_CLONE_SWITCH ]; then
    UNPRIVILEGED_USERNS_CLONE=`cat $UNPRIVILEGED_USERNS_CLONE_SWITCH`
  fi

  if [ $USER_NS == 'y' ] && [ $UNPRIVILEGED_USERNS_CLONE != 0 ]; then
    NO_SANDBOX=""
  else
    echo "ATTENTION: Sandboxing of this app has been disabled since the user namespace feature of your OS is disabled."
    echo "Please enable user namespaces or use the deb package."
    NO_SANDBOX="--no-sandbox"
  fi
}