#!/bin/sh
###################################################################################################
##
## custom.sh
## This script can be run on a Mac OS X env to create custom Mac, Windows, and Linux installers.
## If run on a Linux env then only a Linux and Windows installer is built.
## There is no equivelant Windows script.
##
## http://www.crashplan.com/enterprise/support/doku.php/customize_desktop
##
###################################################################################################
function logHeaderMsg() {
	echo
	echo =================================================================================================
	echo "  $1" 
	echo
}
function getPrompt() {
	if [ "${1}" == "address" ]; then 
		PROMPT="The primary address and port to the authority that manages the accounts and issues licenses (host:port)."
	elif [ "${1}" == "secondaryAddress" ]; then 
		 PROMPT="The secondary address and port to the authority that manages the accounts and issues licenses (host:port)."
	elif [ "${1}" == "hideAddress" ]; then 
		PROMPT="Hide address from the user (yes or no)."
	elif [ "${1}" == "lockedAddress" ]; then 
		PROMPT="Lock server address setting so that user cannot change server address (true or false)."
	elif [ "${1}" == "registrationKey" ]; then 
		PROMPT="The organization registration key (AAAA-BBBB-CCCC-DDDD)."
	elif [ "${1}" == "username" ]; then 
		PROMPT="The username to use when authorizing the computer."
	elif [ "${1}" == "password" ]; then 
		PROMPT="The password used when authorizing the computer."
	elif [ "${1}" == "skinCustomized" ]; then 
		PROMPT="Have any skin files been customized (yes or no)."
	elif [ "${1}" == "proxy.enable" ]; then
		PROMPT="Connect through a proxy server (yes or no)."
	elif [ "${1}" == "proxy.pacUrl" ]; then 
		PROMPT="If using a proxy, enter the url of the PAC config file."
	elif [ "${1}" == "ssoAuth.enabled" ]; then 
		PROMPT="Enable single sign-on (yes or no)."
	elif [ "${1}" == "ssoAuth.hide" ]; then 
		PROMPT="Hide prompt to use single sign-on, it's always used."
	elif [ "${1}" == "ssoAuth.provider" ]; then 
		PROMPT="Name of the single sign-on application."
	else
		PROMPT=${1}
	fi
}
function cpFail() {
	rm -rf "${TMP}"
	logEnd "FAILED $1"
	exit 1
}
function cpSuccess() {
	rm -rf "${TMP}"
	logEnd "SUCCESS"
	exit
}
function logEnd() {
	if [ ${TIME_START} ]; then
		TIME_END=`date +%s`
		TIME_ELAPSED=$((TIME_END -  TIME_START))
	fi
	echo ""
	echo ""
	echo =================================================================================================
	if [ "${1}" ]; then
		echo "   ${1}"
	fi
	if [ ${TIME_ELAPSED} ]; then
		echo "   DONE after $(( TIME_ELAPSED / 60 ))m $(( TIME_ELAPSED % 60 ))s"
	else
		echo "   THE END"
	fi
	echo =================================================================================================
}
function optOS() {
	if [ $1 == "win" ]; then
		OS_GIVEN=true
		BUILD_WIN=true
	elif [ $1 == "mac" ]; then
		OS_GIVEN=true
		BUILD_MAC=true
	elif [ $1 == "linux" ]; then
		OS_GIVEN=true
		BUILD_LINUX=true
	elif [ $1 == "solaris" ]; then
		OS_GIVEN=true
		BUILD_SOLARIS=true
	else
		echo "Unknown OS option: $1"
	fi
}
function optInclude() {
	if [ $1 == "x64" ] || [ $1 == "64" ]; then
		BUILD_WIN64=true
	elif [ $1 == "msi" ]; then
		BUILD_MSI=true
	else
		echo "Unknown include option: $1"
	fi
}
function optExclude() {
	if [ $1 == "win" ]; then
		NO_WIN=true
	elif [ $1 == "mac" ]; then
		NO_MAC=true
	elif [ $1 == "linux" ]; then
		NO_LINUX=true
	elif [ $1 == "solaris" ]; then
		NO_SOLARIS=true
	else
		echo "Unknown exclude option: $1"
	fi
}
TIME_START=`date +%s`
SCRIPTDIR=$(dirname `ls -l $0 | awk '{ print $NF }'`)
cd "${SCRIPTDIR}"
SCRIPTDIR=`pwd`
TMP="${SCRIPTDIR}/tmp"
if [ ! -e "${TMP}" ]; then
	mkdir "${TMP}"
