#!/bin/bash
# download and update firefox to latest official version
# need to install gtk3, libapulse, and insert "sandbox" stuff
# requires bash 4.3 or newer for arrays and nameref
# jamesbond 2015, 2017
# MIT license


export TEXTDOMAIN=get_app

### config
APPTITLE="$(gettext 'Update Firefox')"
WORKDIR=/tmp/update-firefox.$$
ARCH=${ARCH:-x86_64} # i686 for 32-bit
case $ARCH in
	x86_64)
		FFARCH=linux64
		LIBDIR=lib64
		;;
	
	i686)
		FFARCH=linux
		LIBDIR=lib
		;;
	*)
		echo "$ARCH not supported"
		exit 1
		;;
esac

declare -A LANGUAGES=(
   [English (US)]=en-US
   [Acholi]=ach
   [Afrikaans]=af
   [Albanian]=sq
   [Arabic]=ar
   [Aragonese]=an
   [Armenian]=hy-AM
   [Assamese]=as
   [Asturian]=ast
   [Azerbaijani]=az
   [Basque]=eu
   [Belarusian]=be
   [Bengali (Bangladesh)]=bn-BD
   [Bengali (India)]=bn-IN
   [Bosnian]=bs
   [Breton]=br
   [Bulgarian]=bg
   [Catalan]=ca
   [Chinese (Simplified)]=zh-CN
   [Chinese (Traditional)]=zh-TW
   [Croatian]=hr
   [Czech]=cs
   [Danish]=da
   [Dutch]=nl
   [English (British)]=en-GB
   [English (South African)]=en-ZA
   [Esperanto]=eo
   [Estonian]=et
   [Finnish]=fi
   [French]=fr
   [Frisian]=fy-NL
   [Fulah]=ff
   [Gaelic (Scotland)]=gd
   [Galician]=gl
   [German]=de
   [Greek]=el
   [Gujarati (India)]=gu-IN
   [Hebrew]=he
   [Hindi (India)]=hi-IN
   [Hungarian]=hu
   [Icelandic]=is
   [Indonesian]=id
   [Irish]=ga-IE
   [Italian]=it
   [Kannada]=kn
   [Kazakh]=kk
   [Khmer]=km
   [Korean]=ko
   [Latvian]=lv
   [Ligurian]=lij
   [Lithuanian]=lt
   [Lower Sorbian]=dsb
   [Macedonian]=mk
   [Maithili]=mai
   [Malay]=ms
   [Malayalam]=ml
   [Marathi]=mr
   [Norwegian (BokmÃ¥l)]=nb-NO
   [Norwegian (Nynorsk)]=nn-NO
   [Oriya]=or
   [Persian]=fa
   [Polish]=pl
   [Portuguese (Brazilian)]=pt-BR
   [Portuguese (Portugal)]=pt-PT
   [Punjabi (India)]=pa-IN
   [Romanian]=ro
   [Romansh]=rm
   [Russian]=ru
   [Serbian]=sr
   [Sinhala]=si
   [Slovak]=sk
   [Slovenian]=sl
   [Songhai]=son
   [Spanish (Argentina)]=es-AR
   [Spanish (Chile)]=es-CL
   [Spanish (Mexico)]=es-MX
   [Spanish (Spain)]=es-ES
   [Swedish]=sv-SE
   [Tamil]=ta
   [Telugu]=te
   [Thai]=th
   [Turkish]=tr
   [Ukrainian]=urk
   [Upper Sorbian]=hsb
   [Uzbek]=uz
   [Vietnamese]=vi
   [Welsh]=cy
   [Xhosa]=xh
)

declare -A CHANNELS=(
   [Stable]=latest
   [Extended Support Release]=esr-latest
   [Beta]=beta-latest
)

# make sure we cleanup after ourselves
trap 'rm -rf $WORKDIR; exit' 0 INT HUP TERM

### generic helpers
# $1-text
msg() {
	[ -z "$DISPLAY" ] && echo "$1" ||
	Xdialog --title "$APPTITLE" --infobox "$1" 0 0 10000
}

# are we root?
check_root() {
	if [ $(id -u) -ne 0 ]; then
		msg "$(gettext 'You must be root.')"
		exit 1
	fi
}

