#!/bin/bash

# Copyright Jean-Philippe Guillemin <jp.guillemin@free.fr>. This program is free software; you can redistribute
# it and/or modify it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at your option)
# any later version. Please take a look at http://www.gnu.org/copyleft/gpl.htm
#
# Netpkg is a tool for easily install or upgrade packages via the network. With Netpkg,
# you can make a minimal installation of Zenwalk Linux and install/upgrade just the
# packages you need most.
#
#


version="7.0"
zenwalk_version="$(cat /etc/zenwalk-version)"

# Globals #####################################
export LANG=en_US
export configfile="/etc/netpkg.conf"
export PATH="/usr/libexec:/sbin:/bin:/usr/sbin:/usr/bin"

. /etc/shell-colors



# Parsing config files ######################################

netpkgdir=$(sed -n 's/^[ \t]*Netpkg_dir[ \t]*=[ \t]*\(.*\)$/\1/p' $configfile)
export netpkgdir="${netpkgdir:=/var/netpkg}"

# create the netpkgdir directory 
mkdir -p $netpkgdir 2>/dev/null

# Check list of sources from xnetpkg and netpkg.conf
# if [ -e $netpkgdir/sources ] ; then 
# 	for i in $( cat -v /var/netpkg/sources | sed -e 's|^..\(.\).*\(http://[^\r]*\)$|\2 |g' | grep "http" ) ; do 
# 		sources_list="$sources_list $(echo -n $i)"
# 	done
# else
sources_list=$(sed -n 's/^[ \t]*Internet_source[ \t]*=[ \t]*\(.*\)$/\1/p' $configfile)
# fi
export sources_list

local=$(sed -n 's/^[ \t]*Local_repository[ \t]*=[ \t]*\(.*\)$/\1/p' $configfile)
export local="${local:=/var/packages}"

packagelogs=$(sed -n 's/^[ \t]*Package_logs[ \t]*=[ \t]*\(.*\)$/\1/p' $configfile)
export packagelogs="${packagelogs:=/var/log/packages}"

blacklist="$(sed -n 's/^[ \t]*Black_list[ \t]*=[ \t]*\(.*\)$/\1/p' $configfile)"
export blacklist="${blacklist:=aaa_base}"

keepit=$(sed -n 's/^[ \t]*Keep_packages[ \t]*=[ \t]*\(.*\)$/\1/p' $configfile)
export keepit="${keepit:=yes}"

untouchable=$(sed -n 's/^[ \t]*Protected_files[ \t]*=[ \t]*\(.*\)$/\1/p' $configfile)
export untouchable="${untouchable:=/etc/lilo.conf /boot/grub/grub.cfg /etc/fstab}"

dependencies=$(sed -n 's/^[ \t]*Handle_dependencies[ \t]*=[ \t]*\(.*\)$/\1/p' $configfile)
export dependencies="${dependencies:=yes}"

export http_proxy=$(sed -n 's/^[ \t]*Proxy_Socket[ \t]*=[ \t]*\(.*\)$/\1/p' $configfile)
export proxyusr=$(sed -n 's/^[ \t]*Proxy_User[ \t]*=[ \t]*\(.*\)$/\1/p' $configfile)
export proxypwd=$(sed -n 's/^[ \t]*Proxy_Password[ \t]*=[ \t]*\(.*\)$/\1/p' $configfile)
export WGET="wget"
[ "$proxyusr" ] && export WGET="wget --proxy-user=${proxyusr} --proxy-password=${proxypwd}"

logfile=$(sed -n 's/^[ \t]*Logfile[ \t]*=[ \t]*\(.*\)$/\1/p' $configfile)
if [ "$logfile" == "none" ]; then
	export logfile="/dev/null"
else
	export logfile="${logfile:=/var/log/netpkg.log}"
fi

mill[0]="|" ; mill[16]="/" ; mill[32]="-" ; mill[48]="\\"

# fetch the packages list for available packages
getremotepkglist(){
	cat $netpkgdir/mainlist | sort | sed -e 's/^[^|]* *| *\([^|]*.t[glx]z\) *| .*$/\1/'
}

# fetch the packages list for available packages
getremotepkglistbycat(){
	cat $netpkgdir/pkglistfile | sort | sed -n "s/^\($1\) \(.*.t[glx]z\)$/\2/p"
}

# fetch the packages list for package named $1
findpackagebyname(){
	cut -d " " -f2 $netpkgdir/pkglistfile | sed -n "s/^\($1-[^\-]*-[^\-]*-[^\-]*\.t[glx]z\)$/\1/p" 
}

