#!/usr/bin/env bash

__rvm_md5_for_contents()
{
  if   builtin command -v md5     > /dev/null
  then md5         | __rvm_awk '{print $1}'
  elif builtin command -v md5sum  > /dev/null
  then md5sum      | __rvm_awk '{print $1}'
  elif builtin command -v openssl > /dev/null
  then openssl md5 | __rvm_awk '{print $1}'
  else return 1
  fi
  true # for osx
}

__rvm_sha256_for_contents()
{
  if   builtin command -v sha256sum > /dev/null
  then sha256sum           | __rvm_awk '{print $1}'
  elif builtin command -v sha256    > /dev/null
  then sha256              | __rvm_awk '{print $1}'
  elif builtin command -v shasum    > /dev/null
  then shasum -a256        | __rvm_awk '{print $1}'
  elif builtin command -v openssl   > /dev/null
  then openssl sha -sha256 | __rvm_awk '{print $1}'
  else return 1
  fi
  true # for osx
}

__rvm_checksum_for_contents()
{
  typeset __sum
  __sum=$(  echo "$1" | \cat - "$1" | __rvm_md5_for_contents   ) ||
  {
    rvm_error "Neither md5 nor md5sum were found in the PATH"
    return 1
  }
  __sum+=$( echo "$1" | \cat - "$1" | __rvm_sha256_for_contents ) ||
  {
    rvm_error "Neither sha256sum nor shasum found in the PATH"
    return 1
  }
  echo ${__sum}
}

__rvm_rvmrc_key()
{
  printf "%b" "$1" | \tr '[#/.=()]' _
  return $?
}

__rvm_reset_rvmrc_trust()
{
  if [[ "$1" == all ]]
  then
    echo "" > "$rvm_user_path/rvmrcs"
  else
    "$rvm_scripts_path/db" "$rvm_user_path/rvmrcs" \
      "$(__rvm_rvmrc_key "$1")" "delete" >/dev/null 2>&1
  fi
}

__rvm_trust_rvmrc()
{
  [[ -f "$1" ]] || return 1
  __rvm_reset_rvmrc_trust "$1"
  "$rvm_scripts_path/db" "$rvm_user_path/rvmrcs" \
    "$(__rvm_rvmrc_key "$1")" "1;$(__rvm_checksum_for_contents "$1")" >/dev/null 2>&1 ||
  return $?
}

__rvm_untrust_rvmrc()
{
  [[ -f "$1" ]] || return 1
  __rvm_reset_rvmrc_trust "$1"
  "${rvm_scripts_path:-"$rvm_path/scripts"}/db" "$rvm_user_path/rvmrcs" \
    "$(__rvm_rvmrc_key "$1")" "0;$(__rvm_checksum_for_contents "$1")" >/dev/null 2>&1 ||
  return $?
}

__rvm_rvmrc_stored_trust()
{
  [[ -f "$1" ]] || return 1
  "${rvm_scripts_path:-"$rvm_path/scripts"}/db" "$rvm_user_path/rvmrcs" \
    "$(__rvm_rvmrc_key "$1")" ||
  return $?
}

__rvm_rvmrc_stored_trust_check()
{
  typeset _first _second rvmrc_path
  if [[ -n "${ZSH_VERSION:-}" ]]
  then _first=1
  else _first=0
  fi
  _second=$(( _first + 1 ))
  rvmrc_path="$1"

  if [[ -f "$rvmrc_path" ]]
  then
    saveIFS=$IFS
    IFS=$';'
    trust=($(__rvm_rvmrc_stored_trust "$rvmrc_path"))
    IFS=$saveIFS

    if
      [[ "${trust[${_second}]:-'#'}" != "$(__rvm_checksum_for_contents "$rvmrc_path")" ]]
    then
      echo "The rvmrc at '$rvmrc_path' contains unreviewed changes."
      return 1
    elif
      [[ "${trust[${_first}]}" == '1' ]]
    then
      echo "The rvmrc at '$rvmrc_path' is currently trusted."
      return 0
    elif
      [[ "${trust[${_first}]}" == '0' ]]
    then
      echo "The rvmrc at '$rvmrc_path' is currently untrusted."
      return 1
    else
      echo "The trustiworthiness of '$rvmrc_path' is currently unknown."
      return 1
    fi
  else
    echo "There is no $rvmrc_path"
    return 1
  fi
}

