# -*- sh -*-

###
#
# This code is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Copyright 2002-2005 Mike Hearn (mike@plan99.net)
# Copyright 2002-2005 Hongli Lai (h.lai@chello.nl)
# Copyright 2003-2005 Curtis L Knight (knighcl@fastmail.fm)
#
###

export autopackage_version="1.2.6"

# setup XDG configuration variables scoped for autopackage
#
#   AUTOPACKAGE_CONFIG_HOME     User configuration directory
#   AUTOPACKAGE_CONFIG_DIRS     System configuration directories
#   AUTOPACKAGE_CONFIG_DIR      Determined system configuration directory for autopackage

if [ -z "$AUTOPACKAGE_CONFIG_HOME" ]; then
    export AUTOPACKAGE_CONFIG_HOME
    if [ -z "$XDG_CONFIG_HOME" ]; then
        AUTOPACKAGE_CONFIG_HOME="$HOME/.config"
    else
        AUTOPACKAGE_CONFIG_HOME="$XDG_CONFIG_HOME"
    fi
fi

if [ -z "$AUTOPACKAGE_CONFIG_DIRS" ]; then
    export AUTOPACKAGE_CONFIG_DIRS
    if [ -z "$XDG_CONFIG_DIRS" ]; then
        AUTOPACKAGE_CONFIG_DIRS="/etc/xdg"
    else
        AUTOPACKAGE_CONFIG_DIRS="$XDG_CONFIG_DIRS"
    fi
fi

if [ -z "$AUTOPACKAGE_CONFIG_DIR" ]; then
    export AUTOPACKAGE_CONFIG_DIR
    _AUTOPACKAGE_CONFIG_DIRS=$( echo "$AUTOPACKAGE_CONFIG_DIRS" | tr ':' ' ' )
    for _CONFIGURATION_DIR in $_AUTOPACKAGE_CONFIG_DIRS; do
        if [ -e "$_CONFIGURATION_DIR/autopackage/config" ]; then
            AUTOPACKAGE_CONFIG_DIR="$_CONFIGURATION_DIR"
            break
        fi
    done
    unset _AUTOPACKAGE_CONFIG_DIRS
fi

# set defaults that might not be loaded from system configurations
export autopackage_deny_user=false

# load system configurations
[ -e /etc/autopackage/config ] && source /etc/autopackage/config;
[ -e "$AUTOPACKAGE_CONFIG_DIR/autopackage/config" ] && source "$AUTOPACKAGE_CONFIG_DIR/autopackage/config";

# load user configuration if allowed from system configuration
if ! $autopackage_deny_user; then
    [ -e "$AUTOPACKAGE_CONFIG_HOME/autopackage/config" ] && source "$AUTOPACKAGE_CONFIG_HOME/autopackage/config";
fi

# setup XDG data and cache variables scoped for autopackage
#
#   AUTOPACKAGE_DATA_HOME       User data directory
#   AUTOPACKAGE_DATA_DIRS       System data directories
#   AUTOPACKAGE_DATA_DIR        Determined system data directory for autopackage
#   AUTOPACKAGE_CACHE_HOME      User cache directory

if [ -z "$AUTOPACKAGE_DATA_HOME" ]; then
    export AUTOPACKAGE_DATA_HOME
    if [ -z "$XDG_DATA_HOME" ]; then
        AUTOPACKAGE_DATA_HOME="$HOME/.local/share"
    else
        AUTOPACKAGE_DATA_HOME="$XDG_DATA_HOME"
    fi
fi

if [ -z "$AUTOPACKAGE_DATA_DIRS" ]; then
    export AUTOPACKAGE_DATA_DIRS
    if [ -z "$XDG_DATA_DIRS" ]; then
        AUTOPACKAGE_DATA_DIRS="/usr/local/share/:/usr/share/"
    else
        AUTOPACKAGE_DATA_DIRS="$XDG_DATA_DIRS"
    fi
fi

if [ -z "$AUTOPACKAGE_DATA_DIR" ]; then
    export AUTOPACKAGE_DATA_DIR
    _AUTOPACKAGE_DATA_DIRS=$( echo "$AUTOPACKAGE_DATA_DIRS" | tr ':' ' ' )
    for _DATA_DIR in $_AUTOPACKAGE_DATA_DIRS; do
        if [ -e "$_DATA_DIR/autopackage/apkg-funclib" ]; then
            AUTOPACKAGE_DATA_DIR="$_DATA_DIR"
            break
        fi
    done
    unset _AUTOPACKAGE_DATA_DIRS
fi

if [ -z "$AUTOPACKAGE_CACHE_HOME" ]; then
    if [ -z "$XDG_CACHE_HOME" ]; then
        AUTOPACKAGE_CACHE_HOME="$HOME/.cache"
    else
        AUTOPACKAGE_CACHE_HOME="$XDG_CACHE_HOME"
    fi
fi


export autopackage_prefix autopackage_share autopackage_global_db_location autopackage_user_db_location
export autopackage_update_linker_cache autopackage_update_manpath autopackage_deny_user
export autopackage_default_prefix autopackage_no_autosu autopackage_anonymous_reporting autopackage_wget_options
export DEBUGLEVEL EXECUTED_FROM_DIRECTORY WORKING_DIRECTORY _package_filename
export PREFIX _prefix _autopackage_support_install _autopackage_execute_package


# aliases for backwards compatibility.

# the variables here were mostly not documented or public,
# however, it's possible somebody may have used them accidentally
# as they weren't obviously private either. Rather than take the
# risk of breaking packages we just alias them to the old names.
#
# typically they are now public and documented as they were quite
# useful
if [[ "$AUTOPACKAGETARGET" == "1.0" ]]; then
    EXECUTED_FROM_DIRECTORY="$executed_from_directory"
    WORKING_DIRECTORY="$working_dir"
    _package_filename="$package_filename"
    [[ "$_meta_dir" == "" ]] && export _meta_dir="$meta_dir"
    [[ "$_payload_dir" == "" ]] && export _payload_dir="$payload_dir"
fi

# use by package prep and install scripts
if [[ "$_meta_dir" == "" ]]; then
    _meta_dir=`pwd`
fi
export apkg_logfile="$_meta_dir/log"
export apkg_filelist="$_meta_dir/filelist"
export apkg_uninstalldirs="$_meta_dir/uninstalldirs"

# this is public since 1.2
# logging framework depends on this variable - set before calling bashlib
if [ -z "$EXECUTED_FROM_DIRECTORY" ]; then
    EXECUTED_FROM_DIRECTORY=$( pwd )
fi

if [ -z "$TMP" ] || [ ! -d "$TMP" ]; then
    export TMP=/tmp
fi

if [ -z "$WORKING_DIRECTORY" ]; then
    # setup working space
    WORKING_DIRECTORY="${TMP}/autopackage.$RANDOM$$"
    if ! mkdir "$WORKING_DIRECTORY" 2>&-; then
        WORKING_DIRECTORY="$EXECUTED_FROM_DIRECTORY/autopackage.$RANDOM$$"
        if ! mkdir "$WORKING_DIRECTORY" 2>&-; then
            WORKING_DIRECTORY="/tmp/autopackage.$RANDOM$$"
            if ! mkdir "$WORKING_DIRECTORY" 2>&-; then
                red; echo -n "Error: "; normal; echo "Cannot create temporary directory ${TMP}/autopackage.$RANDOM$$ $EXECUTED_FROM_DIRECTORY/autopackage.$RANDOM$$ /tmp/autopackage.$RANDOM$$.";
                exit
            fi
        fi
    fi
    chmod -R 777 "$WORKING_DIRECTORY"
fi

if [[ "$autopackage_config_version" == "" ]] && [ -d "$autopackage_prefix/share/autopackage" ]; then
    echo "No configuration data found in /etc/autopackage/config or ~/.config/autopackage/config";
    exit 1;
fi

# if sideloading then directory will not exist and source files within this directory
oPWD_funclib=`pwd`
if [ -d "$autopackage_prefix/share/autopackage" ]; then
    cd "$autopackage_prefix/share/autopackage"
fi

source "apkg-bashlib"
source "apkg-db"
source "apkg-defs"
source "apkg-dep"
source "apkg-failsafelib"
source "apkg-io"
source "apkg-native"
source "apkg-script-utils"
cd "$oPWD_funclib"
unset oPWD_funclib

alias ls='ls --color=no --indicator-style=none'

# sanity action for removing possible system/user aliases
unalias cp 2>/dev/null
unalias mkdir 2>/dev/null
unalias mv 2>/dev/null
unalias rm 2>/dev/null
unalias rmdir 2>/dev/null

# if group and user are the same and are not
# system uids then allow group writeable files
if [[ "`id -gn`" == "`id -un`" ]] && [ `id -u` -gt 99 ]; then
    umask 002
else
    umask 022
fi


# first trace
trace funclib imports completed
trace funclib autopackage_version=$autopackage_version
trace funclib AUTOPACKAGETARGET=$AUTOPACKAGETARGET
trace funclib WORKING_DIRECTORY=$WORKING_DIRECTORY
trace funclib EXECUTED_FROM_DIRECTORY=$EXECUTED_FROM_DIRECTORY
trace funclib AUTOPACKAGE_CONFIG_HOME=$AUTOPACKAGE_CONFIG_HOME
trace funclib AUTOPACKAGE_CONFIG_DIRS=$AUTOPACKAGE_CONFIG_DIRS
trace funclib AUTOPACKAGE_CONFIG_DIR=$AUTOPACKAGE_CONFIG_DIR
trace funclib AUTOPACKAGE_DATA_HOME=$AUTOPACKAGE_DATA_HOME
trace funclib AUTOPACKAGE_DATA_DIRS=$AUTOPACKAGE_DATA_DIRS
trace funclib AUTOPACKAGE_DATA_DIR=$AUTOPACKAGE_DATA_DIR

# setup variable used specifically in reporting first time installs
# marker file is set in support code install script
if [ -f "$WORKING_DIRECTORY/apkg-support-install" ] && [ -z "$_autopackage_support_install" ]; then
    export _autopackage_support_install=1
    trace funclib converting marker file to first time installation variable _autopackage_support_install=$_autopackage_support_install
fi


##
# $EXECUTED_FROM_DIRECTORY
#
# The absolute path of the directory from which the autopackage was run. This is NOT
# necessarily the absolute path of the package itself, consider the case where a user
# runs, eg "/tmp/foo-1.0.x86.package" from their home directory.

##
# $WORKING_DIRECTORY
#
# The absolute path of the temporary directory from which the autopackage is using.
# The directory will contain all objects used during the installation session.
# Scripts should use this variable instead of $TMP as it is already setup as temporary.

##
# $CXX_ABI
#
# The current system's C++ ABI version. Can be one of these:
# 0 (unknown), 1 (GCC 3.2 ABI), 2 (GCC 3.4 ABI)