# Get the category for package $1
findcategorybypackage(){
	sed -n "s/^\([^ \t]*\)[ \t]*$1[ \t]*$/\1/p" $netpkgdir/pkglistfile
}

# Build a list of installed packages
buildlocalpkglist(){
	rm -f $netpkgdir/localpkglist
	for meta in $(ls $packagelogs) ; do 
		# package="$(sed -n 's/^[ \t]*PACKAGE LOCATION:[ \t]*\(.*\)[ \t]*$/\1/p' $packagelogs/$meta)"
		# echo ${package##*/} >> $netpkgdir/localpkglist
		echo $meta.txz >> $netpkgdir/localpkglist
	done
}

# The main list <available> | <installed>
buildmainlist(){
	rm -f $netpkgdir/mainlist
	listbuilder -a $netpkgdir/pkglistfile -i $netpkgdir/localpkglist | sort > $netpkgdir/mainlist
	# selector="$(cat $netpkgdir/last_selector)"
	selector="${selector:=a}"
	vfilter -${selector} -f $netpkgdir/mainlist > $netpkgdir/Ileftlist
}

# Download and process the meta file 
fetchrepository(){
	
	source="$(tail -n1 $netpkgdir/last_source)"
	echo "Cleaning cache"
	rm -f $netpkgdir/descfile
	rm -f $netpkgdir/pkglistfile
	rm -f $netpkgdir/PACKAGES.TXT*
	
	echo -e "Connecting to $source..."	
	
	neterror=$($WGET --no-check-certificate -O $netpkgdir/PACKAGES.TXT.gz $source/PACKAGES.TXT.gz 2>&1 | grep -E "failed:|Not Found")
	if [ "$neterror" ] ; then
		neterror=$($WGET --no-check-certificate -O $netpkgdir/PACKAGES.TXT $source/PACKAGES.TXT 2>&1 | grep -E "failed:|Not Found")
		if [ "$neterror" ] ; then
			echo "Unable to connect to $source, please check the network or choose another source" 
			return 1
		fi
	else
		echo "Uncompressing meta information"
		if ! gunzip -f $netpkgdir/PACKAGES.TXT.gz 2>/dev/null ; then 
			echo "Unable to extract meta information, please check the network or choose another source"
			return 1
		fi
	fi
	# cleaning PACKAGE SOURCE: lines
	sed -i '/^PACKAGE MIRROR:.*/d' $netpkgdir/PACKAGES.TXT
	
	echo "Computing packages dependencies"
	if [ "$dependencies" = "yes" ] ; then 
		sed -n '
		/^PACKAGE NAME:.*/{
		N;N;N;N
		s/,/ /g
		s/^PACKAGE NAME:[ \t]*\(.*\)-[^-]*-[^-]*-[^-]*\.t[glx]z[ \t]*\n.*\nPACKAGE SIZE (compressed):[ \t]*\(.*\)\nPACKAGE SIZE (uncompressed):[ \t]*\(.*\)\nPACKAGE REQUIRED:[ \t]*\(.*\)/\1:\4/p
		}' \
		$netpkgdir/PACKAGES.TXT > $netpkgdir/depfile
	fi

		
	#echo "Computing packages descriptions"
	#sed -n '
	#/^PACKAGE NAME:.*/{
	#N;N;N;N;N;N;N;N
	#s/^PACKAGE NAME:[ \t]*\(.*\)-[^-]*-[^-]*-[^-]*\.t[glx]z[ \t]*\n.*\nPACKAGE SIZE (compressed):[ \t]*\(.*\)\nPACKAGE SIZE (uncompressed):[ \t]*\(.*\)\nPACKAGE REQUIRED:[ \t]*\(.*\)\n.*\n.*\n.*\n[^ \t]*:[ \t]*\(.*\)/\1: Description :	\5\n\1: Compressed :	\2\n\1: Uncompressed :	\3\n\1: Dependencies :	\4/p
	#}' $netpkgdir/PACKAGES.TXT > $netpkgdir/descfile 
		
		
	echo "Creating packages list"
	sed -n '/^PACKAGE NAME:.*/{ N; s/^PACKAGE NAME:[ \t]*\(.*\.t[glx]z\)[ \t]*\nPACKAGE LOCATION:.*\/\([a-zA-Z0-9]*\)$/\2 \1/p }' \
		$netpkgdir/PACKAGES.TXT > $netpkgdir/pkglistfile
		
		
	echo "Getting local packages list"
	buildlocalpkglist		


	echo "Computing packages status"
	buildmainlist
		
	# Generating a report
	echo -e "Synchronization successful ${BOLDRED} ;-) ${COLOR_RESET}"
	echo ""
}