fi
if [ ! -e "original.properties" ] && [ -e "custom.properties" ]; then
	cp custom.properties original.properties
fi

########################################################################################
## OPTIONS
while getopts ":chi:o:v:x:" Option
do
  case $Option in
  	c     ) CLEAN=true;;
    h     ) HELP=true;;
    i     ) optInclude $OPTARG;;
    o     ) optOS $OPTARG;;
    v     ) URL=$OPTARG;;
    x     ) optExclude $OPTARG;;
    *     ) HELP=true;;   # DEFAULT
  esac
done
shift $(($OPTIND - 1))

if [ ${HELP} ]; then
	logHeaderMsg "HELP - ${HELP}"
	echo " Usage: ${0} [option]"
	echo " "
	echo " Options:"
	echo "   -? : This usage information"
	echo "   -c : Clean or delete any existing previously downloaded installers."
	echo "   -h : This usage information"
	echo "   -i {include}   : Include the given process - see include options below"
	echo "   -o {option}    : OS options - see OS options below"
	echo "   -u {url}       : CrashPlan PROe server URL to download client installers from. i.e. http://proe:4280"
	echo "   -x {exclude}   : Exclude the given process - see exclude options below"
	echo " "
	echo " OS Options:  (only build for this OS)"
	echo "   -o win         : Build the Windows customized zip"
	echo "   -o mac         : Customize the Mac installer"
	echo "   -o linux       : Customize the Linux installer"
	echo " "
	echo " Include Options:  (these are typically not included)"
	echo "   -i x64         : Also build Windows 64-bit customized zip"
	echo "   -i msi         : Also build Windows MSI customized zip"
	echo " "
	echo " Exclude Options:"
	echo "   -x win         : Do not build the Windows customized zip"
	echo "   -x mac         : Do not customize Mac installer"
	echo "   -x linux       : Do not customize Linux installer"
	exit
fi
if [ ! ${OS_GIVEN} ]; then
	BUILD_LINUX=true
	BUILD_WIN=true
	BUILD_MAC=true
	BUILD_SOLARIS=true
fi
if [ ${NO_LINUX} ]; then
	BUILD_LINUX=
fi
if [ ${NO_WIN} ]; then
	BUILD_WIN=
	BUILD_MSI=
	BUILD_WIN64=
fi
if [ ${NO_MAC} ]; then
	BUILD_MAC=
fi
if [ ${NO_SOLARIS} ]; then
	BUILD_SOLARIS=
fi