##
# _initializeAutopackage
#
# Function to initialize certain variables for use by Autopackage support code.
# This beginning logic order is necessary such that when autopackage is not installed
# that the variables can build up properly.
#
function _initializeAutopackage() {
    trace called

    if ! tty -s; then
        # If we don't have a terminal, redirect closed file descriptors
        # to /dev/null to prevent lockups with some programs.

        # __no_fd_close is used by the manager to override this check
        # as it can run funclib code with stdin redirected to /dev/null
        if [[ "$__no_fd_close" == "" ]]; then
            exec >/dev/null 2>/dev/null
        fi
    fi

    # add autopackage installation prefix to $PATH
    if [ -d "$autopackage_prefix/share/autopackage" ] && ! isInList "$autopackage_prefix/share/autopackage" "$PATH"; then
        # autopackage is cvs installed
        trace using cvs installed directories and modifying PATH
        export PATH=$autopackage_prefix/libexec/autopackage:$autopackage_prefix/share/autopackage:$autopackage_prefix/bin:$PATH
    elif [ -d "$autopackage_prefix/share" ] && ! isInList "$autopackage_prefix/share" "$PATH"; then
        # autopackage is not installed
        trace using cvs directories and modifying PATH
        export PATH=$autopackage_prefix/libexec:$autopackage_prefix/share:$autopackage_prefix/bin:$PATH
    fi
    trace "PATH=$PATH"

    # determine package installation prefix, if not passed in as an argument
    # mainly for cases where package meta data is used in prefix like $SHORTNAME
    # and redetermining prefix user changes to root through autosu
    trace _prefix=$_prefix
    if [[ "$_prefix" != "commandline" ]]; then
        PREFIX=`_userPrefix`
    fi

    trace "PREFIX=$PREFIX"

    # fix broken systems (Slackware, SUSE), where PATH does not contain KDE
    # or Gnome when `su`'d to root
    if ! isInList /opt/kde/bin "$PATH" && [ -d /opt/kde/bin ]; then
        export "PATH=$PATH:/opt/kde/bin"
        trace updated PATH to include /opt/kde/bin
    fi
    if ! isInList /opt/kde3/bin "$PATH" && [ -d /opt/kde3/bin ]; then
        export "PATH=$PATH:/opt/kde3/bin"
        trace updated PATH to include /opt/kde3/bin
    fi
    if ! isInList /opt/gnome/bin "$PATH" && [ -d /opt/gnome/bin ]; then
        export "PATH=$PATH:/opt/gnome/bin"
        trace updated PATH to include /opt/gnome/bin
    fi
    
    # gentoo has KDE installed into /usr/kde/<version>, figure out what
    # kde they're running, and add it to $PATH.
    #
    # this hack is probably a little less reliable than the above,
    # so leave them in just in case something weird is going on like /proc
    # isn't mounted, the user is using something other than kwin for their
    # WM, but are using KDE as their DE, etc.
    local kwin_exe=$( readlink "/proc/`ps ax|grep "[ ]kwin"|head -n1|awk -F' ' '{print $1}'`/exe" )
    if [[ "$kwin_exe" != "" ]]; then
        local kde_path=`dirname "$kwin_exe"`
        if ! isInList "$kde_path" "$PATH" && [ -d "$kde_path" ]; then
            export "PATH=$PATH:$kde_path"
            trace updated PATH to include $kde_path
        fi
    fi
    
    # determine package database location which could be either the
    # global db or user-specific DB in the home directory
    _initializePackageDB

    if [[ "${#_skel_dirs[@]}" == 0 ]]; then
        # Add directories from AUTOPACKAGE_SKELETON_DIRS environment variable
        if [[ "$AUTOPACKAGE_SKELETON_DIRS" != "" ]]; then
            local oIFS="$IFS"
            local IFS=$'\n'
            _skel_dirs=(`echo "$AUTOPACKAGE_SKELETON_DIRS" | tr ':' '\n'`)
            IFS="$oIFS"
        fi

        # Add spec dir
        if [[ "$_apspec_dir" != "" ]]; then
            trace "adding spec dir to skeleton path: $_apsec_dir/skeletons"
            _skel_dirs[${#_skel_dirs[@]}]="$_apspec_dir/skeletons"
        fi

        # Add standard skeleton dirs
        if [ -d "$autopackage_prefix/share/autopackage/skeletons" ]; then
            # autopackage is installed
            trace "adding global directory to skeleton path: $autopackage_prefix/share/autopackage/skeletons"
            _skel_dirs[${#_skel_dirs[@]}]="$autopackage_prefix/share/autopackage/skeletons"
        else
            # autopackage is not installed
            trace "adding uninstalled/CVS directory to skeleton path: $autopackage_prefix/share/skeletons"
            _skel_dirs[${#_skel_dirs[@]}]="$autopackage_prefix/share/skeletons"
        fi

        # Add database skeleton dirs for verify mode
        if [[ "$_context" == "verify" ]]; then
	    trace "context is verify, so adding db dirs to skeleton path"
            _skel_dirs[${#_skel_dirs[@]}]="$autopackage_user_db_location"
            _skel_dirs[${#_skel_dirs[@]}]="$autopackage_global_db_location"
        fi

    fi
    trace _skel_dirs=${_skel_dirs[@]}

    # get list of user languages
    if [[ "$language_list" == "" ]]; then
        export language_list="`getLanguages`"
    else
        trace language_list=$language_list
    fi

    # determine environment of destination machine
    if [[ "$AUTOPACKAGE_DISTRIBUTION_ID" == "" ]]; then
        _determineMachine
    else
        trace AUTOPACKAGE_DISTRIBUTION_ID=$AUTOPACKAGE_DISTRIBUTION_ID
    fi

    if [[ "$apkg_md5sum_command" == "" ]]; then
        locateCommand md5sum
        export apkg_md5sum_command="$lc_location"
    fi
    trace apkg_md5sum_command=$apkg_md5sum_command

    if [[ "$cpu_architecture" == "" ]]; then
        # arch command is not consistent, eg ia32.linux vs i686 so use uname
        locateCommand uname
        cpu_architecture=`"$lc_location" -m`

        case "$cpu_architecture" in
	    # We need to deal with amd64 much better than we currently do
	    # Right now treating it as x86 is correct for bi-arch distros
	    # like Fedora. But, it's not right for pure64 distros like
	    # Debian/Ubuntu or Gentoo

            i386 | i486 | i586 | i686 | x86_64 | athlon)
                export cpu_architecture="x86";;

        esac
    fi
    trace cpu_architecture=$cpu_architecture

# Check the system's C++ ABI.
# We deliberately check in /usr/lib by default because we want the *system*'s ABI,
# not whatever newer GCC the user might have installed manually.
# $CXX_ABI is set and exported to what we find. $1 is the path to search for
# and is available so that Gentoo's lack of any libstdc++.so in /usr/lib
# can be hacked around.
function _checkCxxLibs() {
    if [[ "$1" == "" ]]; then
        local checkpath="/usr/lib"
    else
        local checkpath="$1"
    fi

    if [[ "$AUTOPACKAGE_CXX_ABI" != "" ]]; then
         export CXX_ABI="$AUTOPACKAGE_CXX_ABI"
    elif [[ -f "$checkpath/libstdc++.so.8" ]]; then
         export CXX_ABI=4
    elif [[ -f "$checkpath/libstdc++.so.7" ]]; then
         export CXX_ABI=3
    elif [[ -f "$checkpath/libstdc++.so.6" && "`readlink -f /usr/lib/libstdc++.so.6`" != "/usr/lib/libstdc++.so.6.0.5.apkg" ]]; then
         export CXX_ABI=2
    elif [[ -f "$checkpath/libstdc++.so.5" ]]; then
         export CXX_ABI=1
    else
         export CXX_ABI=0
    fi
}

    # NB: a new libstdc++ version does not technically mean a different
    # compiler ABI, all it means is that the std c++ library broke backwards
    # compatibility. Unfortunately, due to the C++ template inlining bug,
    # we have to treat each new STL version as a separate ABI as otherwise
    # incompatible symbols could be mis-bound to each other.
    
    _checkCxxLibs
    if [[ "$CXX_ABI" == "0" ]]; then
        # this might be gentoo, who doesn't keep libstdc++.so in /usr/lib
        # Instead, gentoo keeps its different libstdc++.so's in
        # /usr/lib/gcc/<comp-str>/<comp-ver>/libstdc++.so.<ver>
        # the command gcc-config -c can give useful information, e.g.,:
        # i686-pc-linux-gnu-3.4.6, which means look in 
        # /usr/lib/gcc/i686-pc-linux-gnu/3.4.6.
        if locateCommand gcc-config -c; then
            trace "working around gentoo libstdc++ breakage"
            # this does seem to be gentoo
            local compver=$(echo $lc_output|awk -F '-' '{ print $NF }')
            # don't put anything here that might call locateCommand and reset $lc_output
            local compstr=$(echo $lc_output|sed "s/-$compver$//")
            _checkCxxLibs "/usr/lib/gcc/$compstr/$compver"
        fi
    fi

    trace CXX_ABI=$CXX_ABI

    # allow the launcher to override the anon reporting option
    if [[ "$_autopackage_stats_override" != "" ]]; then
        trace "launcher is overriding stats reporting to be $_autopackage_stats_override"
        export autopackage_anonymous_reporting="$_autopackage_stats_override"
    fi

    trace finished
    return 0
}


##
# _determineMachine
#
# Determine the state of the machine to which the installation is going to happen.
# The runtime state is added to package environment files.
#
# The distribution release text can be forced with $AUTOPACKAGE_DISTRIBUTION_TEXT
# to test this function and all distribution information can be forced in any case
# with $AUTOPACKAGE_LSB_VERSION, $AUTOPACKAGE_DISTRIBUTION_ID, $AUTOPACKAGE_DISTRIBUTION_RELEASE,
# $AUTOPACKAGE_DISTRIBUTION_CODENAME, $AUTOPACKAGE_DISTRIBUTION_DESCRIPTION.
#
function _determineMachine() {

	local LSB_VERSION DISTRIB_DISTRO DISTRIB_RELEASE DISTRIB_CODENAME DISTRIB_DESCRIPTION
	local release_text release_DISTRO release_RELEASE release_CODENAME release_DESCRIPTION
	local text_test

	# Always load lsb release file and do not overwrite environment variables if already present
	if [ -e "/etc/lsb-release" ]; then
		source /etc/lsb-release 2>/dev/null
		# allow force of lsb release file infomation
		# remove capitals and spaces from distribution id
		DISTRIB_ID=(`echo "$DISTRIB_ID" | tr '[:upper:]' '[:lower:]' | sed 's/ //g'`)
		if [ "$LSB_VERSION" ] && [[ "$AUTOPACKAGE_LSB_VERSION" == "" ]]; then export AUTOPACKAGE_LSB_VERSION="$LSB_VERSION"; fi;
		if [ "$DISTRIB_ID" ] && [[ "$AUTOPACKAGE_DISTRIBUTION_ID" == "" ]]; then export AUTOPACKAGE_DISTRIBUTION_ID="$DISTRIB_ID"; fi;
		if [ "$DISTRIB_RELEASE" ] && [[ "$AUTOPACKAGE_DISTRIBUTION_RELEASE" == "" ]]; then export AUTOPACKAGE_DISTRIBUTION_RELEASE="$DISTRIB_RELEASE"; fi;
		if [ "$DISTRIB_CODENAME" ] && [[ "$AUTOPACKAGE_DISTRIBUTION_CODENAME" == "" ]]; then export AUTOPACKAGE_DISTRIBUTION_CODENAME="$DISTRIB_CODENAME"; fi;
		if [ "$DISTRIB_DESCRIPTION" ] && [[ "$AUTOPACKAGE_DISTRIBUTION_DESCRIPTION" == "" ]]; then export AUTOPACKAGE_DISTRIBUTION_DESCRIPTION="$DISTRIB_DESCRIPTION"; fi;
	fi

	# Force distribution release text
	if [[ "$AUTOPACKAGE_DISTRIBUTION_TEXT" != "" ]]; then
		release_text="$AUTOPACKAGE_DISTRIBUTION_TEXT"

	# Look for generic release file
	elif [ -e "/etc/release" ]; then

		release_text=`<"/etc/release"`

	# Look for slackware release file
	elif [ -e "/etc/slackware-version" ]; then

		release_text=`<"/etc/slackware-version"`

	# Look for debian release file
	elif [ -e "/etc/debian_version" ]; then

		# Set Debian as distro
		release_DISTRO="debian"
		release_RELEASE=`<"/etc/debian_version"`
		release_DESCRIPTION="Debian"

	else

		local oIFS="$IFS"
		local IFS=$'\n'

		# Cycle through the release files found in /etc/
		for release_filename in `ls /etc/ | grep release | grep -v lsb-release`; do

			# Release files could be linked so the release filename must match release text
			if [ -r "/etc/$release_filename" ]; then
				release_text=`<"/etc/$release_filename"`
				# only get first line of release text
				release_text=`getLine "$release_text" 1`
				release_distro=`echo "$release_filename" | awk 'BEGIN {FS="-"} { print $1 }'`

				# compare as lower case text
				release_distro=(`echo "$release_distro" | tr '[:upper:]' '[:lower:]'`)
				release_filename=(`echo "$release_filename" | tr '[:upper:]' '[:lower:]' | sed 's/ //g'`)
				release_match=`echo "$release_text" | sed 's/ //g' | grep -i "$release_distro"`

				if [ "$release_match" ]; then
					release_DISTRO="$release_distro"
					break
				fi

			fi

		done

		IFS="$oIFS"

	fi

	# From the matched release file, make release text match variables in a lsb-release file
	if [ "$release_text" ]; then

		# check for ' Linux ' then ' release ' or use first argument as release_DISTRO
		text_test=`echo "$release_text" | grep --ignore-case ' Linux ' | sed 's/ linux / Linux /i' `
		if [[ "$text_test" != "" ]]; then
			text_test=`echo "$text_test" | awk 'BEGIN {FS=" Linux "} { print $1 }'`
			[[ "$release_DESCRIPTION" == "" ]] && release_DESCRIPTION="$text_test Linux"
			text_test=`echo "$text_test" | sed 's/ //g' | tr '[:upper:]' '[:lower:]'`
			[[ "$release_DISTRO" == "" ]] && release_DISTRO="$text_test"
		fi
		text_test=`echo "$release_text" | grep ' release '`
		if [[ "$text_test" != "" ]]; then
			text_test=`echo "$text_test" | awk 'BEGIN {FS=" release "} { print $1 }'`
			[[ "$release_DESCRIPTION" == "" ]] && release_DESCRIPTION="$text_test"
			text_test=`echo "$text_test" | sed 's/ //g' | tr '[:upper:]' '[:lower:]'`
			[[ "$release_DISTRO" == "" ]] && release_DISTRO="$text_test"
		fi
		text_test=`echo "$release_text" | awk 'BEGIN {FS=" "} { print $1 }'`
		if [[ "$text_test" != "" ]]; then
			[[ "$release_DESCRIPTION" == "" ]] && release_DESCRIPTION="$text_test"
			[[ "$release_DISTRO" == "" ]] && release_DISTRO=`echo "$text_test" | tr '[:upper:]' '[:lower:]'`
		fi

		# default: set $release_DESCRIPTION equal to $release_DISTRO
		if [[ "$release_DESCRIPTION" == "" ]]; then
			release_DESCRIPTION="$release_DISTRO"
		fi

		# reading from a fedora-release file sets the release_DISTRO correctly
		# fixup for forcing fedora core through AUTOPACKAGE_DISTRIBUTION_TEXT by the unit test
		# issue is fedora-release != "Fedora Core" like redhat-release == "Red Hat"
		if [[ "$release_DISTRO" == "fedoracore" ]]; then
			release_DISTRO="fedora"
		fi

		# check for release_RELEASE between the parenthesis and ' release ' then ' Linux ' then second argument
		text_test=`echo "$release_text" | grep ' ('`
		if [[ "$text_test" != "" ]]; then
			text_test=`echo "$text_test" | awk 'BEGIN {FS="("} { print $1 }'`
		fi
		text_test=`echo "$text_test" | grep ' release '`
		if [[ "$text_test" != "" ]]; then
			[[ "$release_RELEASE" == "" ]] && release_RELEASE=`echo "$text_test" | awk 'BEGIN {FS=" release "} { print $2 }' | sed 's/ //'`
		fi
		if [[ "$release_RELEASE" == "" ]]; then
			# Loop the release text to find first component to start with a number to make release_RELEASE
			for text in $release_text; do
				if [ `expr index "$text" '[0123456789]'` -eq "1" ]; then
					release_RELEASE="$text"
					break
				fi
			done
		fi

		# check for release_CODENAME between the parenthesis
		text_test=`echo "$release_text" | grep ' ('`
		if [[ "$text_test" != "" ]]; then
			text_test=`echo "$text_test" | awk 'BEGIN {FS="("} { print $2 }'`
			[[ "$release_CODENAME" == "" ]] && release_CODENAME=`echo "$text_test" | awk 'BEGIN {FS=")"} { print $1 }'`
		fi

	fi

	# allow force of release file infomation
	if [ -n "$release_DISTRO" ] && [ -z "$AUTOPACKAGE_DISTRIBUTION_ID" ]; then export AUTOPACKAGE_DISTRIBUTION_ID="$release_DISTRO"; fi;
	if [ -n "$release_RELEASE" ] && [ -z "$AUTOPACKAGE_DISTRIBUTION_RELEASE" ]; then export AUTOPACKAGE_DISTRIBUTION_RELEASE="$release_RELEASE"; fi;
	if [ -n "$release_CODENAME" ] && [ -z "$AUTOPACKAGE_DISTRIBUTION_CODENAME" ]; then export AUTOPACKAGE_DISTRIBUTION_CODENAME="$release_CODENAME"; fi;
	if [ -n "$release_DESCRIPTION" ] && [ -z "$AUTOPACKAGE_DISTRIBUTION_DESCRIPTION" ]; then export AUTOPACKAGE_DISTRIBUTION_DESCRIPTION="$release_DESCRIPTION"; fi;

	# Determine distribution depsolver and frontend
	_DISTRIBUTION_DEPSOLVERS="urpmi yum slapt-get swarte smart apt-get yast emerge"
	_DISTRIBUTION_FRONTEND="gurpmi aptitude synaptic adept wajig yast kpackage"

	for P in $_DISTRIBUTION_DEPSOLVERS; do
		locateCommand "$P" && _DISTRIBUTION_DEPSOLVER="$P" && break;
	done

	for P in $_DISTRIBUTION_FRONTEND; do
		locateCommand "$P" && _DISTRIBUTION_FRONTEND="$P" && break;
	done


	# Determine distribution manager
	if locateCommand "rpm" && rpm -q coreutils &> /dev/null; then
		_DISTRIBUTION_MANAGER="rpm";
	elif locateCommand "dpkg" && dpkg -s coreutils &> /dev/null; then
		_DISTRIBUTION_MANAGER="dpkg";
	elif [ -e "/var/db/pkg" ] && [ -e "/var/lib/portage/world" ] && locateCommand "emerge"; then
		_DISTRIBUTION_MANAGER="portage"
	elif locateCommand "pkgtool"; then
		_DISTRIBUTION_MANAGER="pkgtool"
	fi


	# AUTOPACKAGE_DISTRIBUTION_DEPSOLVER should always be present
	# AUTOPACKAGE_DISTRIBUTION_FRONTEND can be empty as the depsolver itself
	#     will be used by support code - current used in apkg-defs
	# AUTOPACKAGE_DISTRIBUTION_MANAGER will always be present

	# allow forcing of available applications by not setting AUTOPACKAGE_* environment variables
	if [ -n "$_DISTRIBUTION_DEPSOLVER" ] && [ -z "$AUTOPACKAGE_DISTRIBUTION_DEPSOLVER" ]; then
		export AUTOPACKAGE_DISTRIBUTION_DEPSOLVER="$_DISTRIBUTION_DEPSOLVER"
	fi
	if [ -n "$_DISTRIBUTION_FRONTEND" ] && [ -z "$AUTOPACKAGE_DISTRIBUTION_FRONTEND" ]; then
		export AUTOPACKAGE_DISTRIBUTION_FRONTEND="$_DISTRIBUTION_FRONTEND"
	fi
	if [ -n "$_DISTRIBUTION_MANAGER" ] && [ -z "$AUTOPACKAGE_DISTRIBUTION_MANAGER" ]; then
		export AUTOPACKAGE_DISTRIBUTION_MANAGER="$_DISTRIBUTION_MANAGER"
	fi

	trace AUTOPACKAGE_LSB_VERSION=\"$AUTOPACKAGE_LSB_VERSION\"
	trace AUTOPACKAGE_DISTRIBUTION_ID=\"$AUTOPACKAGE_DISTRIBUTION_ID\"
	trace AUTOPACKAGE_DISTRIBUTION_RELEASE=\"$AUTOPACKAGE_DISTRIBUTION_RELEASE\"
	trace AUTOPACKAGE_DISTRIBUTION_CODENAME=\"$AUTOPACKAGE_DISTRIBUTION_CODENAME\"
	trace AUTOPACKAGE_DISTRIBUTION_DESCRIPTION=\"$AUTOPACKAGE_DISTRIBUTION_DESCRIPTION\"
	trace AUTOPACKAGE_DISTRIBUTION_DEPSOLVER=\"$AUTOPACKAGE_DISTRIBUTION_DEPSOLVER\"
	trace AUTOPACKAGE_DISTRIBUTION_FRONTEND=\"$AUTOPACKAGE_DISTRIBUTION_FRONTEND\"
	trace AUTOPACKAGE_DISTRIBUTION_MANAGER=\"$AUTOPACKAGE_DISTRIBUTION_MANAGER\"

}


# will test the dependencies of package $1 and print the root names of the failed deps
function verifyPackage() {

    # since there is no action on the package, user can verify
    # a globally installed package - use _loadPackage instead of _resolveName
    if ! _loadPackage "$1"; then
        _packageReturnCode "1" "$1"
        return "$?"
    fi

    # execute the verifications script
    trace sourcing verification file \"$PACKAGELOCATION/verification\"
    if [ -f "$PACKAGELOCATION/verification" ]; then
        source "$PACKAGELOCATION/verification"
    else
        _packageReturnCode "4" "$1"
        return "$?"
    fi
}


##
# uninstallFromLog
#
# Process the uninstall log that was generated by the autopackage file installation functions.
# The contents of the log must be in the $log variable.
#
# Example:
# # This is part of an autopackage specfile
# [Install]
# copyFiles share/* "$PREFIX/share"
# installLib lib/*
#
# [Uninstall]
# uninstallFromLog
function uninstallFromLog() {
    trace log is:
    trace "$log"
    eval "$log"
    return 0
}

# return of 0 = uninstalled ok
# return of 1 = package not found/database corrupt
# return of 2 = completed with errors
# return of 3 = this package supports some others: listed in uninstall_result (unless $2 = force)
# return of 4 = this package is in the database but wasn't installed by autopackage
# return of 5 = this package was installed by root and you're not root, so piss off
# return of 6 = this package is in the user db, but you're running as root
function uninstallPackage() {
    trace called with $@

    # test to see if removing autopackage support code
    if [[ "$1" == "autopackage" ]]; then
        _outputUninstalling "autopackage" "autopackage" "autopackage"
        _removeAutopackage
        # no debug added to call because the log was just deleted by the previous removeAutopackage call
        _packageReturnCode "$?" --no-debug
        return "$?"
    fi

    # ensure we have the root name while _loadPackage checks all available package databases
    local name=`_resolveName "$1"`
    unset DISPLAYNAME SHORTNAME
    _loadPackage "$1"
    local r=$?

    # we might have failed to load package environment so check that there is data
    # for display and shortname and substitute in $1 otherwise
    [ -z "$DISPLAYNAME" ] && DISPLAYNAME="$1"
    [ -z "$SHORTNAME" ] && SHORTNAME="$1"
    _outputUninstalling "$DISPLAYNAME" "$SHORTNAME" "autopackage"

    if [ -z "$name" ] && (( r > 0 )); then
        warn "could not load $1"
        _outputUninstallFail $( out "$intl_PACKAGE_NOT_FOUND" "$1" )
        return 1
    fi
    trace $1 resolved to $name
    unset name

    # the name may have been resolved to a database we can't/shouldn't actually access.

    # firstly, if we are root, check that the package is
    # in the global database. it could be in the user db
    # if the user ran package using sudo, but we don't
    # want to touch the user db as the root user, otherwise
    # things get complicated.
    if [[ `id -u` == "0" ]] && [ -e "$autopackage_user_db_location/$ROOTNAME/environment.en" ]; then
        warn "we are root but package is installed as user"
        _outputUninstallFail "$intl_UNINSTALL_NO_SUDO"
        return 6
    fi

    # next, if we are not root and the package exists in the global db but not the user db, we can't proceed
    if [ -e "$autopackage_global_db_location/$ROOTNAME/environment.en" ] && [ ! -e "$autopackage_user_db_location/$ROOTNAME/environment.en" ] && [[ `id -u` != "0" ]]; then
        warn "we are not root and need to be"
        _outputUninstallFail "$intl_UNINSTALL_MUST_BE_ROOT"
        return 5
    fi

    # Check we don't support anything
    local root_name=`justRootName "$ROOTNAME"`
    if ! $force && ( [[ `echo x; cat "$autopackage_db_location/$root_name/supports" 2>/dev/null` != "x" ]] && [[ "$2" == "" ]] ); then
        local uninstall_result

        local oIFS="$IFS"
        IFS=$'\n'

        local uninstall_result
        while read; do
            local tmp=$( _loadPackage "$REPLY"; echo "$DISPLAYNAME ($SHORTNAME)"; )
            if [ -n "$tmp" ] && [ -z "$uninstall_result" ]; then
                uninstall_result="$tmp";
            elif [ -n "$tmp" ] && [ -n "$uninstall_result" ]; then
                uninstall_result="$uninstall_result, $tmp";
            fi
        done <"$autopackage_db_location/$root_name/supports"

        IFS="$oIFS"
        unset oIFS

        warn "we support something else: $uninstall_result"
        _outputUninstallFail `out "$intl_UNINSTALLING_WOULD_BREAK" "$uninstall_result"`
        return 6
    fi
    unset root_name

    trace checking for installation environment file
    if [ ! -e "$autopackage_db_location/$ROOTNAME/environment.en" ]; then
        warn "package not an autopackage"
        _outputUninstallFail "$intl_PACKAGE_NOT_AUTOPACKAGE"
        return 7
    fi

    # now get the script section
    trace retrieving uninstall scripts
    local script_uninstall=`<"$autopackage_db_location/$ROOTNAME/uninstall"`
    [[ "$script_uninstall" == "" ]] && local script_uninstall=`getSection "$autopackage_db_location/$ROOTNAME"/info Script-Uninstall`

    # log for use in eval "$script_uninstall" call to uninstallFromLog function
    local log=$(<"$autopackage_db_location/$ROOTNAME/log")

    # load package environment variables
    _loadPackageEnvironment "$autopackage_db_location/$ROOTNAME"

    # remove support entries from dependencies
    _unforgeDependencies "$ROOTNAME"

    trace evaluating script_uninstall
    trace "$script_uninstall"
    eval "$script_uninstall"

    # remove root database package directory and symlinks
    removeFile "$autopackage_db_location/$SHORTNAME"
    removeFile "$autopackage_db_location/$SHORTNAME-$SOFTWAREVERSION"
    rm -fr "$autopackage_db_location/$ROOTNAME"

    # check for deletion of package root directory
    if [ -e "$autopackage_db_location/$ROOTNAME" ]; then
        warn root directory deleted
        _outputUninstallFail "$intl_PACKAGE_NOT_AUTOPACKAGE"
        return 7
    else
        _outputUninstallDone
        return 0
    fi
}


##
# _packageReturnCode <RETURN-CODE> [MESSAGE]
# RETURN-CODE: returned exit code to evaluate and provide output.
# MESSAGE: text that would accompany the gettext (apkg-defs) output.
#
# $uninstall_result is set as text output from the uninstallPackage command to
# give an message to the user.
#
function _packageReturnCode() {

	local object="$2"

	[[ "$2" == "--no-debug" ]] && export DEBUGLEVEL=0 && object="autopackage"

	case "$1" in

		"0" )	# continuation status
			green
			out "$intl_DONE"
			normal
			;;

		"1" )	# continuation status
			red
			out "$intl_PACKAGE_NOT_FOUND" "$object"
			normal
			;;

		"2" )
			red
			out "$intl_FAILED"
			cyan
			out "$intl_ERRORS"
			normal
			out "$uninstall_result"
			;;

		"3" )
			red
			out "$intl_FAILED"
			normal
			out "$intl_UNINSTALLING_WOULD_BREAK"
			out "$uninstall_result"
			out
			out "$intl_UNINSTALL_DO_IT_ANYWAY"
			out
			;;

		"4" )	# continuation status
			red
			out "$intl_PACKAGE_NOT_AUTOPACKAGE"
			normal
			;;

		"5" )	# continuation status
			red
			out "$intl_UNINSTALL_MUST_BE_ROOT"
			normal
			;;

		"6" )	# continuation status
			red
			out "$intl_UNINSTALL_NO_SUDO"
			normal
			;;

		"7" )
			red
			outn "$intl_FAIL"
			normal
			out "$intl_PACKAGE_SPECIFY"
			;;

		"10" )
			red
			outn "$intl_FAIL"
			normal
			out "$intl_FILE_NOT_READABLE" "$object"
			;;

		"12" )
			out "$intl_INSTALL_SUCCESS" "$object"
			;;

		"13" )
			red
			outn "$intl_FAIL"
			normal
			out "$intl_INSTALL_ERROR" "$object"
			;;

                "14" )
                        red
                        outn "$intl_FAIL"
                        normal
	                out "$intl_CANNOT_EXECUTE_PACKAGE_DIRECTLY"
                        ;;

		"15" )
			red
			outn "$intl_FAIL"
			normal
			out "$intl_PACKAGE_UNKNOWN_COMMAND" "$object"
			;;

		* )
			assertNotReached
			;;

	esac
	return "$1"
}