# take a look at local packages list to see which version of the $1 package installed
isremoteinstalled(){
	sed -n "s/^\($1-[^\-]*-[^\-]*-[^\-]*\.t[glx]z\)$/\1/p" $netpkgdir/localpkglist
}


# Download ($category $package) 
download(){
		
	source="$(tail -n1 $netpkgdir/last_source)"
	
	[ "$(echo $package | egrep ".*\.tlz$")" ] && ZIP="lzma"
	[ "$(echo $package | egrep ".*\.txz$")" ] && ZIP="lzma"	
	[ "$(echo $package | egrep ".*\.tgz$")" ] && ZIP="gzip"
	
	if [[ -e $local/$1/$2 && ! "$($ZIP -tv $local/$1/$2 2>&1 | egrep -e "corrupt|invalid")" ]]; then
		echo -e "${BOLDWHITE}Nothing to do, $2 is already in local cache ${COLOR_RESET}"	
		return
	else
		echo -e "${BOLDWHITE}Downloading $2 ${COLOR_RESET}"	
		
		mkdir -p $local/$1 2>/dev/null
		rm -f $local/$1/$2 2>/dev/null	 
		
		# we need to get an encoded URL if any
		# url=$($WGET -O- -q $source/$1/ \
		#| grep ".*\.t[glx]z<\/[a|A]>" \
		#| grep "$2" \
		#| sed -e "s/^.*<\(a\|A\) \(href\|HREF\)=\"\(.*\.t[glx]z\)\">.*/\3/")
	
		url="${source}/${1}/${2}"
	
		# check if we've got an absolute URL :(
		if [ $( echo "$url" | egrep -e "ftp:.*|http:.*|https:.*" ) ]; then
			$WGET -c --no-check-certificate -O $local/$1/$2 $url 
		else
			$WGET -c --no-check-certificate -O $local/$1/$2 $source/$1/$url 
		fi
	fi
	
	
}


# Checks for configuration files to update.
checkdotnew(){
	actionlist="differences yes no remove"
	echo "Checking for configuration files to update..."
	dotnewlist="$(find /etc -name "*.new")"
	if [ "$dotnewlist" ] ; then 
		for file in $dotnewlist ; do
		origfile="$(echo $file|sed -e 's/.new//')"
		[ "$(echo $untouchable | grep $origfile)" ] && continue
		echo "Should we move $file to $origfile ?"
		select action in $actionlist ; do
			case $action in
			differences)
				if [ -e $origfile ] ; then
				diff -dU 1 $origfile $file | most
				else
				echo "$file is the only one, no $origfile yet"
				fi 
				;;
			yes)
				cp -f $file $origfile
				rm -f $file
				break
				;;
			 no)
				break
				;;
			 remove)
				rm -f $file
				break
				;;
			esac
		done
		done
	else
	echo "No \".new\" configuration files on the system"
	fi
}


# Choose a download location from sources available in config file
choosesource(){
	source="$(tail -n1 $netpkgdir/last_source 2>/dev/null)" 
	echo -e "Current source is : ${BOLDWHITE}$source ${COLOR_RESET}"
	if [ "$sources_list" ] ; then
		echo "Please choose a source :"
		select newsource in $sources_list ;do 
			[ "$newsource" ] && source="$newsource"
			break
		done
		
		# Entry format checking
		if [ ! "$(echo $source | egrep 'http://|ftp://|https://')" ] ; then
		[ "$source" ] && echo -en "${BOLDWHITE}Bad syntax in url to source $source${COLOR_RESET}" 
		else
		mkdir -p $netpkgdir
		echo "$source" > $netpkgdir/last_source
		sourcehash="$(echo "$source" | md5sum | cut -d " " -f 1)"
		fi
	fi
	source="$(tail -n1 $netpkgdir/last_source 2>/dev/null)" 		

	echo -e "New source is : ${BOLDGREEN}$source ${COLOR_RESET}"
}


