#! /bin/sh
#
#SSAUpdater: a tool for automatic downloading and installing of security patches.
#it runs on all slackware system (including slack ports to other architectures?)
#it is written in ash so you can run it under your preferred shell.
#
#!!!														   !!!
#!!! don't run this script as stand alone application          !!!
#!!! SSAUpdater has been designed to be called by SSANotifier  !!!
#!!!														   !!!
#
#v.0.90.0
#
#to do:
#-prova gdialog
#-prova xdialog


#--------------------------------------------------
#general settings

TMPDIR=/tmp/SSANotifier

#CONFDIR="/etc/SSANotifier"
#CONFDIR="/home/utente/slack/scripting/SSANotifier/devel"	#just for debugging
#CONFFILE=$CONFDIR/"SSANotifier.conf"

#PATCHLIST="FILE_LIST"
#MD5LIST="CHECKSUMS.md5"

#--------------------------------------------------


#--------------------------------------------------
#"resource table" with some messages displayed on screen
TITLE="SSAUpdater"
# UMESSAGE="Upgrade the system?"
# DMESSAGE="Currently downloading:"
# FMESSAGE="Upgrading the system"
# GMESSAGE="please wait..."
#--------------------------------------------------


#--------------------------------------------------
#auxiliary functions

RemoveOverridden ()
{
##
## this function remove any old version of a patchd
## it is called olny after a new patch version has been checked, so we can be _REALLY_ sure
## that the file is no longer required
##

for FILE in $GPGPATCHES; do
	#retrieve the patch name discarding version, arch and build informations
	FNAME=$(echo $FILE | awk -F - '{for (i=1; i<NF-3; i++) {printf $i"-"}; printf $(NF-3)}')
	#look if we find an old version saved in cache
	OLDVERSIONLIST=$(echo $OVERRIDDENPATCHES | sed -e 's| |\n|g' | grep -w "$FNAME" 2>/dev/null)
	#we can have more matches
	#(eg. if we grep the "gimp" patch we can find both "gimp-print" and "gimp" packages)
	for nFILE in $OLDVERSIONLIST; do
		#retrieve the file name of the installed package discarding version, arch and build infos
		INAME=$(echo $nFILE | awk -F - '{for (i=1; i<NF-3; i++) {printf $i"-"}; printf $(NF-3)}')
		#found exactly the same package (this discards "gimp-print" if we are patching the "gimp" package)
		[ "$INAME" = "$FNAME" ] && {
		#remove it
		rm $nFILE*
#continue
		}
	done
done
}
#--------------------------------------------------


#--------------------------------------------------
#entry point

#load settings
. $CONFFILE

#if the local mirror doesn't exist we create it!
[ -d $LOCALMIRROR ] || {
mkdir -p $LOCALMIRROR || { echo "$0 ABORT: unable to create local mirror"; exit 1; }
}

#check for notification type
case $NOTIFY in
"KDE")
	[ $(which kdialog) ] || { echo "$0 ABORT: kdialog not installed"; exit 1; }
	DIALOGBASE=$(which kdialog)
	[ $(which kdesu) ] || { echo "$0 ABORT: kdesu not installed"; exit 1; }
	SUGUI=$(which kdesu)
	SUGUIOPTS="--noignorebutton -d -n -t -c"
	PASSIVE="--passivepopup"
	SIZE1="500 300"
	SIZE2=""
	SIZE3="800 600"
	SIZE4="1000"
	SIZE5="1000"
;;
"SHELL")
	[ $(which dialog) ] || { echo "$0 ABORT: dialog not installed"; exit 1; }
	DIALOGBASE=$(which dialog)
	SUGUI=$(which su)
	SUGUIOPTS="-c"
	PASSIVE="--infobox"
	SIZE1="20 80"
	SIZE2="10 80"
	SIZE3="20 80"
	SIZE4="10 80"
	SIZE5="10 80"
;;
"GNOME")
	[ $(which zenity) ] || { echo "$0 ABORT: gdialog/zenity not installed"; exit 1; }
	DIALOGBASE=$(which zenity)
	[ $(which gksu) ] || { echo "$0 ABORT: gksu not installed"; exit 1; }
	SUGUI=$(which gksu)
	SUGUIOPTS="-u root -w"
	PASSIVE="--progress --pulsate --auto-close --width=300"
	SIZE1="500 300"
	SIZE2=""
	SIZE3="800"
	SIZE3A="600"
	SIZE4="200"
	SIZE5="1000"
;;
*)
	echo "$0 ABORT: selected notification not supported"
	exit 1
;;
esac

#create a log file
TMPLOG=$TMPDIR/message-$(date +%Y%m%d%H%M%S)
echo "SSANotifier report:" > $TMPLOG

#clean repository
for OFILE in $OBSOLETEPATCHES; do
	echo "removed obsolete patch $OFILE" >> $TMPLOG
	rm $OFILE*
done

#if we want to check the gpg encription we download the gpgkey file
#!!!
#!!! useful to check for its existance and set a flag to force the key download every time
#!!!
[ $CHECKGPG -eq 1 ] && {
	[ -f $(basename $GPGKEY) ] && rm $(basename $GPGKEY) #force old key remotion.
	$WGET $WGETOPTS $GPGKEY || { echo "$0 ABORT: unable to download gpg key"; exit 1; }
	#we import the key in our keyring
	[ $($GPG --import $(basename $GPGKEY) 1> /dev/null) ] && { echo "$0 ABORT: unable to import gpg key"; exit 1; }
}