function checkConfigVersion() {
    if [[ "$autopackage_config_version" != "1" ]]; then
	red; outn "$intl_FAIL"; normal;
	out "$intl_BAD_CONFIG_VERSION";
	return 1;
    fi
    return 0;
}

# variable that holds all the package specfile keys that are available
specKeys="AUTOPACKAGETARGET \
	COMPRESSION \
	CPUARCHITECTURES \
	DISPLAYNAME \
	EULAFILENAME \
	EULADISPLAY \
	INTERFACEVERSION \
	LICENSE \
	MAINTAINER \
	PACKAGEDESKTOP \
	PACKAGEFILENAME \
	PACKAGER \
	PACKAGEREPORTING \
	PACKAGEVERSION \
	REPOSITORY \
	REPOSITORYFILENAME \
	ROOTINSTALLONLY \
	ROOTNAME \
	SHORTNAME \
	SOFTWAREVERSION \
	SUMMARY \
	URL \
"

# variable that holds all the package specfile keys that can be localized
intlKeys="DISPLAYNAME \
	EULAFILENAME \
	SUMMARY \
"

# variable that holds all the package build keys that are available
buildKeys="BUILDHOST \
	EXPANDSIZE \
	FILETOTAL \
	PACKAGELANGUAGES \
	TIMESTAMPBUILD \
	_PLATFORM \
"

# variable that holds all the package installation keys that are available
installKeys="BACKUP \
	DATABASE \
	PREFIX \
	TIMESTAMPINSTALL \
"


function _resetKeys() {

	local key keys

	keys="$specKeys $buildKeys $installKeys PACKAGELOCATION"

	oIFS="$IFS"
	IFS=$' \t\n'

	for k in $keys; do
		unset $k
	done

	IFS="$oIFS"
	return 0

}