# prompt for action (install / upgrade / reinstall / download) for a list of packages ($1) #########################
promptaction(){

# this variable will track for packages installed as dependecies
processedlist=''

rm -f $netpkgdir/tmppkglist 2>/dev/null

if [[ "$*" ]] ; then
	for pattern in $* ; do
		sed -n "/$pattern/{p;q}" $netpkgdir/localpkglist >> $netpkgdir/tmppkglist
		getremotepkglist | grep -E $pattern >> $netpkgdir/tmppkglist
	done
else
	cat $netpkgdir/localpkglist >> $netpkgdir/tmppkglist
	getremotepkglist >> $netpkgdir/tmppkglist
fi

for package in $(cat $netpkgdir/tmppkglist) ; do
	
	# If we find the package in this list then it's already processed
	[ "$(echo "$processedlist" | grep "$package")" ] && continue

	# the software name
	softname=${package%-*}; softname=${softname%-*}; softname=${softname%-*} 

	# We need to find the category for $package
	category=$(findcategorybypackage $package)
	[[ "$category " == " " ]] && category="local"

	# take a look in the blacklist 
	if [ "$(echo $blacklist | grep "$softname ")" ]; then
		processedlist="${processedlist} $package"
		continue
	fi	

	# do we have this package installed in ANY version ?
	remoteinstalled="$(isremoteinstalled $softname)"
	
	allowed=""
	
	# do we have this package installed in the exact version ?
	if [ -e $packagelogs/${package%.*} ]; then
		if [ -n "$(echo "$filter" | grep 'I')" ]; then
			desc="$(sed -n "/$softname:\(.*\)/{p;q}" $packagelogs/${package%.*} )"
			[[ "$desc " == " " ]] && desc="installed"
			echo -en "${BOLDBLUE}[I][$category]${COLOR_RESET}"
			echo -n "$package"
			echo " ($desc)"	
			allowed="remove"
			[[ "$category" != "local" ]] && allowed="$allowed reinstall"
			processedlist="${processedlist} $package"
		else
			[[ "${mill[$pos]}" != "" ]] && printf "\e[31m%s\e[0m\b" "${mill[$pos]}" ; ((rotation++)) ; pos=$(( $rotation % 64 ))
		fi
	# so it's installed in another version
	elif [ "$remoteinstalled" ]; then
		
		if [ "$(vfilter -u -f $netpkgdir/mainlist -q $package)" ]; then
			if [ -n "$(echo "$filter" | grep 'U')" ]; then
				desc="$(sed -n "/$softname:\(.*\)/{p;q}" $netpkgdir/PACKAGES.TXT)"
				echo -en "${BOLDRED}[U][$category]${COLOR_RESET}"
				echo -n "$package"
				echo " ($remoteinstalled is installed)"
				allowed="install download remove"
				processedlist="${processedlist} $package"
			else
				[[ "${mill[$pos]}" != "" ]] && printf "\e[31m%s\e[0m\b" "${mill[$pos]}" ; ((rotation++)) ; pos=$(( $rotation % 64 ))
			fi				
		elif [ "$(vfilter -d -f $netpkgdir/mainlist -q $package)" ]; then
			if [ -n "$(echo "$filter" | grep 'D')" ]; then
				desc="$(sed -n "/$softname:\(.*\)/{p;q}" $netpkgdir/PACKAGES.TXT)"
				echo -en "${BOLDYELLOW}[D][$category]${COLOR_RESET}"
				echo -n "$package"
				echo " ($remoteinstalled is installed)"
				allowed="install download remove"	
				processedlist="${processedlist} $package"
			else
				[[ "${mill[$pos]}" != "" ]] && printf "\e[31m%s\e[0m\b" "${mill[$pos]}" ; ((rotation++)) ; pos=$(( $rotation % 64 ))
			fi							
		fi
			
	else
		if [ -n "$(echo "$filter" | grep 'N')" ]; then
			desc="$(sed -n "/$softname:\(.*\)/{p;q}" $netpkgdir/PACKAGES.TXT)"
			[[ "$desc " == " " ]] && desc="installed"
			echo -en "${BOLDCYAN}[N][$category]${COLOR_RESET}"
			echo -n "$package"
			echo " ($desc)"	
			allowed="install download"
			processedlist="${processedlist} $package"
		else
			[[ "${mill[$pos]}" != "" ]] && printf "\e[31m%s\e[0m\b" "${mill[$pos]}" ; ((rotation++)) ; pos=$(( $rotation % 64 ))
		fi	
	fi
	if [[ "$allowed " != " " ]] ; then
		actionlist="$allowed skip exit"
		echo " what should I do ?"
		select action in $actionlist ; do
			case $action in
				'install')
					PROMPT=1
					autoinstall $package
					PROMPT=0
					break
					;;
				'download')
					download $category $package
					break
					;;
				'remove')
					removepkg $package
					break
					;;
				'reinstall')
					autoinstall $package
					break
					;;
				'skip')
					echo "Skipping [$category] $package"
					echo
					break
					;;
				'exit')
					echo "Bye :)"
					echo
					exit
					
			esac
		done
	fi
done

}