#if we want to check the md5sum we download the checksum file
[ $CHECKMD5 -eq 1 ] && {
	[ -f "$MD5LIST" ] && rm "$MD5LIST"
	$WGET $WGETOPTS $SERVER/"$MD5LIST" || { echo "$0 ABORT: unable to download md5sums"; exit 1; }
	[ $CHECKGPG -eq 1 ] && {
		#if we want to check the gpg key we download the checksum asc file...
		rm "$MD5LIST"".asc" 2> /dev/null
		$WGET $WGETOPTS $SERVER/"$MD5LIST"".asc" || { echo "$0 ABORT: unable to download md5sums asc"; exit 1; }
		#...and we test it
		[ $($GPG --verify $MD5LIST".asc" $MD5LIST 1> /dev/null) ] && \
			{ echo "$0 ABORT: md5sums didn't pass gpg check"; exit 1; }
	}
}

#echo ${NEWPATCHES}

#if we have a new patch we download it
WGETPATCHES=""
for FILE in $NEWPATCHES; do
	$DIALOGBASE --title "$DMESSAGE" $PASSIVE $(basename $FILE) $SIZE4 2>/dev/null &
	echo "$WGET $WGETOPTS -P $TMPDIR $SERVER/$FILE" >> $TMPLOG
	$WGET $WGETOPTS -P $TMPDIR $SERVER/$FILE 
	[ $? -eq 0 ] || {
		rm $TMPDIR/$(basename $FILE) &>/dev/null	#if we fail and we have a partial download we remove the file
		echo "unable to download $(basename $FILE): file discarded" >> $TMPLOG
#this line kills the kde popup dialog if it is used... otherwise it does nothing!
		kill $(ps aux | grep -m1 "passivepopup" | awk '{printf $2"\n"}') &>/dev/null
		continue
	}
	#if we want to check the gpg key we download tgz signatures
	[ $CHECKGPG -eq 1 ] && {
		echo "$WGET $WGETOPTS -P $TMPDIR $SERVER/$FILE.asc" >> $TMPLOG
		$WGET $WGETOPTS -P $TMPDIR $SERVER/$FILE."asc"
 		[ $? -eq 0 ] || {
			rm $TMPDIR/$(basename $FILE) &>/dev/null	#if we fail we remove the file
			rm $TMPDIR/$(basename $FILE)".asc" &>/dev/null
			echo "unable to download $(basename $FILE).asc: file discarded" >> $TMPLOG
			kill $(ps aux | grep -m1 "passivepopup" | awk '{printf $2"\n"}') &>/dev/null
			continue
		}
	}
	WGETPATCHES="$WGETPATCHES $(basename $FILE)"	#if everything goes right we add the file to the upgrade list
	kill $(ps aux | grep -m1 "passivepopup" | awk '{printf $2"\n"}') &>/dev/null
done

#echo $WGETPATCHES

#dangerous? it leaves temp files all around...
#[ -z "$WGETPATCHES" ] && [ -z "$PENDINGPATCHES" ] && { echo "$0 ABORT: unable to download patches"; \
#	exit 0; }

#if we want to check the md5 it is time to do it!
MD5PATCHES=""
[ $CHECKMD5 -eq 1 ] && {
	for FILE in $WGETPATCHES; do
		echo "$MD5SUM $TMPDIR/$FILE" >> $TMPLOG
		SUM=$($MD5SUM $TMPDIR/$FILE)
		STRING=$(grep $SUM $MD5LIST | cut -f 3 -d /)	#if we match a checksum look if it is related to the right file!
		[ $STRING==$FILE ] && MD5PATCHES="$MD5PATCHES $FILE" \
		|| {
			rm $TMPDIR/$FILE 2> /dev/null	#if the file fails the checksum we remove it
			rm $TMPDIR/$FILE".asc" 2>/dev/null
			echo "$(basename $FILE) didn't pass the md5sum: file discarded" >> $TMPLOG
		}
	done
} || {	#if we don't want to do any check
MD5PATCHES="$WGETPATCHES"
}

#echo $MD5PATCHES

#[ -z "$MD5PATCHES" ] && [ -z "$PENDINGPATCHES" ] && { echo "$0 ABORT: no patch passed the md5 check"; \
#	exit 0; }

#if we want to check gpg key
[ $CHECKGPG -eq 1 ] && {
	for FILE in $MD5PATCHES; do
		echo "$GPG --verify $TMPDIR/$FILE.asc $TMPDIR/$FILE" >> $TMPLOG
		$GPG --verify $TMPDIR/$FILE".asc" $TMPDIR/$FILE 1>/dev/null
		[ ! $? -eq 0 ] && {
			rm $TMPDIR/$FILE 2> /dev/null	#if the file fails the gpg check we remove it
			rm $TMPDIR/$FILE".asc" 2>/dev/null
			echo "$(basename $FILE) didn't pass the gpg check: file discarded" >> $TMPLOG
		} || {
			GPGPATCHES="$GPGPATCHES $FILE"	#esle we add the file to the upgrade list
		}
	done
} || {	#else we skip the gpg signature check
	GPGPATCHES="$MD5PATCHES"
}

#move checed file into patches local repository
mv $TMPDIR/*.tgz* .
#if and overridden version was present in the local mirror, we remove it! (we use the OVERRIDDENPATCHES variable)
RemoveOverridden

#append pending patches (they have been checked in a previous session)
GPGPATCHES="$GPGPATCHES $PENDINGPATCHES"

[ -z "$GPGPATCHES" ] || $UPGRADEPKG $UPOPTS $GPGPATCHES >> $TMPLOG

#show report
[ ! $NOTIFY = "GNOME" ] && $DIALOGBASE --title "$TITLE" --textbox "$TMPLOG" $SIZE3 || \
$DIALOGBASE --title "$TITLE" --text-info --filename="$TMPLOG" --width=$SIZE3 --height=$SIZE3A
rm $TMPLOG

# update info about last check
mv $NEWLIST $OLDLIST 2>/dev/null