#!/bin/sh

. "${EF_ROOT}/plugins/ef/lib/xmlfuncs"
. "${EF_ROOT}/plugins/ef/lib/jsfuncs"

#-------------------------------------------------------------------------------
# Emit an EnginFrame XML error.
#
# Parameter 1: error message (must be defined)
# Parameter 2: error title (defaults to "EnginFrame Plugin Error")
# Parameter 3: command causing error (defaults to "Unknown Command")
#-------------------------------------------------------------------------------
ef_error() {
  _msg=`ef_xml_escape -i "$1"`
  [ -z "${_msg}" ] && return 1

  _title=`ef_xml_escape -i "$2"`
  [ -z "${_title}" ] && _title="EnginFrame Plugin Error"

  _cmd=$(ef_xml_escape -i "$(echo "$3" | sed "s|${EF_ROOT}|EF_ROOT|g")")
  [ -z "${_cmd}" ] && _cmd="Unknown Command"

cat << EOF
  <ef:error>
    <ef:title>$_title</ef:title>
    <ef:message>$_msg</ef:message>
    <ef:command>$_cmd</ef:command>
  </ef:error>
EOF
}

# logging to /tmp/grid.log
# parameter: message to log
tmp_log() {
  echo "$1" >> /tmp/grid.log
}



#-------------------------------------------------------------------------------
# Emit an EnginFrame HTML warning.
#
# Parameter 1: warning message (must be defined)
#-------------------------------------------------------------------------------
ef_warning() {
  _msg=`ef_xml_escape -i "$1"`
  [ -z "${_msg}" ] && return 1
cat <<EOF
  <div class="warning_message">$_msg</div>
EOF
}



#-------------------------------------------------------------------------------
# Converts a spooler URI to real file path
#-------------------------------------------------------------------------------
spooler2file() {
  FILE=""

  if [ -n "$1" ] ; then
    FILE=`echo "$1" | sed 's%spooler://%%'`
  fi

  echo "${FILE}"
}



# --------------------------------------------------------------------------- #
# EF_sed_sh_escape
# ================
# Private function.
#
# Perform (correctly) escaping of a string that will be evaluated in SH.
# --------------------------------------------------------------------------- #

ef_sed_sh_escape() {
    sed -e 's/\\/\\\\/g' \
        -e 's/`/\\`/g' \
        -e 's/"/\\"/g' \
        -e "s/'/\\\'/g" \
        -e 's/\&/\\\&/g' \
        -e 's/(/\\(/g' \
        -e 's/)/\\)/g' \
        -e 's/\;/\\\;/g' \
        -e 's/>/\\\>/g' \
        -e 's/</\\\</g' \
        -e 's/|/\\|/g' \
        -e 's/#/\\#/g'
}


# --------------------------------------------------------------------------- #
# EF_sh_sanitize_single
# =====================
#
# --------------------------------------------------------------------------- #

ef_sh_sanitize_single() {
    if [ "$#" -gt 0 ]; then
        echo "$1" | sed "s/'/'\"'\"'/g;"
    else
        sed "s/'/'\"'\"'/g;"
    fi
}


# --------------------------------------------------------------------------- #
# EF_sh_sanitize
# ==============
# Invoke ef_sed_sh_escape. This function could read input from command line
# or, if command line is empty, from a pipe.
# --------------------------------------------------------------------------- #

ef_sh_sanitize() {
    if [ "$#" -gt 0 ]; then
        echo "$@" | ef_sed_sh_escape
    else
        cat - | ef_sed_sh_escape
    fi
}


# --------------------------------------------------------------------------- #
# EF_sh_surround_quote
# =====================
#
# --------------------------------------------------------------------------- #

ef_sh_surround_quote() {
    if [ "$#" -gt 0 ]; then
        echo "$1" | ef_sh_sanitize_single 2>/dev/null | sed "s/^/'/;s/$/'/"
    else
        ef_sh_sanitize_single 2>/dev/null | sed "s/^/'/;s/$/'/"
    fi
}


#---------------------------------------------------------------------------- #
# EF_find_awk
# ===========
# Find a version of awk we can trust.
# This awk must:
# 1) understand functions
# 2) support GNU gsub function
#
# Arguments: none
#-------------------------------------------------------------------------------