# Check deps , then Install / Reinstall / Upgrade a list of packages
# The full and exact package name MUST be provided
autoinstall() {	

if [ "$*" ]; then 

	finallist='' 
	
	# We need an up to date list of installed packages
	buildlocalpkglist	
	
	for package in $* ; do
	
		# the software name
		softname=${package%-*}; softname=${softname%-*}; softname=${softname%-*} 
				
		# take a look in the blacklist 
		if [ "$(echo $blacklist | grep "$softname ")" ]; then
			continue
		fi	

		finallist="${finallist} $package"
		
		[ ! "$dependencies" = "yes" ] && continue

		deps="$(grep "^$softname:.*$" $netpkgdir/depfile | cut -s -d ":" -f 2-)"
		[ ! "$deps" ] && continue

		for dep in $deps ; do
		
			# We need to find package for $dep ($dep is the short name)
			deppackage="$(sed -n "s/^.*[ \t]\($dep-[^\-]*-[^\-]*-[^\-]*.t[glx]z\)[ \t]*$/\1/p" $netpkgdir/pkglistfile)"
			[ ! "$deppackage" ] && continue		
		
			# If it's already in the list, then skip	
			[ "$(echo $finallist | grep "$deppackage" )" ] && continue
 
			# Do we have it installed ? then skip
			[ -e $packagelogs/${deppackage%%.t[glx]z} ] && continue

			# Is it a downgrade ? then skip
			[ "$(vfilter -d -f $netpkgdir/mainlist -q $deppackage)" ] && continue		 

			# take a look in the blacklist 
			if [ "$(echo $blacklist | grep "$dep ")" ]; then
				continue
			fi	

			if [ "$PROMPT" = "1" ] ; then
				echo "$deppackage is required by $package : do you want to install this dependency package ?"
				select action in yes skip ; do
					case $action in
						yes)
							finallist="${finallist} $deppackage"
							break
							;;
						skip)
							break
					esac
				done
				continue			
			fi
			finallist="${finallist} $deppackage"
		done	 
	done

	for package in $finallist ; do

		# We need to find the category for $package
		category=$(findcategorybypackage $package)

		# the software name
		softname=${package%-*}; softname=${softname%-*}; softname=${softname%-*} 

		# take a look in pkgtool logs to see if we've got it installed
		remoteinstalled="$(isremoteinstalled $softname)"

		# download the package if needed
		download $category $package
		
		# Failed to download ?
		if [[ ! "$(cat $local/$category/$package)" || ! -e $local/$category/$package ]] ; then
			echo "[F] $local/$category/$package $(date)" >> $logfile
			echo "Failed to download $package, please checkout another source : skipping"
			continue
		fi
		
	[ "$(echo $package | egrep ".*\.tlz$")" ] && ZIP="lzma"
	[ "$(echo $package | egrep ".*\.txz$")" ] && ZIP="lzma"
	[ "$(echo $package | egrep ".*\.tgz$")" ] && ZIP="gzip"
	
		# check package integrity
		if [ "$($ZIP -tv $local/$category/$package 2>&1 | egrep -e "corrupt|invalid")" ]; then
			echo "$package is corrupted, please checkout another source : skipping"
			rm -f $local/$category/$package 2>/dev/null
			continue
		fi
		
		if [ -e $packagelogs/${package%.*} ]; then
			echo -n "Reinstalling"
			echo -e "${BOLDBLUE} [$category]$package${COLOR_RESET}"
			upgradepkg --reinstall $local/$category/$package 
			echo "[U] $local/$category/$package $(date)" >> $logfile
		elif [ "$(vfilter -u -f $netpkgdir/mainlist -q $package)" ]; then
			echo -n "Upgrading"
			echo -e "${BOLDRED} [$category]$package${COLOR_RESET}"
			upgradepkg $local/$category/$package
			echo "[U] $local/$category/$package $(date)" >> $logfile
		elif [ "$(vfilter -d -f $netpkgdir/mainlist -q $package)" ]; then
			echo -n "Downgrading"
			echo -e "${BOLDYELLOW} [$category]$package${COLOR_RESET}"
			upgradepkg $local/$category/$package	
			echo "[U] $local/$category/$package $(date)" >> $logfile	
		else
			echo -n "Installing"
			echo -e "${BOLDCYAN} [$category]$package${COLOR_RESET}"
			installpkg $local/$category/$package
			echo "[I] $local/$category/$package $(date)" >> $logfile
		fi
		
		# remove package if we don't want to keep it
		if [ ! "$keepit" = "yes" ]; then
			rm -f $local/$category/$package 2>/dev/null
		fi
		
		# We need an up to date list of installed packages
		buildlocalpkglist
		
	done
fi
}




