#!/bin/bash

# Script to handle menu profiles for CDD subsystem, installed by your system
# administrator via cdd-common package.
#
# this script should be put in ${HOME}./menu/cdd-menu and is executed by
# update-menus when run by user (not root)
#
# It prints on STDOUT Debian menu entries for user
#
# DO NOT REMOVE IT UNLESS YOU KNOW WHAT YOU ARE DOING

CONFBASE=${CONFBASE:-/etc/cdd}

# read generic CDD conf
. ${CONFBASE}/cdd.conf

CDDUSER=`whoami`

tasksdir=/usr/share/cdd/tasks

# it has to be run only by unprivileged users via update-menus
test "${CDDUSER}" == "root" && exit 0

# Upper case the first letter of a string to have a nicer menu
NameToUpper() {
	if [ $# -ne 1 ] ; then
		RET=64 # EX_USAGE
		return ${RET}
	fi
	echo $1 | perl -ne 'print "\u\L$_";'
	return 0
}

# Obtain title from HTML page for menu hints
GetHTMLTitle () {
        if [ $# -ne 1 ] ; then
                RET=64 # EX_USAGE
                return ${RET}
        fi
        perl -ne 'while (<>) {chomp; $all.="$_ ";}
                    ($title) = ($all =~ /.*\<title\>(.*)\<\/title\>.*/i);
                    $title =~ s/\s+/ /g ;
                    print $title ; exit 0;' $1
	return 0
}

# Obtain title (= first line) from text file for menu hints
GetTxtTitle () {
        if [ $# -ne 1 ] ; then
                RET=64 # EX_USAGE
                return ${RET}
        fi
	head -1 $1 | sed -e "s/[[:space:]]\+/ /g" -e "s/^[[:space:]]*\(.*\)[[:space:]]*$/\1/"
	return 0
}

# Strip CDD-name from meta package name
GetTaskNameFromPackage () {
        if [ $# -ne 2 ] ; then
                RET=64 # EX_USAGE
                return ${RET}
        fi
	CDD=$1  # CDD - name
	PKG=$2  # meta package name
	echo $PKG | sed "s/^$CDD-//"
	return 0
}

# Obtain task title which has to be defined in the meta package control templates
GetTaskTitle () {
        if [ $# -ne 1 ] ; then
                RET=64 # EX_USAGE
                return ${RET}
        fi
	PKG=$1  # meta package name
	cat "$tasksdir"/"$CDD"/`GetTaskNameFromPackage "$CDD" "$PKG"`
	return 0
}

getMenuEntriesFromDependencies() {
	RET=""
	if [ $# -ne 1 ] ; then
		RET=64 # EX_USAGE
		return ${RET}
	fi
	PKG="$CDD"-$1
	TASK=`GetTaskTitle $PKG`
	SECTION=`NameToUpper "$CDD"`/`NameToUpper "$TASK"`

	# find the list of Depends / Recommends / Suggests
	DepPkgs=`dpkg --status "$PKG" | \
		sed -e '/^Description/,$d' -e '/^Conffiles/,$d' | \
		grep -v ^[A-CE-QT-Z] | \
		grep -v ^S[eot] | \
		sed -e "s/([^)]*)//" \
		    -e "s/,* *${CDD}-common//" \
		    -e "s/^[^:]*: *//" \
		    -e "s/, */\\n/g" | \
		sort | uniq`

	# check whether CDD-maintainer provided menu override different from
	# package maintainers menu file
	# FIXME: This is outdated!  The concept of menu files named like the
        #        meta package is stopped in favour of single menu files named like
        #        the dependant package.  The rationale is that you can get more
        #        fine grained replacements.
	cddmenufile=""
	if   [ -s "$HOME"/.menu/"$PKG" ] ; then
		cddmenufile="$HOME"/.menu/"$PKG"
	elif [ -s /etc/cdd/"$CDD"/menu/"$PKG" ] ; then
		cddmenufile=/etc/cdd/"$CDD"/menu/"$PKG"
	elif [ -s /usr/lib/cdd/"$CDD"/menu/"$PKG" ] ; then
		cddmenufile=/usr/lib/cdd/"$CDD"/menu/"$PKG"
	elif [ -s /usr/share/cdd/"$CDD"/menu/"$PKG" ] ; then
		cddmenufile=/usr/share/cdd/"$CDD"/menu/"$PKG"
	fi

	for pkg in $DepPkgs ; do
	    # if CDD maintainer provided override just continue
	    [ ! -z "$cddmenufile" ] && grep -q -i "?package($pkg)" "$cddmenufile" && continue

	    # check for documentation text of CDD maintainer which should
	    # be prefered over package maintainers menu
	    docfile=""
	    if   [ -s /usr/share/doc/"$PKG"/"$pkg".html ] ; then
		docfile=/usr/share/doc/"$PKG"/"$pkg".html
	    elif [ -s /usr/share/doc/"$PKG"/"$pkg".txt ] ; then
		docfile=/usr/share/doc/"$PKG"/"$pkg".txt
	    elif [ -s /usr/share/doc/"$PKG"/"$pkg" ] ; then
		docfile=/usr/share/doc/"$PKG"/"$pkg"
	    fi
	    # if CDD maintainer provides documentation view this as menu entry ...
	    if [ ! -z "$docfile" -a -s "$docfile" ] ; then
		hint=""
		if file "$docfile" | grep -q HTML ; then
		    senspager=sensible-browser
		    hint=`GetHTMLTitle "$docfile"`
		else
		    senspager=sensible-pager
		    hint=`GetTxtTitle "$docfile"`
		fi
		if [ ! -z "$hint" ] ; then
		    hint="hints=\""$hint"\""
		fi
		cat <<EOT
?package($pkg): needs="text" \\
        section="$SECTION" \\
	title="`NameToUpper "$pkg"`" $hint \\
	command="$senspager $docfile"
EOT
	    fi

	    # search for a menu file with the following priority
	    # ${HOME}/.menu, /etc/menu, /usr/share/cdd/${CDD}/menu, /usr/share/menu, /usr/lib/menu
	    pkgmenufile=""
	    donotchange=1
	    if   [ -s "$HOME"/.menu/"$pkg" ] ; then
		pkgmenufile="$HOME"/.menu/"$pkg"
	    elif [ -s /etc/menu/"$pkg" ] ; then
		pkgmenufile=/etc/menu/"$pkg"
	    elif [ -s /usr/share/cdd/"$CDD"/menu/"$pkg" ] ; then
		pkgmenufile=/usr/share/cdd/"$CDD"/menu/"$pkg"
		donotchange=0
	    elif [ -s /usr/share/menu/"$pkg" ] ; then
		pkgmenufile=/usr/share/menu/"$pkg"
	    elif [ -s /usr/lib/menu/"$pkg" ] ; then
		pkgmenufile=/usr/lib/menu/"$pkg"
	    fi
            if [ ! -z "$pkgmenufile" ] ; then
		if [ $donotchange -eq 1 ] ; then
		    # the 2. and 3. -e - expression tries to fix missing '"' around the entries
		    sed -e "/^[[:space:]]*$/d" \
			-e 's?\([ :][^=^ ]*=\) *\([^"^=]*\)\( [^=]\+=\)?\1"\2"\3?g' \
			-e 's?\([ :][^=^ ]*=\) *\([^"^=]*\)\( [^=]\+=\)?\1"\2"\3?g' \
			-e 's?\( [^=]\+=\) *\([^"^=]\+[^"^\]\)$?\1"\2"?' \
			-e "s?\(section\)[[:space:]]*=[[:space:]]*\"*[^\"\\]*\"*?\1=\"$SECTION\"?" $pkgmenufile
		else
		    # strip possible comments
		    grep -v "^[[:space:]]*#" $pkgmenufile
		fi
	    fi
	    # HACK: Add blank line which helps in case of missing newlines
	    echo
	done
	
	[ -s "$cddmenufile" ] && cat "$cddmenufile"
}

ALLCDD=`getCDDList`
for CDD in ${ALLCDD}; do
	# read per CDD conf
	test -f  ${CONFBASE}/${CDD}/${CDD}.conf && \
		. ${CONFBASE}/${CDD}/${CDD}.conf

	if [ -d "$tasksdir"/"$CDD" ] ; then
		for PKG in `ls "$tasksdir"/"$CDD"` ; do
			getMenuEntriesFromDependencies "$PKG"
		done
	fi

#	# print on STDOUT menu generic entries if user belongs to CDD
#	checkUserInCDD ${CDD} ${CDDUSER} && \
#		test -d ${CONFBASE}/${CDD}/menu/ && \
#			find ${CONFBASE}/${CDD}/menu/ -maxdepth 1 -mindepth 1 -type f \
#				-exec cat {} \;
#
#	# and role specific menu entries
#	for ROLE in `getUserRoles ${CDD} ${CDDUSER}`; do
#		test -d ${CONFBASE}/${CDD}/menu/${ROLE} &&
#			find ${CONFBASE}/${CDD}/menu/${ROLE} -maxdepth 1 -mindepth 1 \
#				-type f -exec cat {} \;
#	done
done