##
# _installAutopackage
#
# Installs autopackage support tools within downloader.
## START INSTALLAUTOPACKAGE
## Function is substituted from apkg-funclib.
function _installAutopackage() {

	local retval
	local oldpath="$PATH"

	_autosuCommand -m apkg-install autopackage/install --silent
	retval="$?"

	# remove expanded autopackage support code package
	rm -fr "autopackage"

	if [[ "$retval" != "0" ]] && [[ "$retval" != "5" ]]; then
		_finishWindow
		return "$retval"
	fi

	# load installed autopackage support code
	[ -e /etc/autopackage/config ] && source /etc/autopackage/config;
	[ -e "${XDG_CONFIG_HOME:-$HOME/.config}/autopackage/config" ] && source "${XDG_CONFIG_HOME:-$HOME/.config}/autopackage/config";

	if [[ "$autopackage_prefix" == "" ]]; then
		out
		red
		out "$intl_SETUP_CANT_FIND_CONFIG"
		normal
		out
		_finishWindow
		return 1
	fi
	source "$autopackage_prefix/share/autopackage/apkg-funclib"

	# return value of 5 is a failed gtkfe installation
	out
	out "# # # # # # # # # # # #"
	out
	out "Autopackage support code was installed."
	if [[ "$retval" == "5" ]]; then
		out "Autopackage graphical interface installation was skipped."
	else
		out "Autopackage graphical interface was installed."
	fi
	out
	out "# # # # # # # # # # # #"
	out

	out "$intl_SETUP_THANKYOU"
	out
	out "# # # # # # # # # # # #"
	out

	# we do this here so it appears after the packages have been installed on first run
	if ! isInList "$autopackage_prefix/bin" "$oldpath"; then
		updateEnv PATH "$autopackage_prefix/bin"
		out "$intl_SETUP_RUN_EXEC_BASH"
		out
		out "# # # # # # # # # # # #"
		out
	fi

	_finishWindow
	return 0

}
## END INSTALLAUTOPACKAGE


##
# _removeAutopackage
#
# Determines how autopackage support code is installed and removes support code.
function _removeAutopackage() {

	trace called
	local r1 r2
	local rpm_removed=false

	if [[ `id -u` == "0" ]] && [[ "$AUTOPACKAGE_DISTRIBUTION_MANAGER" == "rpm" ]]; then

		for p in autopackage-devel autopackage; do

			# check for installed rpm
			"$lc_location" -q --quiet "$p"
			r1="$?"
			# proceed with removal if found
			if [[ "$r1" == "0" ]]; then
				trace removing $p rpm
				rpm -e --quiet "$p"
				r2="$?"
				# if not successful removal then create error text and fail
				if [[ "$r2" != "0" ]]; then
					uninstall_result="$p rpm was not removed. Please remove it manually."
					return "2"
				fi
				rpm_removed=true
			fi

		done

		# if a rpm was removed then return, otherwise
		# other removal commands will execute
		if $rpm_removed; then
			return 0
		fi

	fi

	# test to see if support code is from a package
	if [ -O "$autopackage_prefix/share/autopackage/remove" ]; then
		trace executing "$autopackage_prefix/share/autopackage/remove" --silent
		"$autopackage_prefix/share/autopackage/remove" --silent;
		return "$?"

	# test to see if support code is from CVS
	elif [ -L "$autopackage_prefix/share/autopackage" ]; then
		locateCommand package
		apkg_main_dir=`ls -la "$lc_location"`
		apkg_main_dir=`echo  "$apkg_main_dir" | awk 'BEGIN { FS=" -> " } { print $2 }'`
		apkg_main_dir=`dirname "$apkg_main_dir"`
		[[ "$apkg_main_dir" == "." ]] && apkg_main_dir="$lc_location"
		if [ -e "$apkg_main_dir/unsetup" ]; then
			trace executing "$apkg_main_dir/unsetup" --silent
			"$apkg_main_dir/unsetup" --silent;
			return "$?"
		fi

	fi

	# autopackage must be installed since we exist, so it must not be available to
	# be removed - return code for _packageReturnCode function
	return 5

}


##
# _installGTKFE
#
# Determines if autopackage gtk front end application needs to be downloaded/upgraded/installed.
function _installGTKFE() {

    trace called

    local retval _runtime_mirrors

    # if manually called from install script
    if [[ "$EXECUTED_FROM_DIRECTORY" == "" ]]; then
        EXECUTED_FROM_DIRECTORY=`pwd`
        EXECUTED_FROM_DIRECTORY=`dirname "$EXECUTED_FROM_DIRECTORY"`
    fi

    if testForLib libgtk-x11-2.0.so && testForLib libglade-2.0.so; then

        ! "$autopackage_silent" && out "$intl_SETUP_YOU_HAVE_GTK";

        if locateCommand autopackage-launcher-gtk; then
            apkg_gtk_version=`"$lc_location" --version | awk 'BEGIN {FS=" version "} { print $2 }'`
        fi

        trace found GTKFE version $apkg_gtk_version but have $autopackage_version of autopackage
        if [[ "$apkg_gtk_version" != "$autopackage_version" ]] && [[ "$lc_location" != "" ]]; then
            trace removing GTKFE $apkg_gtk_version
            #AUTOPACKAGE_FRONTEND=apkg-ttyfe PATH="$PATH":~/.local/bin package remove autopackage-gtk
            # needs to be in subshell to protect the package environment
            (
            # send command to null as removal does ui which should not go to console but does anyway
            # encapsulation of the removal gui/tui would remove this requirement
            AUTOPACKAGE_FRONTEND=apkg-ttyfe uninstallPackage autopackage-gtk &> /dev/null; exit $?
            )
        fi

        if ! locateCommand "autopackage-launcher-gtk"; then
            _package_directory=$( dirname "$_package_filename" )
            # check in sealed installer packages directory
            if [ -e "$_meta_dir/packages/autopackage-gtk-$autopackage_version.package" ]; then
                filename="$_meta_dir/packages/autopackage-gtk-$autopackage_version.package"

            # check in executed from directory
            elif [ -e "$EXECUTED_FROM_DIRECTORY/autopackage-gtk-$autopackage_version.package" ]; then
                filename="$EXECUTED_FROM_DIRECTORY/autopackage-gtk-$autopackage_version.package"

           # check in package base directory
            elif [ -e "$_package_directory/autopackage-gtk-$autopackage_version.package" ]; then
                filename="$_package_directory/autopackage-gtk-$autopackage_version.package"
            fi

            unset _package_directory
            trace located GTKFE package=$filename

            # allow gtkfe package to be executed directly
            export _autopackage_execute_package=1

            if [[ "$filename" != "" ]]; then
                out
                ! "$autopackage_silent" && out "Installing graphical interface, please wait... "
                chmod +x "$filename"
                "$filename"
                retval="$?"
                if [[ "$retval" != "0" ]]; then
                    _finishWindow
                    return "$retval"
                fi
            else
                trace trying to download GTKFE package "http://autopackage.org/downloads/$autopackage_version/autopackage-gtk-$autopackage_version.package"
                if [[ "$yesno_suppress" != "1" ]]; then
                    yesNo "OK to download and install graphical interface now? (Y/n): "
                    retval="$?"
                    if [[ "$retval" != "0" ]]; then
                        return "$retval"
                    fi
                fi

                if [[ "$AUTOPACKAGE_RUNTIME_MIRRORS" == "" ]]; then
                    _runtime_mirrors="http://autopackage.org/downloads http://www.wildgardenseed.com/autopackage http://www.allaboutgames.co.uk/autopackage"
                else
                    _runtime_mirrors="$AUTOPACKAGE_RUNTIME_MIRRORS"
                fi
                out
                out
                for mirror in $_runtime_mirrors; do
                    download "$mirror/$autopackage_version/autopackage-gtk-$autopackage_version.package"
                    retval=$?
                    out
                    out
                    if [[ "$retval" == "0" ]] && [ -f "autopackage-gtk-$autopackage_version.package" ]; then
                        filename="`pwd`/autopackage-gtk-$autopackage_version.package"
                        ! "$autopackage_silent" && out "Installing graphical interface, please wait... "
                        chmod +x "$filename"
                        "$filename"
                        retval="$?"
                        if [[ "$retval" != "0" ]]; then
                            _finishWindow
                            return "$retval"
                        fi
                        rm "$filename"
                        break
                    fi
                done
                ! "$autopackage_silent" && out "Unable to download, skipping installation of graphical interface... "
                _finishWindow
                return 1

            fi

            ! "$autopackage_silent" && out " "
            return 0

        fi

        return 5

    fi

    return 0

}


##
# _installApbuild
#
# Upgrade/install apbuild.
function _installApbuild() {

	trace called
	keep_apbuild=false

	if locateCommand apgcc; then
		# Only upgrade if the apbuild on the system is different
		if ! diff --brief "$lc_location" "$apkg_main_dir/../apbuild/apgcc" &> /dev/null; then
			keep_apbuild=false
			# check for SVN directory apbuild
			if [ ! -e "$apkg_main_dir/../apbuild" ]; then
				err "Need to have SVN directory autopackage/apbuild available"
				err "so that it can be installed for use."
				return 1
			fi
			cd "$apkg_main_dir/../apbuild"

			! "$autopackage_silent" && out
			! "$autopackage_silent" && out "Need to remove SVN directory apbuild's apgcc executable... "
			if ! "$autopackage_silent"; then
			    make uninstall
			else
			    make uninstall > /dev/null 2>&1
			fi
		else
			keep_apbuild=true
			! "$autopackage_silent" && [[ "$1" != "-q" ]] && out
			! "$autopackage_silent" && [[ "$1" != "-q" ]] && out "Skipping installation of SVN directory apbuild's apgcc executable... "
		fi
	fi

	if ! $keep_apbuild; then
		! "$autopackage_silent" && out
		! "$autopackage_silent" && out "Installing SVN directory apbuild's apgcc executable... "
		cd "$apkg_main_dir/../apbuild"

		! "$autopackage_silent" && out
		! "$autopackage_silent" && out "Need to install SVN directory apbuild's apgcc executable... "
		if ! "$autopackage_silent"; then
		    make install
		else
		    make install > /dev/null 2>&1
		fi

		# add uninstall commands to log
		logCommand "oPWD=\`pwd\`; cd `escapeFilename "${apkg_main_dir}/../apbuild"`; make uninstall; cd \"\$oPWD\";"
	fi
}

## START AUTOSUCOMMAND
## Function is substituted from apkg-funclib.
function _autosuCommand() {

	local status_message

	# autosu error codes
	#   0  Success
	#  11  User clicked cancel
	#  12  User doesn't have a password
	#  13  su exited abnormally
	#  14  User typed incorrect password 3 times
	#  15  System error

	# Don't use autosu if we're already root, or
	# if $autopackage_no_autosu is set, or if --local-only was passed
	# on the command line
	
	# If /etc/autopackage/config was not found, then that means the user
	# installed autopackage itself as non-root. In that case, never ask
	# for the root password, because root will not be able to find the
	# autopackage support libraries.

	if [[ `id -u` == 0 || "$INSTALL_FORCE" == "local" || ( ! -f /etc/autopackage/config && -f "${XDG_CONFIG_HOME:-$HOME/.config}/autopackage/config" ) || ("$autopackage_no_autosu" == "true" && "$1" != "--root-only") ]]; then
		# Filter out autosu arguments
		while [[ "${1:0:1}" == "-" ]]; do
			if [[ "$1" == '--root-only' ]]; then
				shift
			elif [[ "$1" == '--local-only' ]]; then
				shift
			elif [[ "$1" == '-m' ]]; then
				shift
				shift
			else
				break
			fi
		done
		"$@"
		return "$?"
	fi

	local cmdret
	local r
	local autosu_component

	cmdret="$TMP/autosu.$RANDOM$$"

	# define autosu component and location to execute autosu command

	# check for X and GTK2
	if [[ "$DISPLAY" == "" ]] || ! xdpyinfo &>/dev/null || [[ "$AUTOPACKAGE_FRONTEND" == "apkg-ttyfe" ]] || ! testForLib libgtk-x11-2.0.so || ldd autopackage/libexec/autosu-gtk 2>/dev/null|grep -q "not found" || ldd "$autopackage_prefix/libexec/autopackage/autosu-gtk" 2>/dev/null|grep -q "not found"; then
		# No X and/or GTK2, and/or missing deps, so use tui (could be a headless script)
		autosu_component="autosu-tui"
	else
		autosu_component="autosu-gtk"
	fi

	# autopackage support code installation location
	if [ -x "$autopackage_prefix/libexec/autopackage/$autosu_component" ]; then
        	trace invoking autosu: "$autopackage_prefix/libexec/autopackage/$autosu_component" "$@"
		"$autopackage_prefix/libexec/autopackage/$autosu_component" "$@" 5>"$cmdret"
		r="$?"
		cmdret=`<"$cmdret"; rm "$cmdret"`

	# autopackage support code package location
	elif [ -x "autopackage/libexec/$autosu_component" ]; then
        	trace invoking autosu: "autopackage/libexec/$autosu_component" "$@"
		"autopackage/libexec/$autosu_component" "$@" 5>"$cmdret"
		r="$?"
		cmdret=`<"$cmdret"; rm "$cmdret"`
	fi

	# user clicked cancel or entered the wrong password 3 times
	if [[ "$r" == "11" || "$r" == "14" ]]; then
		return 13

	# user does not have a root password
	elif [[ "$r" == "12" ]]; then
		# Filter out autosu arguments and run the command directly
		while [[ "${1:0:1}" == "-" ]]; do
			shift
			shift
		done
		"$@"
		return "$?"

	# for all other errors fail
	elif [[ "$r" != "0" ]]; then
		return 15
	fi

	# Return the command's (not autosu's) exit code
	return $cmdret

}
## END AUTOSUCOMMAND