# getall ###############################################
getall() {
	echo "Connecting to the packages repository..."
	echo
	for package in $(getremotepkglist) ; do

		if [ "$package" ]; then
		
			# We need to find the category for $package
			category=$(findcategorybypackage $package)
			
	
			if [[ ! "$( echo "$* " | grep "$category " )" && "$*" != "" ]] ; then
				[[ "${mill[$pos]}" != "" ]] && printf "\e[31m%s\e[0m\b" "${mill[$pos]}" ; ((rotation++)) ; pos=$(( $rotation % 64 ))
				continue
			fi		 
			
			download $category $package
			
		fi
	done


}


# upgrade the whole system ###############################################
updateall() {
	
echo "You're about to upgrade the whole system : are you sure ?"
select action in "yes" "abort" ; do
	case $action in
		yes)
			rm -f $netpkgdir/tmppkglist 2>/dev/null
			
			if [[ "$1" ]] ; then
				getremotepkglistbycat $1 >> $netpkgdir/tmppkglist
			else
				getremotepkglist >> $netpkgdir/tmppkglist
			fi
			
			echo "Connecting to the packages repository..."
			echo
			for package in $(cat $netpkgdir/tmppkglist) ; do

				if [ "$package" ]; then
					
					# We need to find the category for $package
					category=$(findcategorybypackage $package)				 

					# the software name
					softname=${package%-*}; softname=${softname%-*}; softname=${softname%-*} 
					# take a look in pkgtool logs to see if we've got it installed
					remoteinstalled="$(isremoteinstalled $softname)"
					
					if [ -e $packagelogs/${package%.*} ]; then
						echo "[$category]$package : already installed : skipping"
						continue
					
					elif [ -n "$remoteinstalled" ]; then
										
						# take a look in the blacklist 
						if [ "$(echo $blacklist | grep "$softname ")" ]; then
							[[ "${mill[$pos]}" != "" ]] && printf "\e[31m%s\e[0m\b" "${mill[$pos]}" ; ((rotation++)) ; pos=$(( $rotation % 64 ))
							continue
						fi						 
						
						if [ "$(vfilter -u -f $netpkgdir/mainlist -q $package)" ]; then 
						# If we reached this point then this package needs to be upgraded 
							echo -en "${BOLDWHITE}[$category]$package${COLOR_RESET}"
							echo " : $remoteinstalled is installed : upgrading"

							autoinstall $package
							
						fi
					else
						echo "[$category]$package : not installed : skipping"
					fi
				fi
			done
			
		break
		;;
	abort)
		exit 0
	esac
done


}


# list packages from repository #########################
listall() {
	
	processedlist=''
	
	rm -f $netpkgdir/tmppkglist 2>/dev/null
	
	if [[ "$1" == "local" ]] ; then
		cat $netpkgdir/localpkglist >> $netpkgdir/tmppkglist
	elif [[ "$1" ]] ; then
		getremotepkglistbycat $1 >> $netpkgdir/tmppkglist
	else
		cat $netpkgdir/localpkglist >> $netpkgdir/tmppkglist
		getremotepkglist >> $netpkgdir/tmppkglist
	fi
	
	for package in in $(cat $netpkgdir/tmppkglist) ; do
	
		# the software name
		softname=${package%-*}; softname=${softname%-*}; softname=${softname%-*} 
		
		# If we find the package in this list then it's already processed
		[ "$(echo "$processedlist" | grep "$package")" ] && continue
	
		# We need to find the category for $package
		category=$(findcategorybypackage $package)
		[[ ! "$category" ]] && category="local"

		# take a look in the blacklist 
		if [ "$(echo $blacklist | grep "$softname ")" ]; then
			if [ -n "$(echo "$filter" | grep 'I')" ]; then
				desc="blacklisted"
				echo -n "[X][$category]" 
				echo -n " $package"
				echo " $desc"
			else
				[[ "${mill[$pos]}" != "" ]] && printf "\e[31m%s\e[0m\b" "${mill[$pos]}" ; ((rotation++)) ; pos=$(( $rotation % 64 ))
			fi
			processedlist="${processedlist} $package"
			continue
		fi	

		# do we have this package installed in ANY version ?
		remoteinstalled="$(isremoteinstalled $softname)"
		
		# do we have this package installed in the exact version ?
		if [ -e $packagelogs/${package%.*} ]; then
			if [ -n "$(echo "$filter" | grep 'I')" ]; then
				desc="$(sed -n "/$softname:\(.*\)/{p;q}" $packagelogs/${package%.*} )"
				[[ "$desc " == " " ]] && desc="installed"
				echo -en "${BOLDBLUE}[I][$category]${COLOR_RESET}" 
				echo -en " $package"
				echo " $desc"
				processedlist="${processedlist} $package"		 
			else
				[[ "${mill[$pos]}" != "" ]] && printf "\e[31m%s\e[0m\b" "${mill[$pos]}" ; ((rotation++)) ; pos=$(( $rotation % 64 ))
			fi
		# so it's installed in another version
		elif [ -n "$remoteinstalled" ]; then
			if [ -n "$(echo "$filter" | grep 'U')" ]; then		
				if [ "$(vfilter -u -f $netpkgdir/mainlist -q $package)" ]; then
					desc="$(sed -n "/$softname:\(.*\)/{p;q}" $netpkgdir/PACKAGES.TXT)"
					echo -en "${BOLDRED}[U][$category]${COLOR_RESET}"
					echo -en " $package"
					echo " $desc"
					processedlist="${processedlist} $package"
				fi
			else
				[[ "${mill[$pos]}" != "" ]] && printf "\e[31m%s\e[0m\b" "${mill[$pos]}" ; ((rotation++)) ; pos=$(( $rotation % 64 ))
			fi
			if [ -n "$(echo "$filter" | grep 'D')" ]; then
				if [ "$(vfilter -d -f $netpkgdir/mainlist -q $package)" ]; then
					desc="$(sed -n "/$softname:\(.*\)/{p;q}" $netpkgdir/PACKAGES.TXT)"
					echo -en "${BOLDYELLOW}[D][$category]${COLOR_RESET}"
					echo -en " $package"
					echo " $desc"	
					processedlist="${processedlist} $package"		
				fi		
			else
				[[ "${mill[$pos]}" != "" ]] && printf "\e[31m%s\e[0m\b" "${mill[$pos]}" ; ((rotation++)) ; pos=$(( $rotation % 64 ))
			fi
		else
			if [ -n "$(echo "$filter" | grep 'N')" ]; then
				desc="$(sed -n "/$softname:\(.*\)/{p;q}" $netpkgdir/PACKAGES.TXT)"
				[[ "$desc " == " " ]] && desc="installed"
				echo -en "${BOLDCYAN}[N][$category]${COLOR_RESET}" 
				echo -en " $package"
				echo " $desc"	
				processedlist="${processedlist} $package"
				else
					[[ "${mill[$pos]}" != "" ]] && printf "\e[31m%s\e[0m\b" "${mill[$pos]}" ; ((rotation++)) ; pos=$(( $rotation % 64 ))
				fi
		fi
	done

}