# $1-text, returns true/false
yesno() {
	local p
	if [ -z "$DISPLAY" ]; then
		printf "%s\nType [yes] to continue: " "$1"
		read p
		case "${p,,}" in
			yes) return 0
		esac
		return 1
	else
		Xdialog --title "$APPTITLE" --yesno "$1" 0 0
	fi
}

# $1-text
splash() {
    if [ -z "$DISPLAY" ]; then
        echo "$1"
    else
        if [ "$1" ]; then
            [ $SPID ] && kill $SPID
            Xdialog --title "$APPTITLE" --no-buttons --infobox "$1" 0 0 100000000 &
            SPID=$!
        else
            [ $SPID ] && kill $SPID
            SPID=""
        fi
    fi
}

# $@ - words
sortwords() {
	for p; do echo $p; done | sort -u
}

# $1-text $2-selections $3-default
choose() {
	local -n ITEMS=${2}
	local value index xdialog_items="" state
	if [ -z "$DISPLAY" ]; then
		echo "$1"
		OIFS="$IFS"; IFS=$'\n'
		select index in $(sortwords "${!ITEMS[@]}"); do
			#echo Selected Lang is $index, its code is ${ITEMS["$index"]}
			echo ${ITEMS["$index"]}
			break
		done
		IFS="$OIFS"
	else
		OIFS="$IFS"; IFS=$'\n'
		for index in $(sortwords "${!ITEMS[@]}"); do
			[ "$index" = "$3" ] && state=on || state=off
			xdialog_items="$xdialog_items \"${ITEMS[$index]}\" \"$index\" $state"
		done
		IFS="$OIFS"
		eval Xdialog --title \"$APPTITLE\" --stdout --no-tags --radiolist \"$1\" 30 50 10 $xdialog_items
	fi
}

check_online () {
    if [ ! "$(grep up /sys/class/net/*/operstate)" ]; then
        msg "$gettext 'No connection to internet. Leaving now.'"
        exit
    fi    
}

# $1-pkgname (no space)
download_support_libraries() {
	local PKG=$1
	if [ "$(slapt-get --search $PKG)" = "" ] ; then
		splash "$(gettext "Updating package list, please wait...")"
		slapt-get --update
	fi
	if ! slapt-get --installed | grep -q "^$PKG.*$ARCH"; then
		splash "$(gettext "Installing $PKG, please wait...")"
		if ! slapt-get --install $PKG; then
			splash
			msg "$(gettext "Failed to install $PKG.")"
			exit 1
		fi
	fi
}


### firefox-specific stuff

# $1-version
package_firefox() {
	splash "$(eval echo $(gettext 'Making firefox $1 package, the package will be stored in $HOME'))"
	mkdir pkg.$$; cd pkg.$$
	
	# extract
	mkdir -p usr/$LIBDIR/ usr/share/pixmaps usr/bin usr/share/applications
	tar -xf ../firefox.tar.bz2 -C usr/$LIBDIR
	
	# setup symlinks, etc
	mv usr/$LIBDIR/firefox usr/$LIBDIR/firefox-$1
	ln -s firefox-$1 usr/$LIBDIR/firefox
	ln -s /usr/$LIBDIR/firefox/firefox usr/bin/firefox
    for ICONPATH in /usr/$LIBDIR/firefox-$LATEST/browser/icons/mozicon128.png \
        /usr/$LIBDIR/firefox-$LATEST/browser/chrome/icons/default/default128.png
    do
        [ -e $ICONPATH ] && break;
    done
    ln -s $ICONPATH usr/share/pixmaps/firefox.png &&
    
	# run firefox as spot
	# TODO: symlink to program-spot in future versions
	cat << "EOF" >> usr/bin/firefox-spot &&
#!/bin/dash
exec /usr/bin/run-as-spot /usr/bin/firefox "$@"
EOF
	chmod +x usr/bin/firefox-spot &&
	
	# desktop file
	cat << "EOF" > usr/share/applications/firefox.desktop 
[Desktop Entry]
Version=1.0
Name=Firefox Browser
GenericName=Web Browser
Comment=Your web, the way you like it
Exec=firefox-spot %U
Icon=firefox.png
Terminal=false
Type=Application
MimeType=text/html;text/xml;application/xhtml+xml;application/vnd.mozilla.xul+xml;text/mml;x-scheme-handler/http;x-scheme-handler/https;
StartupNotify=false
X-MultipleArgs=false
X-Desktop-File-Install-Version=0.16
Categories=WebBrowser;
Encoding=UTF-8
EOF

	# desc
	mkdir install
	cat << EOF > install/slack-desc
firefox: firefox $1 (Web browser)  
firefox:  
firefox: Official Firefox web browser from Mozilla.
firefox: 
firefox: 
firefox: 
firefox: 
firefox: 
firefox: 
firefox: 
firefox:  
EOF
	# set default prefs to un-mute Firefox
	cat << EOF > usr/$LIBDIR/firefox-$1/defaults/pref/autoconfig.js
// Enable settings in mozilla.cfg
pref("general.config.filename", "mozilla.cfg");
pref("general.config.obscure_value", 0);
EOF
	cat << EOF > usr/$LIBDIR/firefox-$1/mozilla.cfg
// Need these settings to work
defaultPref("security.sandbox.content.syscall_whitelist", "16,54");
defaultPref("security.sandbox.content.write_path_whitelist", "/dev/snd/");
EOF

	# make the pkg
	makepkg -c n -l n $HOME/firefox-$1-$ARCH-official.txz > /dev/null 2>&1
}