ef_find_awk() {
    _awk_test_code='function tl(str){ return tolower(str) } { print tl($1) }'
    for _awk in \
        "`which gawk 2>/dev/null`" \
        "`which nawk 2>/dev/null`" \
        "/usr/toolbox/nawk" \
        "/usr/bin/awk"
        do

        if [ ! -x "${_awk}" ]; then
            continue
        fi

        _awk_res=`echo 'FOO' | $_awk "${_awk_test_code}" 2> /dev/null `
        if [ "$_awk_res" = 'foo' ]; then
            _awk_prog=${_awk}
            break
        fi
    done
    echo "$_awk_prog"
}



#---------------------------------------------------------------------------- #
# EF_find_hash
# ============
# Find a version hashing program we can use.
#
# Arguments: none
#-------------------------------------------------------------------------------

ef_find_hash() {
    for _digester in \
        sha1sum \
        md5sum \
        cksum
    do
        _test=`which "${_digester}" 2>/dev/null`
        if [ -x "${_test}" ] ; then
            _hash_prog="${_test}"
            break
        fi
    done

    echo "${_hash_prog}"
}


#-------------------------------------------------------------------------------
#
# Creates a temporary file
#
# Parameter 1 (optional): desired temporary file name (no path)
# Parameter 2 (optional): permissions (default: 600)
#
# Returns: full path plus temporary file name on success
#          exports EF_TEMPFILE_ERROR error string on failure
#
# Exit value: 0 on success, 1 on error
#
#-------------------------------------------------------------------------------
ef_create_tempfile () {
  [ -n "$1" ] \
     && EF_TEMPFILE_NAME=$1 \
     || EF_TEMPFILE_NAME="ef_tmp_$(date +'%N')$$"
  [ -n "$2" ] \
     && EF_TEMPFILE_PERM=$2 \
     || EF_TEMPFILE_PERM="600"
  [ -n "${TMPDIR}" ] \
     && EF_TEMPFILE_PATH=${TMPDIR} \
     || EF_TEMPFILE_PATH="/tmp"
  EF_TEMPFILE=`tempfile -n "${EF_TEMPFILE_PATH}/${EF_TEMPFILE_NAME}" -m "${EF_TEMPFILE_PERM}" 2>/dev/null`
  if [ "$?" -eq 0 ]; then
    echo "${EF_TEMPFILE}"
    return 0
  else
    EF_TEMPFILE_ERROR=`umask 066 2>&1 && touch "${EF_TEMPFILE_PATH}/${EF_TEMPFILE_NAME}" 2>&1 && chmod ${EF_TEMPFILE_PERM} "${EF_TEMPFILE_PATH}/${EF_TEMPFILE_NAME}" 2>&1`
    if [ "$?" -eq 0 ]; then
      echo "${EF_TEMPFILE_PATH}/${EF_TEMPFILE_NAME}"
      return 0
    else
      export EF_TEMPFILE_ERROR
      return 1
    fi
  fi
}


#-------------------------------------------------------------------------------
#
# Expand variables safely
#
# Parameter 1 : variables string to expand
#
# Returns: expanded variables values
#
#-------------------------------------------------------------------------------

ef_safe_expand_variables() {
    echo "$1" | awk '
    BEGIN {
        FS=":"
        empty_ct = 0
        content = 0
        #rx_variable = "\\${[a-zA-Z_][a-zA-Z0-9_]*}|\\${[$#]}"
        rx_variable = "\\${[a-zA-Z_][a-zA-Z0-9_]*}|\\${[$#]}|\\$[a-zA-Z_][a-zA-Z0-9_]*"
    }
    function expand_variables(s) {
        start = match(s, rx_variable)
        if (start == 0) {
            return s
        }
        #end = index(s, "}")
        end = RSTART + RLENGTH - 1
        vname = substr(s, start+1, RLENGTH-1)
        if (substr(vname, 1,1) == "{") {
            vname = substr(vname, 2, length(vname)-2)
        }
        #vname = substr(s, start+2, end-start-2)
        if (vname == "#" || vname == "$") {
            # Special case for ${#} and ${$}
            vval = vname
        } else {
            vval = ENVIRON[vname]
        }
        return substr(s, 1, start-1) vval expand_variables(substr(s, end+1))
    }
    {
        empty_ct = 0
        if (content == 0) {
            content = 1
        }
        print expand_variables($0)
    }'
}