__rvm_check_rvmrc_trustworthiness()
{
  # Trust when they have the flag... of doom!
  (( ${rvm_trust_rvmrcs_flag:-0} == 0 )) || return 0

  # Fail if no file given
  [[ -n "$1" ]] || return 1

  typeset _first _second saveIFS

  if [[ -n "${ZSH_VERSION:-}" ]]
  then _first=1
  else _first=0
  fi
  _second=$(( _first + 1 ))
  saveIFS="$IFS"
  IFS=$';'
  typeset -a trust
  trust=( $( __rvm_rvmrc_stored_trust "$1" ) )
  IFS="$saveIFS"
  if
    [[ "${trust[${_second}]:-'#'}" == "$(__rvm_checksum_for_contents "$1")" ]]
  then
    [[ "${trust[${_first}]}" == '1' ]] || return $?
  else
    __rvm_ask_to_trust "$1" || return $?
  fi
  true
}

__rvm_display_rvmrc()
{
  typeset _rvmrc_base
  _rvmrc_base="$(basename "${_rvmrc}")"

  __rvm_table <<-TEXT
The contents of the ${_rvmrc_base} file will now be displayed.
After reading the file, you will be prompted again for 'yes or no' to set the trust level for this particular version of the file.

Note: You will be re-prompted each time the ${_rvmrc_base} file's contents change
changes, and may change the trust setting manually at any time.
TEXT
  __rvm_wait_anykey "(( press a key to review the ${_rvmrc_base} file ))"

  printf "%b" "${rvm_warn_clr}"
  command cat -v "${_rvmrc}"
  printf "%b" "${rvm_reset_clr}"

  __rvm_table "Viewing of ${_rvmrc} complete." <<-TEXT
Trusting an ${_rvmrc_base} file means that whenever you cd into this directory, RVM will run this ${_rvmrc_base} shell script.
Note that if the contents of the file change, you will be re-prompted to review the file and adjust its trust settings. You may also change the trust settings manually at any time with the 'rvm rvmrc' command.
TEXT
}

__rvm_ask_to_trust()
{
  typeset trusted value anykey _rvmrc
  _rvmrc="${1}"

  if [[ ! -t 0 || -n "$MC_SID" ]] || (( ${rvm_promptless:=0} == 1 ))
  then return 2
  fi

  __rvm_table "NOTICE" <<-TEXT
RVM has encountered a new or modified $(basename "${_rvmrc}") file in the current directory, this is a shell script and therefore may contain any shell commands.

Examine the contents of this file carefully to be sure the contents are safe before trusting it!
Do you wish to trust '${_rvmrc}'?
Choose v[iew] below to view the contents
TEXT
  trusted=0
  while (( ! trusted ))
  do
    # TODO: extract and replace with something better like https://gist.github.com/mpapis/5232756
    printf "%b" 'y[es], n[o], v[iew], c[ancel]> '

    builtin read response
    value="$(echo -n "${response}" | \tr '[[:upper:]]' '[[:lower:]]' | __rvm_strip)"

    case "${value:-n}" in
      v|view)
        __rvm_display_rvmrc
        ;;
      y|yes)
        trusted=1
        ;;
      n|no)
        break
        ;;
      c|cancel)
        return 1
        ;;
    esac
  done

  if (( trusted ))
  then
    __rvm_trust_rvmrc "$1"
    return 0
  else
    __rvm_untrust_rvmrc "$1"
    return 1
  fi
}