# $1-version
install_firefox() {
	splash "$(eval echo $(gettext 'Upgrading firefox to $1...'))"
	removepkg firefox
	installpkg $HOME/firefox-$1-$ARCH-official.txz
	splash
	msg "$(gettext 'Done.')"
}

get_current_version() {
	ls -ld /usr/$LIBDIR/firefox-* | tail -n 1 | sed 's/.*firefox-//'
}

# $1-language $2-channel (latest/esr-latest/beta-latest)
# This trick is from https://gist.github.com/ruario/9672798
get_latest_version() {
	local FFLANG=${1:-en-US}
	local FFCHANNEL=${2:-latest}
	wget --spider -S --max-redirect 0 "https://download.mozilla.org/?product=firefox-${FFCHANNEL}&os=$FFARCH&lang=${FFLANG}" 2>&1 |
	sed -n '/Location: /{s|.*/firefox-\(.*\)\.tar.*|\1|p;q;}'
}

#### main
check_root
check_online
! yesno "\
$(gettext 'Running this program may replace your Firefox with the OFFICIAL binary
from Mozilla, instead of Fatdog-build one.') $(gettext 'Recent versions require
GTK3 libraries and apulse library to be installed.') $(gettext 'In addition, 
there may be other libraries that missing from Fatdog that prevent this 
official binary from running.') $(gettext 'Are you sure you want to continue?')
" && exit

mkdir $WORKDIR; cd $WORKDIR

	FFCHANNEL=$(choose "Choose channels" CHANNELS "Stable") || exit
	FFLANG=$(choose "Choose languages" LANGUAGES "English (US)") || exit
	LATEST=$(get_latest_version $FFLANG $FFCHANNEL)
	CURRENT=$(get_current_version)	

	if [ "$LATEST" = "$CURRENT" ]; then
		msg "$(eval echo `gettext 'You are already running the latest version $LATEST.'`)"
	else
		if [ -z $CURRENT ]; then
			! yesno "$(gettext 'You do not seem to have firefox installed.')
$(gettext 'Do you want to install it?')" && exit
		fi

		# install support libraries
		download_support_libraries gtk3
		download_support_libraries libapulse

		# download the stuff - this is the official download path from Mozilla
		# see https://ftp.mozilla.org/pub/firefox/releases/latest/README.txt
		splash "$(eval echo $(gettext 'Downloading firefox $LATEST, please wait ...'))"
		if wget -O firefox.tar.bz2 "https://download.mozilla.org/?product=firefox-$FFCHANNEL&os=$FFARCH&lang=$FFLANG"; then
			package_firefox $LATEST
			install_firefox	$LATEST	
		else
			splash
			msg "$(gettext 'Failed to download.')"
		fi
	fi
	
cd - >/dev/null
exit