###################################################################################################
## Prompt for custom.properties
REVIEW="y"
CHANGE="n"
while [ "${REVIEW}" == "y" ] || [ "${REVIEW}" == "yes" ]; do
	# CHANGE
	if [ "${CHANGE}" == "y" ] || [ "${CHANGE}" == "yes" ]; then
		echo
		logHeaderMsg "Modify customization settings"
		sed '/^\#/d' custom.properties | sed '/^[[:space:]]*$/d' | sed 's/=.*$//g' > "tmp/names.txt"
		SSOAUTH_ENABLED=
		PROXY_ENABLE=
		PROPS=( $( cat "tmp/names.txt" ) )
		for NAME in ${PROPS[@]}
		do
			## SKIP
			if [ "_${NAME}" == "_proxy.pacUrl" ] && [ ! ${PROXY_ENABLE} ]; then
				continue;
			fi
			if [ "_${NAME}" == "_ssoAuth.hide" ] && [ ! ${SSOAUTH_ENABLED} ]; then
				continue;
			fi
			if [ "_${NAME}" == "_ssoAuth.provider" ] && [ ! ${SSOAUTH_ENABLED} ]; then
				continue;
			fi
						
			VALUE=`sed '/^\#/d' custom.properties | grep ${NAME}  | tail -n 1 | sed 's/^.*=//;s/^[[:space:]]*//;s/[[:space:]]*$//'`
			getPrompt ${NAME}
			echo
			INPUT=
			if [ "${VALUE}" ]; then
				if [ "${VALUE}" == "true" ]; then
					VALUE="yes"
				elif [ "${VALUE}" == "false" ]; then
					VALUE="no"
				fi
				echo "${PROMPT}"
				read -rp "${NAME} [${VALUE}]? " INPUT
			else 
				echo "${PROMPT}"
				read -rp "${NAME}? " INPUT
			fi
			if [ "${INPUT}" ]; then
				if [ "${NAME}" == "hideAddress" ] || [ "${NAME}" == "lockedAddress" ] || [ "${NAME}" == "skinCustomized" ] || [ "${NAME}" == "proxy.enable" ] || [ "${NAME}" == "ssoAuth.enabled" ] || [ "${NAME}" == "ssoAuth.hide" ]; then
					while [ "${INPUT}" != "yes" ] && [ "${INPUT}" != "y" ] && [ "${INPUT}" != "no" ] && [ "${INPUT}" != "n" ]; do
						read -rp "  yes or no? " INPUT
					done
					if [ "${INPUT}" == "yes" ] || [ "${INPUT}" == "y" ]; then
						INPUT="true"
					else
						INPUT="false"
					fi
				fi
				if [ "${NAME}" == "registrationKey" ]; then
					if [ "x${INPUT}" != "x!" ]; then
						INPUT=`echo ${INPUT} | tr [a-z] [A-Z]`
						TEST=`echo ${INPUT} | sed 's/[^a-zA-Z0-9]*//g'`
						while [ ${#TEST} != 16 ]; do
							read -rp "  Invalid  (Example: AAAA-BBBB-CCCC-DDDD)? " INPUT
							TEST=`echo ${INPUT} | sed 's/[^a-zA-Z0-9]*//g'`
						done
					fi
				fi

				if [ "x${INPUT}" == "x!" ]; then
					INPUT=
				fi
				
				if [ "${NAME}" == "ssoAuth.enabled" ] && [ "${INPUT}" == "true" ]; then
					SSOAUTH_ENABLED=true
				fi
				
				if [ "${NAME}" == "proxy.enable" ] && [ "${INPUT}" == "true" ]; then
					PROXY_ENABLE=true
				fi

				## Escape slashes and ampersands from the INPUT values, otherwise they are evaluated as special characters when writing to temp prop file below
				## Goofy multi-step process to escape literal backslash chars, but not backslashes used to escape other chars
				INPUT=`echo "${INPUT}" | sed -e 's/\\\/BACKSLASH/g' -e 's/\//\\\\\//g' -e 's/\&/\\\&/g' -e 's/BACKSLASH/\\\\\\\/g'`

				## Copy the change to the properties file
				sed -e "s/^${NAME}=.*/${NAME}=${INPUT}/g" custom.properties > "tmp/new.properties"
				mv "tmp/new.properties" "custom.properties"
			fi
		done
	fi

	# REVIEW
	logHeaderMsg "Please review your customization settings below:"
	sed '/^\#/d' custom.properties | sed '/^[[:space:]]*$/d'
	echo

	# PROMPT
	read -p "Change settings  (yes, no, or revert) [no]? " CHANGE
	if [ ! "${CHANGE}" ]; then
		CHANGE="no"
	fi
	while [ "${CHANGE}" != "yes" ] && [ "${CHANGE}" != "y" ] && [ "${CHANGE}" != "no" ] && [ "${CHANGE}" != "n" ] && [ "${CHANGE}" != "revert" ] && [ "${CHANGE}" != "r" ]; do
		read -p "yes, no, or revert? " CHANGE
	done
	if [ "${CHANGE}" == "revert" ] || [ "${CHANGE}" == "r" ]; then
		cp original.properties custom.properties
		REVIEW="yes"
		CHANGE="no"
	else
		REVIEW=${CHANGE}
	fi
done

while [ ! "${URL}" ]; do
	URL=`cat .url 2> /dev/null`
	
	if [ ${URL} ]; then
		read -p "CrashPlan PROe server url  [${URL}]? " INPUT
	else
		read -p "CrashPlan PROe server url  (Example: http://proe:4280)? " INPUT
	fi
	if [ "${INPUT}" ]; then
		URL=${INPUT}
		echo ${URL} > .url
	fi
done


TIME_START=`date +%s`


###################################################################################################
## Custom SKIN
CUSTOM_SKIN=
if [ -d "skin" ] && [ $LOGO_MD5_OLD ] && [ $SPLASH_MD5_OLD ] && [ $PROP_MD5_OLD ] && [ $BG_MD5_OLD ]; then
	if [ "`uname`" = 'Darwin' ]; then
		MD5CMD=md5
	else
		MD5CMD=md5sum
	fi
	LOGO_MD5=`$MD5CMD -q skin/logo_main.png`
	SPLASH_MD5=`$MD5CMD -q skin/splash_default.png`
	PROP_MD5=`$MD5CMD -q skin/skin.properties`
	BG_MD5=`$MD5CMD -q skin/window_bg.jpg`

	if [ "x$LOGO_MD5" != "x$LOGO_MD5_OLD" ] || [ "x$SPLASH_MD5" != "x$SPLASH_MD5_OLD" ] || [ "x$PROP_MD5" != "x$PROP_MD5_OLD" ] || [ "x$BG_MD5" != "x$BG_MD5_OLD" ]; then
		CUSTOM_SKIN=true
	fi
fi


###################################################################################################
## MAC
if [ "`uname`" = 'Darwin' ] && [ ${BUILD_MAC} ]; then
	logHeaderMsg "Copy customizations into Mac installer, ${DMG}"

	DMG="CrashPlanPROe_Mac.dmg"
	if [ -e ${DMG} ] && [ "${CLEAN}" ]; then
		rm -f ${DMG}
	fi
	if [ ! -e ${DMG} ]; then
		echo "Downloading Mac installer..."
		curl -O "${URL}/download/${DMG}" || cpFail "Failed to download Mac installer."
	fi

		## eject CrashPlanPROe
	if [ -e /Volumes/CrashPlanPROe ]; then
		echo "Eject CrashPlanPROe"
		hdiutil eject /Volumes/CrashPlanPROe || cpFail "Failed to eject CrashPlanPROe."
	fi
	
	## mount dmg
	echo "Mount DMG."
	hdiutil attach ${DMG} || cpFail "Failed to mount DMG."

		## copy custom
	DST="/Volumes/CrashPlanPROe/.Custom"
	if [ -e "${DST}" ]; then
		rm -rf "${DST}"
	fi
	mkdir -v "${DST}"
	if [ ${CUSTOM_SKIN} ]; then
		echo "skin -> ${DST}/skin"
		cp -R skin "${DST}" || cpFail "Failed to copy skin into DMG."
		rm -rf "${DST}/skin/tray"
	fi
	cp -v userInfo.sh "${DST}" || cpFail "Failed to copy userInfo.sh into DMG."
	cp -v custom.properties "${DST}" || cpFail "Failed to copy custom.properties into DMG."

		## eject CrashPlanPROe
	echo "Eject CrashPlanPROe"
	hdiutil eject /Volumes/CrashPlanPROe
fi


###################################################################################################
## LINUX
if [ ${BUILD_LINUX} ]; then
	logHeaderMsg "Copy customizations into Linux installer, ${TAR}"

	TAR="CrashPlanPROe_Linux.tgz"
	if [ -e ${TAR} ] && [ "${CLEAN}" ]; then
		rm -f ${TAR}
	fi
	if [ ! -e ${TAR} ]; then
		echo "Downloading Linux installer..."
		curl -O "${URL}/download/${TAR}" || cpFail "Failed to download Linux installer."
	fi

	## extract Linux installer
	echo "Extract Linux installer"
	tar -xf ${TAR} || cpFail "Failed to extract Linux installer"

	## copy custom
	DST="CrashPlanPROe-install/custom"
	if [ -e "${DST}" ]; then
		rm -rf "${DST}"
	fi
	mkdir -v "${DST}"
	if [ ${CUSTOM_SKIN} ]; then
		echo "skin -> ${DST}/skin"
		cp -R skin "${DST}" || cpFail "Failed to copy skin into Linux installer"
		rm -rf "${DST}/skin/tray"
	fi
	cp -v custom.properties "${DST}" || cpFail "Failed to copy custom.properties into Linux installer"
	
	## create Linux installer
	mv -v ${TAR} "${TAR}.bak"
	echo "Package Linux installer"
	tar --exclude ".svn" -zcf ${TAR} "CrashPlanPROe-install" || FAIL_TAR=true
	if [ ${FAIL_TAR} ]; then
		mv -v "${TAR}.bak" ${TAR}
		rm -rf "CrashPlanPROe-install"
		cpFail "Failed to recreate the Linux installer"
	fi
	rm -rf "CrashPlanPROe-install"
	rm -v "${TAR}.bak"
fi


###################################################################################################
## WIN
if [ ${BUILD_WIN} ]; then
	EXE="CrashPlanPROe_Win.exe"
	ZIP="CrashPlanPROe_Win.zip"
	logHeaderMsg "Create customized zip for Windows self-extracting EXE, ${ZIP}"

	if [ -e ${EXE} ] && [ "${CLEAN}" ]; then
		rm -f ${EXE}
	fi
	if [ ! -e ${EXE} ]; then
		echo "Downloading Windows EXE installer..."
		curl -O "${URL}/download/${EXE}" || cpFail "Failed to download Windows EXE installer."
	fi

	DST_PARENT="${TMP}/win/"
	DST="${DST_PARENT}custom"
	if [ -d "${DST_PARENT}" ]; then
		rm -rf "${DST_PARENT}"
	fi
	if [ -e ${ZIP} ]; then
		rm -f ${ZIP}
	fi
	mkdir -vp "${DST}"
	
	## copy custom
	if [ ${CUSTOM_SKIN} ]; then
		echo "skin -> ${DST}/skin"
		cp -R skin "${DST}" || cpFail "Failed to copy skin for Windows zip"
	fi
	cp -v custom.properties "${DST}" || cpFail "Failed to copy custom.properties for Windows zip"
	cp -v cpinstall.ico "${DST_PARENT}"
	cp -v ${EXE} "${DST_PARENT}"
	
	## create Windows ZIP
	cd "${DST_PARENT}"
	zip -x \*/.svn/* -r -D "../../${ZIP}" * || cpFail "Failed to build Windows EXE zip"
	echo "tmp/win/${ZIP} -> ./${ZIP}"
	rm "${DST_PARENT}${EXE}"
	cd "${SCRIPTDIR}"
	
	###############################################################################################
	## WIN EXE 64-bit
	if [ ${BUILD_WIN64} ]; then
		EXE="CrashPlanPROe-x64_Win.exe"
		ZIP="CrashPlanPROe-x64_Win.zip"
		logHeaderMsg "Create customized zip for Windows self-extracting 64-bit EXE, ${ZIP}"
	
		if [ -e ${EXE} ] && [ "${CLEAN}" ]; then
			rm -f ${EXE}
		fi
		if [ ! -e ${EXE} ]; then
			echo "Downloading Windows 64-bit EXE installer..."
			curl -O "${URL}/download/${EXE}" || cpFail "Failed to download Windows 64-bit EXE installer."
		fi
	
		## copy custom
		rm -fv "${DST_PARENT}*.exe"
		cp -v ${EXE} "${DST_PARENT}"
		
		## create Windows ZIP
		cd "${DST_PARENT}"
		rm -f "../../${ZIP}"
		##read -p "Check? " CHECK
		zip -x \*/.svn/* -r -D "../../${ZIP}" * || cpFail "Failed to build Windows 64-bit EXE zip"
		echo "tmp/win/${ZIP} -> ./${ZIP}"
		rm "${DST_PARENT}${EXE}"
		cd "${SCRIPTDIR}"
	fi
	
	###############################################################################################
	## WIN MSI
	echo "BUILD_MSI=${BUILD_MSI}"
	if [ ${BUILD_MSI} ]; then
		MSI="CrashPlanPROe_Win.msi"
		ZIP="CrashPlanPROe-msi_Win.zip"
		logHeaderMsg "Create customized zip for Windows MSI distribution, ${ZIP}"
	
		if [ -e ${MSI} ] && [ ${CLEAN} ]; then
			rm -f ${MSI}
		fi
		if [ ! -e ${MSI} ]; then
			echo "Downloading Windows MSI installer..."
			curl -O "${URL}/download/${MSI}" || cpFail "Failed to download Windows MSI installer."
		fi
	
		## copy custom
		rm -fv "${DST_PARENT}*.exe"
		cp -v ${MSI} "${DST_PARENT}"
		
		## create Windows ZIP
		cd "${DST_PARENT}"
		rm -f "../../${ZIP}"
		##read -p "Check? " CHECK
		zip -x \*/.svn/* -r -D "../../${ZIP}" * || cpFail "Failed to build Windows MSI zip"
		echo "tmp/win/${ZIP} -> ./${ZIP}"
		rm "${DST_PARENT}${MSI}"
		cd "${SCRIPTDIR}"
	fi
fi



cpSuccess
###################################################################################################
###################################################################################################