#!/usr/bin/env bash

# JKF 2021-05-18
# Some sites seem to get in a mess with their *.tpl template files.
# This tool attempts to fix these problems.
# If it can find the right version of a template file locally, by
# checking MD5 checksums, then it will prompt you to replace the wrong
# version with that file.
# If it can't find the right version locally, it will go and fetch a
# fresh set for your particular ZendTo version from https://zend.to and
# prompt you to replace it with that fresh version.


# Work out the MD5 checksum of $1 in a form
# that should match exactly with the contents
# of my 'checksums' file.
# If the file doesn't exist, return 0.
GetMD5() {
	if [ -f "$1" ]; then
		R="$( $MD5Command $1 | \
		      awk '{ print $'$MD5Word' }' | \
		      tr 'A-F' 'a-f' | \
		      tr -dc '0-9a-f' )"
		echo $R
	else
		echo 0
	fi
}

# Tell the user what is happening, in bold
# Taken from my ZendTo Installer lib/functions.sh library.
shout() {
  printf '\033[1m'"$*"'\033[0m\n'
}

# Prompt the user for a response. Pass in
# 1. prompt string
# 2. default default value to be used if the default is blank
# 3. default value (what we guess it should be)
# Call it like the examples below.
# Taken from my ZendTo Installer lib/functions.sh library.
prompt() {
  PROMPT="$1"
  DEFDEF="$2"
  DEF="$3"

  # No suggested value? Use the "default default"
  if [ "x$DEF" = "x" ]; then
    DEF="$DEFDEF"
  fi

  # No default default either? Then don't tell the user anything.
  # Pressing return will result in an empty answer, which may be
  # what we want.
  if [ "x$DEF" = "x" ]; then
    DEFOFFERED=''
  else
    DEFOFFERED=" [Default is $DEF]"
  fi

  if [ "x$ALLDEFAULTS" = "xy" ]; then
    printf "\033[1m$PROMPT$DEFOFFERED:\033[0m $DEF\n" 1>&2
    ANSWER="$DEF"
  else
    printf "\033[1m$PROMPT$DEFOFFERED:\033[0m " 1>&2
    read ANSWER
    if [ "x$ANSWER" = "x" ]; then
      ANSWER="$DEF"
    fi
  fi

  echo "$ANSWER"
}

# Ask a yes/no question. Return true (0) if they said yes, 1 otherwise.
# Pass in the prompt and the default to offer ('y' or 'n').
# Returns true (0) if they said yes. False (1) otherwise.
# Taken from my ZendTo Installer lib/functions.sh library.
yesno() {
	YPROMPT="$1"

	YANSWER=''
	while [ "x$YANSWER" != "xn" -a "x$YANSWER" != "xy" ]
	do
		YANSWER="$(prompt "$YPROMPT (y/n)" "y" "y" )"
		# Turn anything into a single lower-case letter
		YANSWER="$(echo "$YANSWER" | cut -c 1 | tr '[:upper:]' '[:lower:]' )"
	done
	if [ "x$YANSWER" = "xy" ]; then
		return 0
	fi
	return 1
}

echo 'Checking all your *.tpl files match the shipped ones for this version:'
echo

# Work out where their *.tpl templates are stored
if [ "x$ZENDTOPREFS" = "x" ]; then
	ZENDTOPREFS="$1"
fi
if [ "x$ZENDTOPREFS" = "x" ]; then
	ZENDTOPREFS="/opt/zendto/config/preferences.php"
fi
ZTCONFIGDIR="$( dirname "$ZENDTOPREFS" )"
ZTDIR="$( dirname "$ZTCONFIGDIR" )"
TEMPLATESDIR="$ZTDIR/templates"

# Found it?
if [ ! -d "$TEMPLATESDIR" ]; then
	echo Sorry, I cannot find your '*.tpl' ZendTo template files.
	echo Please ensure the "ZENDTOPREFS" environment variable
	echo is set correctly, then re-run me.
	exit 1
fi

echo "Templates should be in $TEMPLATESDIR"
cd "$TEMPLATESDIR"

#
# Find which command and which word of its output
# gives us the MD5 checksum of a file
#
TESTFILE=about.tpl
MD5Command="$( command -v md5 )"
[[ "x$MD5Command" = "x" ]] && MD5Command="$( command -v md5sum )"