# File protector function ######################################
protect() {
	# we backup all critical files as .old
	for protectedfile in $untouchable ; do
		[ -e $protectedfile ] && cp -f $protectedfile $protectedfile.old 2>/dev/null
	done
}

# File unprotector function 
unprotect() {
# delete backuped files in case it's the same OR no newer was added
for protectedfile in $untouchable ; do
	if [ -e $protectedfile ]; then
		newfile="$protectedfile"
		oldfile="$newfile.old"
		# clean up the redundant copy
		if [ "$(cat $oldfile 2>/dev/null | md5sum)" = "$(cat $newfile 2>/dev/null | md5sum)" ]; then
			rm $oldfile 2>/dev/null
		fi
	fi
	# Otherwise, we leave the .old copy for root to consider...
done

}

# Final cleanup ######################################
cleanup(){
	
	# We delete unchanged protected files or keep the old backuped one
	unprotect
	
	exit 0
}

# remove the netpkgdired files on any type of exit
trap 'cleanup' TERM INT EXIT

# main( :) #########################

# We always need an up to date list of installed packages
buildlocalpkglist

# Some fun :)
baneer() {
echo -en "${BOLDRED}"
echo "      _  __      __         __        ";
echo "     / |/ /___  / /_ ___   / /__ ___  ";
echo "    /    // -_)/ __// _ \ /  '_// _ \ ";
echo "   /_/|_/ \__/ \__// .__//_/\_\ \_, / ";
echo "                  /_/          /___/  ";
echo -e "${COLOR_RESET}"
}
# CLI howto ###############################################

usage() {

	echo -e "Commands are :"
	echo -e " ${BOLDWHITE}netpkg pattern1 [pattern2 ...]${COLOR_RESET} : Match pattern(s) and prompt for action"
	echo -e "    (actions can be : install, remove, reinstall, download)"	
	echo -e " ${BOLDWHITE}netpkg update|-u ${COLOR_RESET} : Prompt user for all \"updatable\" packages)"
	echo -e " ${BOLDWHITE}netpkg all|-a [category] ${COLOR_RESET} : list all packages in category (ie : xap)"
	echo -e "    (category specification is optional)"
	echo -e " ${BOLDWHITE}netpkg changes|-c [category] ${COLOR_RESET} : list all CHANGED packages"
	echo -e " ${BOLDWHITE}netpkg news|-n [category] ${COLOR_RESET} : list all NEW packages"
	echo -e " ${BOLDWHITE}netpkg local|-l [category] ${COLOR_RESET} : list all LOCAL packages"
	echo -e " ${BOLDWHITE}netpkg update-all|-uu [category] ${COLOR_RESET} : Update all packages without prompting"
	echo -e " ${BOLDWHITE}netpkg download-all ${COLOR_RESET} : Download all repository packages without prompting"

	echo
	echo -e "Setup commands :"			 
	echo -e " ${BOLDWHITE}netpkg addsource|rmsource \"URL\"${COLOR_RESET} : add or remove repository URLs from netpkg.conf"	
	echo -e " ${BOLDWHITE}netpkg dotnew${COLOR_RESET} : search for .new config files in the suystem and prompt for action"
	echo -en ${COLOR_RESET}
	echo
}