##
# _checkVersionRequirements
#
# Determines minimum levels of acceptable versions for certain commands
function _checkVersionRequirements() {

	trace funclib: sanity version checks starting

	#locateCommand file "--version"
	#current_version=`echo "$lc_output" | grep -e 'file-' | sed 's/file-//'`
	#if ! compareVersions "3.30" "$current_version"; then
	#	out "$intl_SETUP_VERSION_REQUIREMENT" "file" "3.30"
	#	exit 1
	#fi

	locateCommand wc "--version"
	# There's a difference between GNU textutils's wc and coreutils's wc
	if echo "$lc_output" | grep -q '^wc (textutils)'; then
		current_version=`echo "$lc_output" | grep -e 'wc ' | sed 's/wc (textutils) //'`
		if ! compareVersions "2.0.14" "$current_version"; then
			out "$intl_SETUP_VERSION_REQUIREMENT" "wc" "2.0.14"
			exit 1
		fi
	#else
	#	current_version=`echo "$lc_output" | grep -e 'wc ' | sed 's/wc (coreutils) //'`
	#	if ! compareVersions "4.5" "$current_version"; then
	#		out "$intl_SETUP_VERSION_REQUIREMENT" "wc" "4.5"
	#		exit 1
	#	fi
	fi

	# test for glib-2.0 requirement
	if ! testForLib libglib-2.0.so; then
		out "$intl_SETUP_VERSION_REQUIREMENT" "glib" "2.0"
		exit 1
	fi

	trace funclib: sanity version checks completed

}


function _processPackageArguments() {
	# process the CLI arguments, step 2
	trace called with $@
	force="false" # default
	while [[ "$1" != "" ]]; do
		case `echo $1 | sed 's/=.*//'` in
			"-p" | "--prefix") export PREFIX=$( chewArgument $@ ); shift; shift;
				trace using prefix $PREFIX
				if [[ "$PREFIX" == "" ]]; then red; outn "$intl_FAIL"; normal; out "$intl_PREFIX_NOT_SPECIFIED"; exit 1; fi;
                    # mark where prefix was set
                    export _prefix=commandline
                    trace _prefix=$_prefix
				;;
			"-f" | "--force") force="true"; shift;
				;;
			"-h" | "--help") shift; out "$intl_INSTALLER_HELP"; _installerFinish; exit 0;;
			"-g" | "--gtkfe") shift; export AUTOPACKAGE_FRONTEND="autopackage-frontend-gtk";;
			"-t" | "--ttyfe") shift; export AUTOPACKAGE_FRONTEND="apkg-ttyfe";;
			"--local-only") shift; export INSTALL_FORCE="local";; # Force local installation
			"--root-only") shift; export INSTALL_FORCE="system";; # Force system-wide installation
			*)  red; outn "$intl_FAIL"; normal; out "$intl_UNKNOWN_OPTION" "$1"; shift;
				shift; exit 1;
				;;
		esac
	done
}


function _genSummary() {
	{
		echo "DISPLAY-SUMMARY"
		echo "install"
		echo "success"
		echo "$SHORTNAME"
		if [ -e "$WORKING_DIRECTORY/display-names" ]; then
			echo `wc -l <"$WORKING_DIRECTORY/display-names"`
			cat "$WORKING_DIRECTORY/display-names"
		else
			echo "0"
		fi
		if [ -e "$WORKING_DIRECTORY/desktop-files" ]; then
			echo `wc -l <"$WORKING_DIRECTORY/desktop-files"`
			cat "$WORKING_DIRECTORY/desktop-files"
		else
			echo 0
		fi
		if [ -e "$WORKING_DIRECTORY/install-sizes" ]; then
			# stream sum total - count is always 1
			echo "1"
			while read; do
				line=`echo "$REPLY"`
				[[ "$line" != "" ]] && let "total = $total + $line"
			done <"$WORKING_DIRECTORY/install-sizes"
			echo "$total"
		else
			echo "0"
		fi
		if [ -e "$WORKING_DIRECTORY/failed-recommends" ]; then
			echo `wc -l <"$WORKING_DIRECTORY/failed-recommends"`
			cat "$WORKING_DIRECTORY/failed-recommends"
		else
			echo "0"
		fi

	} > "$autopackage_pipe"
	cat "$autopackage_pipe" >/dev/null # sloppy but i'm tired -m
}


##
# getLanguages
#
# Returns a list of user languages like 'fr_CA en_US en fr' from 'fr_CA.UTF-8:en_US.UTF-8:en_US:en'.
# Example: language_list=`getLanguages`
function getLanguages() {

	local language_list language_match_list language_item language_element

	# if AUTOPACKAGE_LANGUAGE is used then the user is forcing
	if [ "$AUTOPACKAGE_LANGUAGE" ]; then
		language_list="$AUTOPACKAGE_LANGUAGE"
		trace using AUTOPACKAGE_LANGUAGE=$AUTOPACKAGE_LANGUAGE

	else

		# order and structure defined by The Open Group Base Specifications Issue 6
		# use LANGUAGE if it exist because it is used by GNU gettext
		if [[ "$LANGUAGE" != "" && "$LANGUAGE" != "C" ]]; then
			language_list="$LANGUAGE"
			trace using LANGUAGE=$LANGUAGE

		# LC_ALL is used to default LC_* environment variables
		elif [[ "$LC_ALL" != "" && "$LC_ALL" != "C" ]]; then
			language_list="$LC_ALL"
			trace using LC_ALL=$LC_ALL

		# use LANG if LC_ALL is not present
		elif [[ "$LANG" != "" && "$LANG" != "C" ]]; then
			language_list="$LANG"
			trace using LANG=$LANG

		# define default language
		else
			language_list="en"
			trace using default as language_list=$language_list
		fi

	fi

	# filter for LANGUAGE information syntax and strip encoding descriptions
	language_list_temp=`echo "$language_list" | sed 's/:/ /g'`
	unset language_list
	for language_item in $language_list_temp; do
		# strip encoding
		language_item=`getMajor "$language_item"`
		if ! isInList '-F ' "$language_item" "$language_list"; then
			if [[ "$language_list" == "" ]]; then
				language_list=`echo "$language_item"`
			else
				language_list=`echo "$language_list $language_item"`
			fi
		fi
		unset language_item language_match
	done

	# breakdown language_COUNTRY by stripping COUNTRY description and add to language_match_list
	for language_item in $language_list; do
		language_element="${language_item/_*/}"
		if [[ "$language_item" != "$language_element" ]]; then
			language_match_list=`echo "$language_match_list $language_element"`
		fi
		unset language_item language_element
	done

	# cycle through language_match_list and add to language_list if it does not exist in language_list
	for language_match_item in $language_match_list; do
		unset language_match
		if ! isInList '-F ' "$language_match_item" "$language_list"; then
			language_list=`echo "$language_list $language_match_item"`
		fi
	done

	# add default language 'en' if not present or derived
	if ! isInList '-F ' "en" "$language_list"; then
		trace adding en as default to language_list
		language_list=`echo "$language_list en"`
	fi

	trace language_list=$language_list
	echo "$language_list"
	return 0

}


##
# _loadPackageEnvironment <DIRECTORY>
# DIRECTORY: base directory in which to look for environment files
#
# Loads package environment file from the DIRECTORY.
# The users language setting is determined and the representative environment
# file is loaded. The environment file enables the system to give localized
# package information. If any information is not localized, then it will be
# have been retrieved from the en language setting. The environment files can
# be either processed files (environment.en) or non-processed
# (apkg-environment.en) files.
# <pre>
# Process:
#   Looks for environment file to match user languages
#     fr --> apkg-environment.fr     de --> apkg-environment.de
#   If files are named environment then the files have already been copied
#     into the package database and load the representative file instead
#   If no localized environment file exists then load apkg-environment.en
#   Create files to copy into package database
#     fr --> environment.fr     de --> environment.de
# </pre>
# Example:
#   _loadPackageEnvironment "$autopackage_db_location/$1"
#
function _loadPackageEnvironment() {

    trace called with "$1"
    local location="$1"
    local language
    unset language_selected

    # get list of user languages if not defined by _initializeAutopackage - this is used
    # during initial autosu through _autosuCommand() for installation authorization
    if [[ "$language_list" == "" ]]; then
        language_list=`getLanguages`
    else
        trace language_list=$language_list
    fi

    # go through language list and match the first language from order of preference user listing
    for language in $language_list; do

        if [ -f "$location/environment.${language}" ]; then
            trace loading package environment from "$location/environment.${language}"
            source "$location/environment.${language}"
            language_selected="$language"
            break
        elif [ -f "$location/apkg-environment.${language}" ]; then
            trace loading package environment from "$location/apkg-environment.${language}"
            source "$location/apkg-environment.${language}"
            language_selected="$language"
            break
        fi

    done

    if [ ! "$language_selected" ]; then
        trace requested user language not found, falling back to en or database package location
        language_selected="en"
        if [ -f "$location/environment.${language_selected}" ]; then
            trace loading package environment from "$location/environment.${language_selected}"
            source "$location/environment.${language_selected}"
        elif [ -f "$location/apkg-environment.${language_selected}" ]; then
            trace loading database package environment from "$location/apkg-environment.${language_selected}"
            source "$location/apkg-environment.${language_selected}"
        fi
    fi

    # set variable for location for other functions that call _loadPackageEnvironment
    export PACKAGELOCATION="$location"

    # set variable for backup location if a file copy collides
    # if not set, it means it is not read or available from package database environment file
    [[ "$BACKUP" == "" ]] && export BACKUP="$ROOTNAME/backup";

    # set variable for the language that was selected for display from getLanguages $language_list
    export language_selected="$language_selected"

    # make local timestamps available
    if [ -n "$TIMESTAMPINSTALL" ]; then
        # TIMESTAMPINSTALL is set through _createPackageEnvironmentFiles written to apkg-environment.$language
        # if this is the current package environment read from environment.${language_selected} then $TIMESTAMPINSTALL is not set
        TIMESTAMPINSTALL_LOCAL=`echo "$TIMESTAMPINSTALL" | sed 's/T/ /'`
        TIMESTAMPINSTALL_LOCAL=`LC_ALL="$language_selected" date --date="$TIMESTAMPINSTALL_LOCAL" --iso-8601=seconds`
    fi
    TIMESTAMPBUILD_LOCAL=`echo "$TIMESTAMPBUILD" | sed 's/T/ /'`
    TIMESTAMPBUILD_LOCAL=`LC_ALL="$language_selected" date --date="$TIMESTAMPBUILD_LOCAL" --iso-8601=seconds`

    # repository skeleton value always trumps meta data value
    # check for skeleton existence and retrieve value
    local m_skelfile=`_locateSkeleton "$ROOTNAME"`
    if [ -n "$m_skelfile" ]; then
        REPOSITORY=`getSectionKey "$m_skelfile" "Meta" "Repository"`
    fi

    trace ROOTNAME=$ROOTNAME
    trace SHORTNAME=$SHORTNAME
    trace DISPLAYNAME=$DISPLAYNAME
    trace AUTOPACKAGETARGET=$AUTOPACKAGETARGET

    if [[ "$_meta_dir" == "" ]]; then
        local _meta_dir=$1
    fi
    export apkg_logfile="$_meta_dir/log"
    export apkg_filelist="$_meta_dir/filelist"

}


##
# _createPackageEnvironmentFiles <DIRECTORY>
# DIRECTORY: base directory to create environment files.
#
# Loads package environment file from the DIRECTORY.
# The users language setting is determined and the representative environment
# file is loaded. Processes for each package language, the environment
# files to be prepared for copying in package installation database.
# Add runtime installation variables to environment files.
# <pre>
# Process:
#   Create files to copy into package database within _createDBEntry function.
#     fr --> environment.fr     de --> environment.de
# </pre>
# Example:
#   _createPackageEnvironmentFiles "$_meta_dir"
#
function _createPackageEnvironmentFiles() {

    trace called with "$1"
    local location="$1"
    local language

    # Load and use package environment file during package file creation
    _loadPackageEnvironment "$location"

    # Create package environment file for use in _createDBEntry function if not created yet
    if [ ! -e "$location/environment.en" ]; then

        # Determine install package variables for package environment file
        if [[ `id -u` == "0" ]]; then
            DATABASE="Global"
        else
            DATABASE="User"
        fi

        # set variables to use $installKeys list
        # generate UTC timestamp to use with locale
        # bash compatibility use format instead of --iso-8601=seconds
        TIMESTAMPINSTALL="`LC_ALL=C date -u +%Y-%m-%dT%T%z | cut -b -19`Z"

        # go through language list and create package environment files and add runtime install variables
        for language in $PACKAGELANGUAGES; do

            trace creating package environment from "$location/apkg-environment.${language}"
            cp -f "$location/apkg-environment.${language}" "$location/environment.${language}"

            oIFS="$IFS"
            IFS=$' \t\n'

            echo "" >> "$location/environment.${language}"
            echo "# Package install information" >> "$location/environment.${language}"
            for k in $installKeys; do
                echo "export ${k}=\"${!k}\"" >> "$location/environment.${language}"
            done

            IFS="$oIFS"

        done

    fi

}


##
# _dumpPackageEnvironment <IDENTIFY>
# IDENTIFY: text to identify the location of the breakpoint
#
# Place _dumpPackageEnvironment in some logic to trace all of the package variables.
# Add extra variables to trace by including a APKG_DUMP_VARIABLES.
#
# Example:
#   export AUTOPACKAGE_DUMP_VARIABLES="_meta_dir WORKING_DIRECTORY"
#   _dumpPackageEnvironment first package to arrive
function _dumpPackageEnvironment() {

	local apkg_variables
	local apkg_variable
	trace called with $@
	# if AUTOPACKAGE_DUMP_VARIABLES is used then the user is adding variables to output
	if [ "$AUTOPACKAGE_DUMP_VARIABLES" ]; then
		apkg_variables="$specKeys $buildKeys $installKeys $AUTOPACKAGE_DUMP_VARIABLES"
	else
		apkg_variables="$specKeys $buildKeys $installKeys"
	fi
	for apkg_variable in $apkg_variables; do
		a="${apkg_variable}"
		trace "$apkg_variable=\"${!a}\""
	done

}