i=0
MD5Word=notfound
for F in `$MD5Command $TESTFILE`
do
  #echo ${#F}
  i=$((i+1))
  if [ ${#F} = 32 ]; then
    MD5Word=$i
  fi
done
if [ "x$MD5Word" != "xnotfound" ]; then
  :
  #echo Found word $MD5Word to be the checksum
else
  echo "Please ensure you have the 'md5sum' command installed."
  echo "Then try again."
  exit 1
fi

WrongFiles=()
RightFiles=()
AnyNotFound=no
AllCorrect=yes

while read Checksum Template; do
	T="$(GetMD5 $Template)"
	if [ "$T" = "$Checksum" ]; then
		#echo "$Template is correct"
		continue
	fi

	AllCorrect=no
	# File $F is not what it should be.
	# Do we have a correct copy in here too?
	Found=notfound
	for Possible in ${Template}*
	do
		#echo Testing "$Possible"
		U="$(GetMD5 "$Possible")"
		if [ "$U" = "$Checksum" ]; then
			# Found $Possible is the right file
			#echo Found match with "$Template" and "$Possible"
			Found="$Possible"
			break
		fi
	done

	WrongFiles+=($Template)
	RightFiles+=($Found) # either the filename or 'notfound'

	# Did we find a copy here?
	if [ "$Found" != "notfound" ]; then
		# Yes!
		echo The correct shipped version of "$Template" is "$Found"
		echo
	else
		# No :-(
		echo I could not find a correct shipped version of "$Template",
		echo I will need to go and fetch you a new one from https://zend.to.
		echo
		AnyNotFound=yes
	fi

done < checksums

if [ "$AllCorrect" = "yes" ]; then
	echo All your template files correctly match the shipped versions.
	exit 0
fi

# Do we need to fetch a new copy of the template files?
if [ "$AnyNotFound" = "yes" ]; then
	# Fetch the tgz distribution and unpack it safely
	FetchDir="$( mktemp -d )"
	ZTVersion="$( /usr/bin/env php -r "include '$ZENDTOPREFS'; echo ZTVERSION;" )"
	#echo Fetching a fresh set of templates for version $ZTVersion
	URL="https://zend.to/files/ZendTo-${ZTVersion}.tgz"
	curl --silent --insecure -o $FetchDir/ZendTo.tgz "$URL"
	error=no
	if [ -f $FetchDir/ZendTo.tgz ]; then
		tgzsize="$( stat -c%s $FetchDir/ZendTo.tgz )"
		if [ "$tgzsize" -lt 2000 ]; then
			error=yes
		fi
	else
		error=yes
	fi
	if [ "$error" = "yes" ]; then
		echo Attempt to fetch "$URL" failed.
		echo I need to be able to use it to fetch the latest
		echo correct version of at least 1 of your ZendTo template
		echo files in $TEMPLATESDIR.
	else
		# Got the tgz file, so unpack the templates from it.
		echo I have fetched a fresh copy of the template files for $ZTVersion
		echo and put them in $FetchDir
		tar xCf $FetchDir $FetchDir/ZendTo.tgz ZendTo-$ZTVersion/templates
	fi
	echo
	FetchT="$FetchDir/ZendTo-$ZTVersion/templates"
fi

# Now loop through each WrongFiles element, finding the
# correct file to replace it with
for i in ${!WrongFiles[@]}; do
	Wrong=${WrongFiles[$i]}
	Right=${RightFiles[$i]}
	if [ "x$Right" = "xnotfound" ]; then
		Right="$FetchT/$Wrong"
	fi
	#echo I need to replace $Wrong with $Right
	if yesno "Should I replace $Wrong with $Right" "y"; then
		if [ -f "$Right" ]; then
			# Replace it without touching the permissions or
			# SELinux attributes at all
			cat "$Right" > "$Wrong"
			rm -f "$Right"
		else
			echo "Failed to find $Right"
		fi
	fi
done

# Clean up
if [ "$AnyNotFound" = "yes" ]; then
	echo
	shout Would you like me to clean up the temporary copy of the ZendTo files I
	if yesno "downloaded into $FetchDir" "y"; then
		rm -rf "$FetchDir"
	fi
fi
# In case they are using SELinux, quietly reset all the security attributes
restorecon -FR /opt/zendto/templates >/dev/null 2>&1

exit 0