# Local options
if [ "$1" ]; then
	case "$1" in
		'--help' | '-help' | 'help')
			usage
			exit 1
			;;
		'source' | '-s')			
			choosesource
			fetchrepository
			export source="$(tail -n1 $netpkgdir/last_source 2>/dev/null)"
			exit 0
			;;
		'dotnew' | '-d')
			checkdotnew
			exit 1
			;;
		'addsource')
			if [ "$2" ] ; then
			echo "Internet_source = $2" >> $configfile
			echo "$2" > $netpkgdir/last_source
			[ ! -e $netpkgdir/pkglistfile ] && exit 1
			else
			echo "you forgot the URL..."
			fi	
			exit 0
			;;
		'rmsource')
			if [ "$2" ] ; then
			cp $configfile "${configfile}.old"
			grep -v "Internet_source = $2" $configfile > "${configfile}.tmp"
			mv "${configfile}.tmp" $configfile	2>/dev/null
			else
			echo "you forgot the URL..."
			fi
			exit 0
			;;
		'remove' | '-r')
			export dependencies="no"
			shift
			removepkg "$*"
			exit 0
	esac
else
	baneer
	echo -e "Netpkg $version running on Zenwalk $zenwalk_version"
	echo -e "Synopsys : ${BOLDWHITE}netpkg pattern [pattern2 ...]${COLOR_RESET}"
	echo -e "   match pattern(s) and prompt for install, remove, reinstall, download"
	exit 1
fi

# How old is the DB ?
mainlistage="0"
[ -e $netpkgdir/mainlist ] && mainlistage=$(stat -c %Z $netpkgdir/mainlist )

# Retrieve the last chosen source if any
if [ -e $netpkgdir/last_source ] ; then 
	export source="$(tail -n1 $netpkgdir/last_source 2>/dev/null)"
	
	if [ $(($(date +%s) - $mainlistage)) -ge 60 ] ; then
	
		echo -en "Current source is ${BOLDGREEN}$source ${COLOR_RESET}"	
		echo "Keep it ? (\"1\" for change, default keep)"
		echo -n "> "

		while read answer ; do
			case $answer in
			1|change)
				choosesource
				fetchrepository
				echo -n "New source is "
				echo -en "${BOLDGREEN}"
				echo $source
				echo -en "${COLOR_RESET}"	
				break
				;;
			*)
				if [ $(($(date +%s) - $mainlistage)) -ge 600 ] ; then
					fetchrepository
				fi
				break
			esac
		done
	fi
else
	choosesource
	fetchrepository
	export source="$(tail -n1 $netpkgdir/last_source 2>/dev/null)"
fi


	[ ! -e $netpkgdir/mainlist ] && exit 1
# Network options
if [ "$1" ]; then
	case "$1" in
		'updade-all' | '-uu')	
			shift
			filter='IUND'*
			protect
			updateall $*
			unprotect
			checkdotnew
			exit 0
			;;
		'download-all')
			shift
			filter='IUND' 
			getall
			exit 0
			;;
		'all' | '-a')
			shift
			filter='IUND' 
			listall $*
			exit 0
			;;
		'changes' | '-c')
			shift
			filter='UD' 
			listall $*
			exit 0
			;;
		'news' | '-n')
			shift
			filter='N' 
			listall $*
			exit 0
			;;
		'local' | '-l')
			shift
			filter='I' 
			listall $*
			exit 0
			;;
		'install' | '-i')
			shift
			export dependencies="no"
			filter='IUND' 
			protect
			promptaction $*
			unprotect
			exit 0
			;;
		'update' | '-u')
			shift
			filter='UD' 
			protect
			promptaction
			unprotect
			exit 0
			;;
		*)
			filter='IUND' 
			protect
			promptaction $*
			unprotect
			exit 0
		esac
else
	usage
	exit 1
fi

exit 0