##
# _packageInfo <SHORTNAME>
# SHORTNAME: name which declares package.
#
# Output package information of a given package.
function _packageInfo() {

    trace called with $1

    out "$intl_PACKAGE_INFO_SHORTNAME" "$SHORTNAME"
    out "$intl_PACKAGE_INFO_DISPLAYNAME" "$DISPLAYNAME"
    out "$intl_PACKAGE_INFO_ROOTNAME" "$ROOTNAME"
    out "$intl_PACKAGE_INFO_SOFTWAREVERSION" "$SOFTWAREVERSION"
    out "$intl_PACKAGE_INFO_INTERFACEVERSION" "$INTERFACEVERSION"
    out "$intl_PACKAGE_INFO_PACKAGEVERSION" "$PACKAGEVERSION"
    out "$intl_PACKAGE_INFO_MAINTAINER" "$MAINTAINER"
    out "$intl_PACKAGE_INFO_LICENSE" "$LICENSE"
    out "$intl_PACKAGE_INFO_ROOTINSTALLONLY" "$ROOTINSTALLONLY"

    [[ "$DATABASE" == "Global" ]] && out "$intl_PACKAGE_INFO_DATABASE" "$intl_PACKAGE_INFO_DATABASE_GLOBAL";
    [[ "$DATABASE" == "User" ]] && out "$intl_PACKAGE_INFO_DATABASE" "$intl_PACKAGE_INFO_DATABASE_USER";
    out "$intl_PACKAGE_INFO_BUILDHOST" "$BUILDHOST"

    TIMESTAMPBUILD=`echo "$TIMESTAMPBUILD" | tr "T" " "`
    # bash compatibility include LANG environment variable
    TIMESTAMPBUILD=`LC_ALL="$language_selected" LANG="$language_selected" date --date="$TIMESTAMPBUILD" +%c`
    out "$intl_PACKAGE_INFO_TIMESTAMPBUILD" "$TIMESTAMPBUILD"

    TIMESTAMPINSTALL=`echo "$TIMESTAMPINSTALL" | tr "T" " "`
    # bash compatibility include LANG environment variable
    TIMESTAMPINSTALL=`LC_ALL="$language_selected" LANG="$language_selected" date --date="$TIMESTAMPINSTALL" +%c`
    out "$intl_PACKAGE_INFO_TIMESTAMPINSTALL" "$TIMESTAMPINSTALL"

    out "$intl_PACKAGE_INFO_SIZE" "$INSTALLSIZE"
    out "$intl_PACKAGE_INFO_PACKAGER" "$PACKAGER"
    out "$intl_PACKAGE_INFO_REPOSITORY" "$REPOSITORY"
    out "$intl_PACKAGE_INFO_URL" "$URL"
    out "$intl_PACKAGE_INFO_SUMMARY" "$SUMMARY"
    out

}


##
# getPackagePrefix <SHORTNAME>
# SHORTNAME: package or executable to find a prefix for.
# Returns: 0 for all cases.
#
# Returns the prefix of a previously installed package or executable.
# It returns the prefix from these scenarios:<br />
# 	a. package is in autopackage database<br />
# 	b. executable is located and give grandparent directory<br />
# 	c. package is assumed to be installing at the sametime then give $PREFIX
#
# Function is useful when trying to install something relative to another package
# or executable like plugins.
#
# Example: export PREFIX=`getPackagePrefix "foobar"`
function getPackagePrefix() {
	pushOptE; set +e;
	trace called with $1
	local prefix
	if isNameKnown "$1"; then
		# subshell as to not collide with the existing environment
		prefix=$( _loadPackage "$1"; echo "$PREFIX"; )
	elif locateCommand "$1"; then
		prefix=`dirname "$lc_location"`
		prefix=`dirname "$prefix"`
	else
		prefix="$PREFIX"
	fi
	echo "$prefix"
	trace finished
	popOptE; return 0;
}


##
# _apkgPrefix
#
# Determine the prefix to use for installing autopackage support code to.
# If the user is root, this is /usr. If the user is not root,
# it is $HOME/.local. The result is output on stdout.
#
# This is an internal function used only while setting up the autopackage
# support code. Never use this function.
function _apkgPrefix() {
	local prefix
	if [[ `id -u` != "0" ]]; then
	    prefix="$HOME/.local"
	else
	    prefix="/usr"
	fi

	trace prefix="$prefix"
	echo "$prefix"
}

##
# _userPrefix
#
# Determine prefix to install software to. This can be overriden
# by the autopackage config file. When root, the result is by default
# /usr, when non-root ~/.local, however this may change on a per-package
# basis depending on the system configuration.
#
# This is an internal function used to set $PREFIX (if $PREFIX isn't already
# explicitly set by an argument). Do not use this function, use $PREFIX instead.
function _userPrefix() {
	local prefix
	trace autopackage_default_prefix=$autopackage_default_prefix
	
	if [[ "$_PLATFORM" == "KDE" ]] && [[ "$AUTOPACKAGETARGET" != "1.0" ]]; then
		# bash thinks that an unset variable is true, so only check post-1.0 packages
		# ($_PLATFORM was introduced in 1.1)
		if [[ `id -u` != "0" ]]; then
			local kdeconfigPrefix="`locateCommand -o kde-config --localprefix`"
			
			if [ -n "$KDEHOME" ]; then
				prefix=$KDEHOME
			elif [ -n "$kdeconfigPrefix" ]; then
				# kde-config returned a sane local prefix
				prefix=$kdeconfigPrefix
			else
				# *sigh*, defaults
				prefix="$HOME/.kde"
			fi
		else
			prefix=`getKdePrefix`
			
			if ! haveWriteAccess "$prefix"; then
				prefix="$HOME/.kde"
			fi
		fi
	else
		if [[ "$autopackage_default_prefix" != "" ]]; then
			prefix="`eval echo $autopackage_default_prefix`"
			if [[ `id -u` != "0" ]]; then
				if ! haveWriteAccess "$prefix"; then
						prefix="$HOME/.local"
				fi
			fi
		else
			if [[ `id -u` != "0" ]]; then
				prefix="$HOME/.local"
			else
				prefix="/usr"
			fi
		fi
	fi
	trace prefix="$prefix"
	echo "$prefix"
}


##
# _userConfig
# Outputs: a directory name.
#
# Determine the folder in which configuration files are stored.
# If root then the directory is /etc or /etc/xdg [XDG]. If user then the directory
# is $HOME/.config or $XDG_CONFIG_HOME/config [XDG].
#
# This is an internal function used only while setting up the autopackage support code.
# It's not encouraged that you use this function unless you have a very good reason to do so.
function _userConfig() {
	local etc_dir

	if [[ `id -u` != "0" ]]; then
	    if [[ "$XDG_CONFIG_HOME" != "" ]]; then
			etc_dir="$XDG_CONFIG_HOME"
	    else
			etc_dir="$HOME/.config"
	    fi
	else
            # for now we must ignore XDG_CONFIG_DIRS as the rest of the code can't cope with it
	    etc_dir="/etc"
	fi
	trace etc_dir="$etc_dir"
	echo "$etc_dir"

}

# The original _userConfig had a typo (etc_dir="$XDG_CONFIG_HOME/config"
# instead of etc_dir="$XDG_CONFIG_HOME"). Unfortunately, installConfig uses _userConfig.
# For the sake of compatility we make installConfig use this old (broken) _userConfig
# implementation.
function _userConfig_broken() {
	local etc_dir

	if [[ `id -u` != "0" ]]; then
	    if [[ "$XDG_CONFIG_HOME" != "" ]]; then
		etc_dir="$XDG_CONFIG_HOME/config"
	    else
		etc_dir="$HOME/.config"
	    fi
	else
            # for now we must ignore XDG_CONFIG_DIRS as the rest of the code can't cope with it
	    etc_dir="/etc"
	fi
	trace etc_dir="$etc_dir"
	echo "$etc_dir"

}


# The reason that this is so hard to understand is because we have to start from the
# bottom of the payload tree and work up. A payload may depend on its dependencies
# being fully installed first, so we have to walk the tree in the opposite direction
# to processing the prep scripts -mike 27/04/2003
function processInstallPayloads() {
	# read the first
	local p
	local oIFS="$IFS"

	# for some reason, aliases don't work here (bug in bash?)
	(( DEBUGLEVEL >= 3 )) && _trace $FUNCNAME " $1";

	IFS=$'\n'
	if [ -e "$WORKING_DIRECTORY/meta/$1/payloads" ]; then
		for p in `<"$WORKING_DIRECTORY/meta/$1/payloads"`; do
			# recurse into them
			trace " --> recursing into $p, here we go!"
			_meta_dir="$WORKING_DIRECTORY/meta/$p" processInstallPayloads "$p" || return $?
			trace " <-- processed OK, recursing out of $p"
		done
	fi
	IFS="$oIFS"

	# does the payload exist? if not, we need to download it first
	if [ ! -d "$WORKING_DIRECTORY/payload/$1" ]; then
		(( DEBUGLEVEL >= 3 )) && _trace $FUNCNAME " payload $1 is registered but non-existant locally, retrieving from network"
		_retrievePayloadFromNet $1 || return 2
	fi

	pushd "$WORKING_DIRECTORY/payload/$1" >/dev/null
	# FIXME: should we do _meta_dir here too?
	export _payload_dir="$WORKING_DIRECTORY/payload/$1"
	# restore environment
	_loadPackageEnvironment "$WORKING_DIRECTORY/meta/$1"
 
	# determine package installation prefix, if not passed in as an argument
	# mainly for cases where package meta data is used in prefix like $SHORTNAME
	trace _prefix=$_prefix
	if [[ "$_prefix" != "commandline" ]]; then
	    export PREFIX=`_userPrefix`
	fi

	# execute the install script
	(( _cur_series_pos++ ))
	"$WORKING_DIRECTORY/meta/$1/apkg-install-script" || {
		popd >/dev/null
		local err=`outn "$intl_INSTALL_ERROR" "$DISPLAYNAME"`
		outputFail "$err"
		return 1
	}
	popd >/dev/null

	trace recording action=record event=installation firsttime=$_autopackage_support_install rootname=`justRootName "$ROOTNAME"` shortname=$SHORTNAME softwareversion=$SOFTWAREVERSION interfaceversion=$INTERFACEVERSION result=0
	if [[ "$PACKAGEREPORTING" != "No" ]]; then
		echo "action=record&event=installation&firsttime=$_autopackage_support_install&rootname=`justRootName "$ROOTNAME"`&shortname=$SHORTNAME&softwareversion=$SOFTWAREVERSION&interfaceversion=$INTERFACEVERSION&result=0" >> "$WORKING_DIRECTORY/reporting"
	else
		trace PACKAGEREPORTING=$PACKAGEREPORTING so skip recording the event
	fi
	
	return 0
}


# **************************************************************
#   Firstly, we check for the presence of the autopackage tools. If not
#   present, then we fork to another script that offers to download
#   and install it - easy for the user no? If it is present, then
#   we proceed with the installation process, using named pipes to
#   communicate with the "front end" module. Installations should
#   have the ability to proceed with NO user interaction whatsoever,
#   this might mean being able to read settings from an external file
#   or simply always having sensible defaults.
#
# **************************************************************