#-------------------------------------------------------------------------------
#
# Load Shell conf file from (in ascending priority order):
#  - EF_ROOT/plugins/<plugin>/conf/<filename>
#  - EF_CONF_ROOT/plugins/<plugin>/<filename>
#
# Parameter 1 : plugin name
# Parameter 2 : filename or relative file path starting from the conf dir
#
# Examples:
#  ef_source_conf lsf ef.lsf.conf
#  ef_source_conf myplugin foo/bar.conf
#  --> load "${EF_ROOT}/plugins/myplugin/conf/foo/bar.conf"
#  --> load "${EF_CONF_ROOT}/plugins/myplugin/foo/bar.conf"
#
# Return codes:
#  0: success
#  1: first conf file not readable
#  2: error sourceing first conf file
#  3: error sourceing the override conf file
#
#-------------------------------------------------------------------------------

ef_source_conf() {
    local _plugin="$1"
    local _filename="$2"
    local _fullpath=""

    _fullpath="${EF_ROOT}/plugins/${_plugin}/conf/${_filename}"
    if [ ! -r "${_fullpath}" ]; then
      return 1
    fi
    . "${_fullpath}" || return 2

    _fullpath="${EF_CONF_ROOT}/plugins/${_plugin}/${_filename}"
    if [ -r "${_fullpath}" ]; then
      . "${_fullpath}" || return 3
    fi
    return 0
}

#-------------------------------------------------------------------------------
# Get absolute path of a conf file from (in ascending priority order):
#  - EF_CONF_ROOT/plugins/<plugin>/<filename>
#  - EF_ROOT/plugins/<plugin>/conf/<filename>
#
# Parameter 1: plugin name
# Parameter 2: filename or relative file path starting from the conf dir
# Returns: absolute path of the given conf file, if any
#
# Examples:
#  path=$(ef_get_conf_path lsf ef.lsf.conf)
#  --> path is "${EF_CONF_ROOT}/plugins/lsf/conf/ef.lsf.conf" if it exists,
#      otherwise is "${EF_ROOT}/plugins/lsf/conf/ef.lsf.conf"
#  path=$(ef_get_conf_path myplugin foo/bar.conf)
#  --> path is "${EF_CONF_ROOT}/plugins/myplugin/conf/foo/bar.conf" if it exists,
#      otherwise is "${EF_ROOT}/plugins/myplugin/conf/foo/bar.conf"
#
# Return codes:
#  0: success
#  1: conf file does not exist neither in EF_CONF_ROOT nor in EF_ROOT
#-------------------------------------------------------------------------------

ef_get_conf_path() {
    local _plugin="$1"
    local _filename="$2"
    local _fullpath=""

    _fullpath="${EF_CONF_ROOT}/plugins/${_plugin}/${_filename}"
    if [ -r "${_fullpath}" ]; then
      echo "${_fullpath}"
      return 0
    fi

    _fullpath="${EF_ROOT}/plugins/${_plugin}/conf/${_filename}"
    if [ -r "${_fullpath}" ]; then
      echo "${_fullpath}"
      return 0
    fi

    return 1
}

#-------------------------------------------------------------------------------
# Escape URI component
#
# Parameter 1: string to encode
#-------------------------------------------------------------------------------
ef_escape_uri_component() {
  if [ -z "${EF_AWK}" ]; then
    EF_AWK="$(ef_find_awk)"
  fi
    # BASH version (not POSIX)
    # echo "$1" | "${EF_AWK}" -f "${EF_ROOT}/plugins/ef/lib/awk/utils.awk" -f <( echo '{ urlencode($0) }' )
    echo "$1" | "${EF_AWK}" "$(cat "${EF_ROOT}/plugins/ef/lib/awk/utils.awk";  echo '{ urlencode($0) }')"
}


#-------------------------------------------------------------------------------
# Emit an EnginFrame XML error and exit
#
# Parameter 1: return code (must be defined)
# Parameter 2: error message (must be defined)
# Parameter 3: error title (defaults to "EnginFrame Plugin Error")
# Parameter 4: command causing error (defaults to "Unknown Command")
#-------------------------------------------------------------------------------
ef_error_and_exit() {
  ef_error "$2" "$3" "$4"
  exit $1
}