# Called when the entire installation is done. Don't confuse this with
# _installScriptFinished, which is called every time an install script has finished.
#
# Put stuff that always needs to be done on exit (whether clean or not) here.
# Exit code (optional) is given in $1
function _installerFinish() {

    trace called

    # exit global session
    if [[ "$autopackage_pipe" != "" ]]; then terminateFE; fi

    if $autopackage_anonymous_reporting && [ -e "$WORKING_DIRECTORY/reporting" ] && locateCommand wget; then
        # send data by POST
        while read; do
            ( wget $autopackage_wget_options --quiet --output-document="/dev/null" --output-file="/dev/null" --post-data="$REPLY" http://autopackage.org/statistics/; ) &
            trace reporting $REPLY
        done <"$WORKING_DIRECTORY/reporting"
    fi

    if [[ "`pwd`" != "$EXECUTED_FROM_DIRECTORY" ]]; then
        trace moving shell to executed from directory
        cd "$EXECUTED_FROM_DIRECTORY"
    fi

    trace removed working directory $WORKING_DIRECTORY
    rm -rf "$WORKING_DIRECTORY"

    # session file removed next time through bashlib
    exit $1
}

##
# _installer
#
# This is the first function that is called when a package begins its installation.
function _installer() {
    trace starting up

    # check that we came through the package script and not directly through the package file
    # old packages might not have template variable so only check in 1.2 API packages
    # additionally set in _installGTKFE for gtkfe installation part of support code setup
    if [[ "$AUTOPACKAGETARGET" != "1.0" ]]; then
        if [ -z "$_autopackage_execute_package" ] && [ -z "$_autopackage_support_install" ]; then
            _packageReturnCode "14"
            _installerFinish 14 # exits for us
        fi
    fi

	# need to process arguments first before allowing the package meta data to be loaded
	# _loadPackageEnvironment sources and writes environment files to database during first run
	_processPackageArguments "$@"

	# initialize variables
	_initializeAutopackage

	if [[ "$first_autosu" == "" ]]; then
                # this [sorta hack] is about preventing recursive authentication attempts
                # it should probably be combined with we_are_the_first - see below
		export first_autosu="true"

                local tmp
                local needed_archs
                tmp=$( _loadPackageEnvironment "$_meta_dir"; echo "$CPUARCHITECTURES"; echo "$ROOTINSTALLONLY"; echo "$DISPLAYNAME"; )

                # check CPU arch is OK before we run any native code
                needed_archs=$( echo "$tmp" | sed -n '1p' )
                local found=false
                for a in $needed_archs; do
                    if [[ "$a" == "$cpu_architecture" ]]; then found=true; fi
                done

                if ! $found; then

                    # arch command is not consistent like ia32.linux != i686 so use uname
                    locateCommand uname
                    this_arch=`"$lc_location" -m`
                    out
                    out "$intl_UNSUPPORTED_CPU_ARCH" "$needed_archs" "$this_arch"
                    out
                    unset this_arch
                    return 1
                fi

                trace passed cpu arch test

		ROOTINSTALLONLY=$( echo "$tmp" | sed -n '2p' )
		DISPLAYNAME=$( echo "$tmp" | sed -n '3p' )
                unset tmp

		export AUTOSU_DISPLAYNAME="$DISPLAYNAME"

                # recurse
		if [[ "$ROOTINSTALLONLY" == "Yes" || "$INSTALL_FORCE" == "system" ]]; then
			_autosuCommand --root-only "$_meta_dir/apkg-installer" "$@"
		else
			_autosuCommand "$_meta_dir/apkg-installer" "$@"
		fi
		retval=$?
                trace "autosu retval=$retval"
		return $retval
	fi

	_loadPackageEnvironment "$_meta_dir"

    # this is the last check before booting frontend
    # check if an end user license agreement requires acceptance
    if ! _checkEULA; then
        return 1
    fi

	if [[ "$we_are_the_first" == "" ]]; then
		export we_are_the_first="true"
	fi  # otherwise it must be false

	boot_frontend="false"
	if [[ "$autopackage_pipe" == "" ]]; then
		export autopackage_pipe="${TMP}/apkg-fifo$$"
		rm -f "$autopackage_pipe" # in case we get an old crashed pid
		trace creating fifo at $autopackage_pipe
		mkfifo "$autopackage_pipe" || {
                    err failed to create fifo
                    exit 1
                }
		boot_frontend="true"
	fi

	# touch the payloads file into existance
	touch "$_meta_dir/payloads"

	# start the install process
	if $we_are_the_first; then
		(
			# create a "global" session, so that we don't quit in the time between the end of the
			# prep scripts and start of the install scripts
			trace waiting for frontend
			if ! waitForHELLO; then
				err "protocol version mismatch, check your install";

				# suppress termination of the FE
				autopackage_pipe=""

				_installerFinish 1
			fi

			# check for user lock
			if $autopackage_deny_user; then
				outputFail "$intl_ACCESS_DENIED"
				_installerFinish 1
			fi

			# check to see if we are already installed.....
			# for now just check the autopackage db
                        # this should be replaced by an actual file check post 1.0
			# dependencies don't do this check because if the dependency
			# check failed, we assume that
			# even when the package is apparently installed, parts of it must be missing

			if ! checkDiskSpace "$EXPANDSIZE" "$PREFIX"; then
				outputFail "$intl_NO_DISK_SPACE" "$SHORTNAME" "$PREFIX" "$EXPANDSIZE";
				_installerFinish 1
			fi

			# process the prep scripts - why do we set we_are_the_first here?
			we_are_the_first="false" "$_meta_dir/apkg-prep-install-script"
			if [[ "$?" == "0" ]]; then

				trace proceeding with removal

				if isNameKnown "$SHORTNAME"; then
					# needs to be in subshell to protect the package environment
					(
						uninstallPackage "$SHORTNAME"; exit $?
					)
					if [[ "$?" != "0" ]]; then
						_installerFinish 1
					fi
				fi

				trace proceeding with installation

				# start a series on the GUI
				if [ -e "$WORKING_DIRECTORY/global-payloads" ]; then
					_total_payloads=$( cat "$WORKING_DIRECTORY/global-payloads" | wc -l )
					# for the current package, which won't be registered
					(( _total_payloads++ ))
					startSeries $_total_payloads
					unset _total_payloads
				else
					startSeries 1
				fi
				export _cur_series_pos=0

				processInstallPayloads "$ROOTNAME" # process the payloads
				local ret="$?"
				if [[ "$ret" == "0" ]]; then
					# we made it! praise be!
					# process waiting session triggers
					_processTriggers --session
					_genSummary
				else
					# if payloads were not installed because of a failure in the package scripts
					# then rollback installation. if the return code is 2 that means something went
					# wrong with unpacking or retrieving the payloads
					###_sessionRollback
                    # still process triggers as caches are probably out of state
                    _processTriggers --session
					_installerFinish "$ret"
				fi # assume we output some FAIL message to explain why we didn't install correctly
			elif [[ "$?" == "3" ]]; then
				# collect result
				trace recording action=record event=installation firsttime=$_autopackage_support_install rootname=`justRootName "$ROOTNAME"` shortname=$SHORTNAME softwareversion=$SOFTWAREVERSION interfaceversion=$INTERFACEVERSION result=3
				if [[ "$PACKAGEREPORTING" != "No" ]]; then
					echo "action=record&event=installation&firsttime=$_autopackage_support_install&rootname=`justRootName "$ROOTNAME"`&shortname=$SHORTNAME&softwareversion=$SOFTWAREVERSION&interfaceversion=$INTERFACEVERSION&result=3" >> "$WORKING_DIRECTORY/reporting"
				else
					trace PACKAGEREPORTING=$PACKAGEREPORTING so skip recording the event
				fi
				local err=`outn "$intl_PREP_ROOTINSTALLONLY" "$DISPLAYNAME"`
				outputFail "$err"
			else
				# collect result
				trace recording action=record event=installation firsttime=$_autopackage_support_install rootname=`justRootName "$ROOTNAME"` shortname=$SHORTNAME softwareversion=$SOFTWAREVERSION interfaceversion=$INTERFACEVERSION result=1
				if [[ "$PACKAGEREPORTING" != "No" ]]; then
					echo "action=record&event=installation&firsttime=$_autopackage_support_install&rootname=`justRootName "$ROOTNAME"`&shortname=$SHORTNAME&softwareversion=$SOFTWAREVERSION&interfaceversion=$INTERFACEVERSION&result=1" >> "$WORKING_DIRECTORY/reporting"
				else
					trace PACKAGEREPORTING=$PACKAGEREPORTING so skip recording the event
				fi
				local err=`outn "$intl_PREP_ERROR" "$DISPLAYNAME"`
				outputFail "$err"
			fi # assume we output some FAIL message to explain why we didn't prepare correctly

			_installerFinish 0

		) &

	else
		(
			"$_meta_dir/apkg-prep-install-script" # just process the prep scripts here, payloads will be recursed into in the correct order by the first process
			if [[ "$?" == "0" ]]; then
				if ! checkDiskSpace "$EXPANDSIZE" "$PREFIX"; then # recheck disk space
					outputFail "$intl_NO_DISK_SPACE" "$SHORTNAME" "$PREFIX" "$EXPANDSIZE"
				fi
				trace subprep went OK
				exit 0
			elif [[ "$?" == "3" ]]; then
				warn subprep failed on ROOTINSTALLONLY check
				exit 3
			else
				warn subprep failed
				exit 1
			fi
		) &
	fi

	if $boot_frontend; then
		# now start the front end.
		# we do this here so the front end gets hold of stdin/stdout
		unset boot_frontend
		( # run as subshell, so it can exit in the middle of the install
                  # do we still have to do this?
			_launchFE "$autopackage_pipe"
		);
		fe_result=$?;

		trace deleting fifo $autopackage_pipe
		rm -f "$autopackage_pipe"

		exit $fe_result;
	else
		wait $!
		exit $?
	fi
}

##
# _sessionRollback
#
# Process the session log that was generated by the autopackage file
# installation functions. Function requires the variable $_autopackage_session
# that is set in bashlib autopackage logging framework.
function _sessionRollback() {

	out "$intl_SESSION_ROLLBACK"
	trace called with _autopackage_session=$_autopackage_session
	local log

	if [ -e "$_autopackage_session" ]; then
		log=`tac "$_autopackage_session"`
                trace executing: "$log"
		eval "$log"
		return 0
	fi

	err Session rollback failed because it requires the session file $_autopackage_session.
	return 1

}


##
# _loadPackage [OPTIONS] <NAME>
# --user: provides packages that the user can modify
# NAME: SHORTNAME or unversioned ROOTNAME that defines package.
# RETURNS: 0 if successful.<br />1 if not available.
#
# Load package information that matches NAME and makes package
# information available to system.
#
# See also: _loadPackageEnvironment().
#
# Example:
# _loadPackage --user "inkscape"
#
function _loadPackage() {

    trace called with $@
    local p r l

    local user_mode=false
    if [[ "$1" == "--user" ]] && [[ `id -u` != "0" ]]; then
        trace set user mode
        user_mode=true
        shift
    fi

    p=$( autopackage_db_location="$autopackage_user_db_location" _resolveName $1 )
    if [[ "$p" != "" ]]; then
        _loadPackageEnvironment "$autopackage_user_db_location/$p"
        return 0
    fi
    warn "package $1 not found in user database"

    if ! $user_mode; then
        p=$( autopackage_db_location="$autopackage_global_db_location" _resolveName $1 )
        if [[ "$p" != "" ]]; then
            _loadPackageEnvironment "$autopackage_global_db_location/$p"
            return 0
        fi
    fi
    warn "package $1 not found in global database"
    return 1
}

##
# _listPackages
#
# List package information that is available to the user.
function _listPackages() {

    trace called with $@
    local user_mode output_format

    if [[ "$1" == "--user" ]] && [[ `id -u` != "0" ]]; then
        trace set user mode
        user_mode=--user
        shift
    fi

    # preserve newlines to work around broken 1.0 packages that
    # have whitespace at the end of their names
    _listPackagesDB "${user_mode}" | while read; do

    if [[ ${REPLY:0:1} != "/" ]]; then
        warn "root name $REPLY malformed"
        continue
    fi

    _loadPackageEnvironment "$REPLY"
    if [ -n "$AUTOPACKAGE_MANAGER_FORMAT" ]; then
       output_format=`echo "\$PACKAGELOCATION|\$INSTALLSIZE|\$TIMESTAMPINSTALL_LOCAL|\$SHORTNAME"`
    elif [ -n "$AUTOPACKAGE_PACKAGE_LIST_FORMAT" ]; then
       output_format=`eval echo "$AUTOPACKAGE_PACKAGE_LIST_FORMAT"`
    else
       # force output list format
       output_format=`echo "$SHORTNAME: $DISPLAYNAME"`
    fi
    out "$output_format"

    done
    return 0

}

##
# _listPackageFiles <SHORTNAME>
# RETURNS: 0 if successful.<br />1 if error code was returned.
#
# List package installed files from user available database.
function _listPackageFiles() {

    trace called with $@
    local list_filename

    if [[ "$1" == "" ]]; then
        _packageReturnCode "7"
        return "$?"
    fi

    if ! _loadPackage "$1"; then
        _packageReturnCode "1" "$1"
        return "$?"
    fi

    if [ -f "$PACKAGELOCATION/files" ]; then
        list_filename="$PACKAGELOCATION/files"
    else
        _packageReturnCode "1" "$1"
        return "$?"
    fi

    cat "$list_filename" | awk 'BEGIN { FS="  " } { print $1 }' | sort
    return 0

}


##
# _listFilePackage <FILENAME>
# RETURNS: 0 if successful.<br />1 if error code was returned.
#
# List package owner of installed file from user available database.
function _listFilePackage() {

    trace called with $@

    if [[ "$1" == "" ]]; then
        # add a message about a required argument which we do not have
        _packageReturnCode "7"
        return "$?"
    fi

    local p r
    local filename="$1"

    if [[ ${filename:0:1} != "/" ]]; then
        filename="`pwd`/${filename}"
    fi
    trace filename=$filename

    for p in `_listPackagesDB`; do
        _loadPackageEnvironment "$p"
        r=`_listPackageFiles "$SHORTNAME" | grep -c "$filename"`
        if (( r > 0 )); then
            echo "$SHORTNAME"
            return 0
        fi
    done
    return 1

}

##
# _listPackageLog <SHORTNAME>
# RETURNS: 0 if successful.<br />1 if error code was returned.
#
# List package log from user available database.
function _listPackageLog() {

    trace called with $@
    local log_filename
    local log_text
    local uninstall_filename
    local output

    if [[ "$1" == "" ]]; then
        _packageReturnCode "7"
        return "$?"
    fi

    if ! _loadPackage "$1"; then
        _packageReturnCode "1" "$1"
        return "$?"
    fi

    if [ -f "$PACKAGELOCATION/uninstall" ] && [ -f "$PACKAGELOCATION/log" ]; then
        uninstall_filename="$PACKAGELOCATION/uninstall"
        log_filename="$PACKAGELOCATION/log"
    elif [ -f "$PACKAGELOCATION/uninstall" ] || [ -f "$PACKAGELOCATION/log" ]; then
        _packageReturnCode "4" "$1"
        return "$?"
    else
        _packageReturnCode "1" "$1"
        return "$?"
    fi

    log_text=`<"$log_filename"`

    while read; do
        line=`echo "$REPLY"`
        match=`echo "$line" | grep -e "^uninstallFromLog"`
        if [[ "$match" != "" ]]; then
            if [[ "$output" != "" ]]; then
                output=`echo "$output"; echo "$log_text";`
            else
                output=`echo "$log_text";`
            fi
        elif [[ "$line" != "" ]] ; then
            if [[ "$output" != "" ]]; then
                output=`echo "$output"; echo "$line";`
            else
                output=`echo "$line";`
            fi
        fi
    done <"$uninstall_filename"
    output=`stripComments "$output"`
    output=`stripBlankLines "$output"`
    echo "$output"
    return 0

}


# Used in backend.template to clean files on exit.
function __cleanup_backend() {
	trace called
	terminateFE
	[ -e "$apkg_logfile" ]  && rm -f "$apkg_logfile"
	[ -e "$apkg_filelist" ] && rm -f "$apkg_filelist"
	[ -e "$apkg_uninstalldirs" ] && rm -f "$apkg_uninstalldirs"
}


### START DOWNLOADAUTOPACKAGEINFO
### Function is substituted from apkg-funclib.
function _downloadAutopackageInfo() {
	cat <<EOF

The installation of this software requires some additional support
code to be installed.

A] If the support code is found in a local directory, it will be used.
   The file containing the support code will be called:

      "autopackage.tar.bz2"

 or

B] If there is an active Internet connection, the support code will be
   downloaded from:

      "http://autopackage.org/downloads/latest/autopackage.tar.bz2"

   Proxy users should ensure the http_proxy environment variable is
   set, otherwise the download may fail.


EOF
}
### END DOWNLOADAUTOPACKAGEINFO


# Used in downloader.template to close terminal window.
### START FINISHWINDOW
### Function is substituted from apkg-funclib.
function _finishWindow() {
	if [[ "$usingX" == "yes" ]]; then
		echo
		echo Press Enter to close this window.
		read junk;
	fi
}
### END FINISHWINDOW


##
# setVariables <KEY> <VALUE> ...
#
# Save package variables into the environment files which will make the variables
# available for prep, install, and uninstall functions.
#
# Example: setVariables "Test" "false"
function setVariables() {
	while [ $# -gt 0 ]
	do

		# go through language list and add variables to each package environment file
		for language in $PACKAGELANGUAGES; do
			echo "export $1=\"$2\"" >> "$_meta_dir/environment.${language}"
		done
		shift 2
	done
}


##
# _checkFile [OPTIONS] <FILENAME>
# FILENAME: file to check information from.
# --perms: permission block of file.
# --links: links to file.
# --uid: user id of file.
# --gid: groud id of file.
# --mtime: last modified time in seconds of file.
# --name: name of file.
# --md5: generated MD5 checksum of file.
# --all: process all availible checks.
#
# Method will do defined checks on FILENAME in the baseline file.
#
# Example:
#   _checkFile --uid --gid --md5 "/lib/libfoo.so.1.1.2"
#   _checkFile --all "/lib/libfoo.so.1.1.2"
#
function _checkFile() {

    local baseline_info
    local file_info
    local file
    local count

    # grab last argument
    declare -a args
    args=("$@")
    count=${#args[@]}

    # last argument is the filename
    b="${count}"
    file=`echo "${!b}"`

    # check for existance
    if [ ! -e "$file" ]; then
        err "File $file does not exist."
        return 1
    fi

    trace checking \"$file\"

    # decrement count and use it to parse over arguments
    (( count-- ))
    i=0
    while (( "$i" < count )); do

        case "$1" in

            "--perms" )
                        file_info=`getFile --perms "$file"`
                        baseline_info=`getBaseline --perms "$file"`
                        ;;

            "--uid" )
                        file_info=`getFile --uid "$file"`
                        baseline_info=`getBaseline --uid "$file"`
                        ;;

            "--gid" )
                        file_info=`getFile --gid "$file"`
                        baseline_info=`getBaseline --gid "$file"`
                        ;;

            "--size" )
                        file_info=`getFile --size "$file"`
                        baseline_info=`getBaseline --size "$file"`
                        ;;

            "--mtime" )
                        file_info=`getFile --mtime "$file"`
                        baseline_info=`getBaseline --mtime "$file"`
                        ;;

            "--md5" )
                        file_info=`getFile --md5 "$file"`
                        baseline_info=`getBaseline --md5 "$file"`
                        ;;

            "--all" )
                        # recurse to run all tests
                        #_checkFile --perms --uid --gid --size --md5 "$file"
                        _checkFile --md5 "$file"
                        # set values to pass the check outside the case
                        file_info="1"
                        baseline_info="1"
                        ;;

            "*" )
                        ;;

        esac

        (( i++ ))

        if [[ "$file_info" == "$baseline_info" ]]; then
            shift
        else
            err validation failure running \"$1\" on \"$file\"
	    err \"$file_info\" does not match \"$baseline_info\"
            return 1
        fi

    done

    return 0

}


##
# _checkBaselineFiles [OPTIONS]
# --perms: permission block of file.
# --links: links to file.
# --uid: user id of file.
# --gid: groud id of file.
# --mtime: last modified time in seconds of file.
# --md5: generated MD5 checksum of file.
# --all: process all availible checks.
#
# Method will parse and do defined checks on every entry in the baseline file.
#
# See also: _checkFile().
#
# Example:
#   _checkBaselineFiles --uid --gid --md5
#   _checkBaselineFiles --all
#
function _checkBaselineFiles() {

    local file
    local line

    while read; do
        line=`echo "$REPLY"`
        file=`echo "$line" | awk '{ print $6 }'`
        if [ -e "$file" ]; then
            _checkFile "$@" "$file"
            local r="$?"
            if [[ "$r" == "0" ]]; then
                continue
            else
                err running \"$1\" on \"$file\"
                return "$r"
            fi
        else
            err "File does not exist $file"
            return 1
        fi
    done <"$autopackage_db_location/$ROOTNAME/baseline"

}

function _xmlSoftwareEntry() {

    trace called with $1 $2 $3

    local output
    local outfile="$1"
    local filename="$2"
    local xml_uri="$3"
    local language

    local xml_uri xml_md5sum xml_size xml_builddate xml_rootname

    [ ! -f "$filename" ] && err "$filename does not exist."

    xml_md5sum=`getFile --md5 "$filename"`
    trace xml_md5sum=$xml_md5sum

    xml_size=`getFile --size "$filename"`
    trace xml_size=$xml_size

    xml_builddate=`echo "$TIMESTAMPBUILD" | cut -c -10`
    trace xml_builddate=$xml_builddate

    xml_rootname=`justRootName "$ROOTNAME"`
    trace xml_rootname=$xml_rootname

    XML_SOFTWARE_ENTRY_1="	<program-info id=\"${xml_rootname}\">"

    XML_SOFTWARE_ENTRY_2="

	</program-info>

	<software version=\"${SOFTWAREVERSION}\">
		<date>${xml_builddate}</date>
		<interface version=\"${INTERFACEVERSION}\" />
		<keyword>UNSTABLE</keyword>"

    xml_uri=`echo "$xml_uri" | sed 's/ /%20/g'`
    XML_SOFTWARE_ENTRY_3="

		<package type=\"autopackage\"
		         version=\"${PACKAGEVERSION}\"
		         size=\"${xml_size}\"
		         md5=\"${xml_md5sum}\">
			${xml_uri}
		</package>
	</software>
"

    unset XML_SOFTWARE_ENTRY_1_2
    unset XML_SOFTWARE_ENTRY_2_3

    # set just for en language ... need to get luau to handle multiple languages with lang:<language> arguments
    local PACKAGELANGUAGES="en"

    for language in $PACKAGELANGUAGES; do

	# source package environment file
	source "$metadata_dir/apkg-environment.${language}"

		# convert some data for xml presentation - need a more complete routine for all package data
		PACKAGER=`echo "$PACKAGER" | sed 's/</\&lt;/g; s/>/\&gt;/g'`
		MAINTAINER=`echo "$MAINTAINER" | sed 's/</\&lt;/g; s/>/\&gt;/g'`

		XML_SOFTWARE_ENTRY_1_2=`echo "$XML_SOFTWARE_ENTRY_1_2"; echo "
		<shortname>${SHORTNAME}</shortname>
		<fullname>${DISPLAYNAME}</fullname>
		<desc>${SUMMARY}</desc>
		<url>${URL}</url>

"`
		XML_SOFTWARE_ENTRY_2_3=`echo "$XML_SOFTWARE_ENTRY_2_3"; echo "
		<short>Short declarative statement(s) about release for language ${language}.</short>
		<long>
			Paragraphs describing the release for language ${language}.
		</long>

"`

    done

    XML_SOFTWARE_ENTRY="$XML_SOFTWARE_ENTRY_1 $XML_SOFTWARE_ENTRY_1_2 $XML_SOFTWARE_ENTRY_2 $XML_SOFTWARE_ENTRY_2_3 $XML_SOFTWARE_ENTRY_3"
    echo "$XML_SOFTWARE_ENTRY"

}


function _searchPackage() {

    # download and install latest package from a matching project's luau repository file
    # only download and install package if the query matches the shortname otherwise
    # any other hits on the search will be displayed

    # determine user mode
    if [[ "$1" == "--user" ]]; then
        user_mode="--user"
        shift
    fi

    if [ -z "$1" ]; then
        _packageReturnCode "7"
        exit "$?";
    elif _loadPackage "$1"; then
        out "Package '$DISPLAYNAME $SOFTWAREVERSION ($SHORTNAME)' is installed.\nUse 'package update $SHORTNAME' to update software."
        _installerFinish 1
    fi

    if ! locateCommand wget; then
        out "Unable to locate the program 'wget'."
        exit 1
    fi

    trace calling "$lc_location" $autopackage_wget_options --output-document=- --output-file="/dev/null" --post-data="query=${1}" http://autopackage.org/packages/search.php
    local listing=`"$lc_location" $autopackage_wget_options --output-document=- --output-file="/dev/null" --post-data="query=${1}" http://autopackage.org/packages/search.php`
    trace listing=$listing

    local listing_count=`stripBlankLines "$listing" | wc -l`

    trace listing_count=$listing_count

    if [ "$listing_count" -eq 1 ]; then
            LINE=`echo "$listing"`

            s_short_name=`echo "$LINE" | awk 'BEGIN { FS="|" } { print $1 }'`
            s_root_name=`echo "$LINE" | awk 'BEGIN { FS="|" } { print $2 }'`
            s_current_version=`echo "$LINE" | awk 'BEGIN { FS="|" } { print $3 }'`
            s_display_name=`echo "$LINE" | awk 'BEGIN { FS="|" } { print $4 }'`
            s_url_repository=`echo "$LINE" | awk 'BEGIN { FS="|" } { print $5 }'`

    fi

    if [ "$listing_count" -eq 1 ] && [[ "$1" == "$s_short_name" ]]; then

        # repository is required to be '.xml' extensioned
        if [ -n "$s_url_repository" ] && echo "$s_url_repository" | grep -qi '\.xml$'; then


            # # should not be doing this here
            # export _autopackage_execute_package=1

            # need to check/fix/update and refactor with retrieve function as this should work

            # # could add to the retrieve api for search/update scenario but
            # # the following does work except for the exported var above
            # registerRepository "$s_root_name" "$s_url_repository"
            # retrieve --install "$s_root_name:$s_current_version"
            # _installerFinish


            locateCommand luau-downloader
            local before=$( date +%s ) # gnu extension

            trace "$lc_location" -P "/dev/zero" -u "$s_url_repository" -o "$WORKING_DIRECTORY/payload"
            if ! "$lc_location" -P "/dev/zero" -u "$s_url_repository" -o "$WORKING_DIRECTORY/payload"; then
                outputFail "Download of package for $1 failed - check your internet connection?"
                return 1
            fi

            local after=$( date +%s )
            trace $[ after - before ] seconds to download package

            # Verify that this really is an Autopackage
            if ! head -n 3 "$WORKING_DIRECTORY/payload" | grep --text -q '# autopackage '; then
                continue
            fi

            if [ -f "$WORKING_DIRECTORY/payload" ]; then
                chmod +x "$WORKING_DIRECTORY/payload"
                mv "$WORKING_DIRECTORY/payload" "$WORKING_DIRECTORY/$s_short_name-$s_current_version.package"
                package install "$WORKING_DIRECTORY/$s_short_name-$s_current_version.package"
                return 0
            else
                # repository file led to no package file or repository file was not present
                return 1
            fi

        else

            out "Found: $s_display_name $s_current_version ($s_short_name)\nbut there no xml repository installation information available."
            _installerFinish

        fi

    fi

    if [ "$listing_count" -gt 0 ]; then
        echo "$listing" | while read; do
            LINE="$REPLY"

            s_short_name=`echo "$LINE" | awk 'BEGIN { FS="|" } { print $1 }'`
            s_root_name=`echo "$LINE" | awk 'BEGIN { FS="|" } { print $2 }'`
            s_current_version=`echo "$LINE" | awk 'BEGIN { FS="|" } { print $3 }'`
            s_display_name=`echo "$LINE" | awk 'BEGIN { FS="|" } { print $4 }'`
            s_url_repository=`echo "$LINE" | awk 'BEGIN { FS="|" } { print $5 }'`

            out "$s_display_name $s_current_version ($s_short_name)"

        done
        _installerFinish

    else

        out "There are no packages that match your search."
        _installerFinish
        exit "1"

    fi
}


##
# _getPackageHeader filename
#
# Returns the public header of the package filename.
function _getPackageHeader() {

    trace called with $1
    local header

    if [ ! -f "$1" ]; then
        err "file \"$1\" does not exist"
        return 1
    fi

    local oIFS="$IFS"
    IFS=$'\n'

    # Extract package header
    # head thinks a package is a binary file so read and collect the header
    # use 'export working_dir=""' as a marker for 1.0 - 1.0.2 packages
    while read; do
        if [[ "$REPLY" == "## END OF HEADER" ]] || [[ "$REPLY" == "export working_dir=\"\"" ]]; then
            break
        else
            header=`echo "$header";echo "$REPLY"`
        fi
    done <"$1"

    IFS="$oIFS"

    echo "$header"
    return 0

}


## START CHECKEULA
## Function is substituted from apkg-funclib.
function _checkEULA() {

    if [[ `id -u` == "0" ]] && [ -n "$EULAFILENAME" ] && [ "$EULADISPLAY" == "Installation" ] && [ ! -f "$AUTOPACKAGE_CONFIG_DIR/eulas/$SHORTNAME-$SOFTWAREVERSION-$PACKAGEVERSION" ] && [ ! -f "$_meta_dir/apkg-eula-$SHORTNAME" ]; then
        trace checking for eula
        if ! _displayEULA; then
            return 1
        else
            # add marker file of approval
            # environment area is not setup for logging so write to interim marker file such that
            # when environment files are copied in apkg-db _createDBEntry() the eula marker is created
            trace adding end user license agreement interim marker file
            copyFile --silent --nobackup --nolog "$_meta_dir/eula/$EULAFILENAME" "$_meta_dir/apkg-eula-$SHORTNAME"
        fi
    elif [ -n "$EULAFILENAME" ] && [ "$EULADISPLAY" == "Installation" ] && [ ! -f "$AUTOPACKAGE_CONFIG_HOME/eulas/$SHORTNAME-$SOFTWAREVERSION-$PACKAGEVERSION" ] && [ ! -f "$_meta_dir/apkg-eula-$SHORTNAME" ]; then
        trace checking for eula
        if ! _displayEULA; then
            return 1
        else
            # add marker file of approval
            # environment area is not setup for logging so write to interim marker file such that
            # when environment files are copied in apkg-db _createDBEntry() the eula marker is created
            trace adding end user license agreement interim marker file
            copyFile --silent --nobackup --nolog "$_meta_dir/eula/$EULAFILENAME" "$_meta_dir/apkg-eula-$SHORTNAME"
        fi
    fi
    return 0

}
## END CHECKEULA


## START DISPLAYEULA
## Function is substituted from apkg-funclib.
function _displayEULA() {

    trace called
    local dialog

    # if filename is not available return error
    if [ ! -f "$_meta_dir/eula/$EULAFILENAME" ]; then
        out "File: $_meta_dir/eula/$EULAFILENAME not found."
        return 1
    fi

    # determine if automatically acceptance
    if ! $autopackage_suppress_eula; then
        trace automatically accepting end user license agreement
        return 0
    fi

    # determine which desktop environment is running and set display application

    # kde running
    if pidof -x kdeinit >/dev/null; then
        dialog="$_meta_dir/eula/display-eula-qt"
        dialog_mode="--eula"

    # gnome running with gtk2
    elif pidof -x gnome-panel >/dev/null && testForLib libgtk-x11-2.0.so; then
        dialog="$_meta_dir/eula/display-eula-gtk2"
        dialog_mode="--eula"

    # # gnome running with gtk1
    # elif pidof -x gnome-panel >/dev/null && testForLib libgtk-x11-1.0.so; then
    #     dialog="$_meta_dir/eula/display-eula-gtk1"

    fi

    # execute dialog application for user approval or disapproval
    if "$dialog" "$dialog_mode" "$_meta_dir/eula/$EULAFILENAME"; then
        trace eula approved
        return 0
    else
        trace eula disapproved
        return 1
    fi

}
## END DISPLAYEULA


