#!/bin/bash

# ------------------------------------------------------------
#	autopackage creator program
# ------------------------------------------------------------

###
#
# 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),
# Hongli Lai (hongli@plan99.net) and others.
#


# Some important variables:
# $metadata_dir
# $payload_dir
#	These variables refer to the metadata and payload directories
#	of the package that's currently being created.

# Output a sample specfile if --mkspec is given.
if [[ "$1" == "--mkspec" ]]; then
	cat <<EOF
# -*-shell-script-*-

#
# This is an example specfile. Delete these comments when you're done.
#

[Meta]
RootName: @mysite.org/myproject:\$SOFTWAREVERSION
DisplayName: MyProject Strategy Game
ShortName: myproject
Maintainer: John Smith <smith@mysite.org>
Packager: John Smith <smith@mysite.org>
Summary: MyProject is an example
URL: http://www.mysite.org/
License: GNU General Public License, Version 2
SoftwareVersion: 1.0
# SoftwareVersion: @VERSION@
Repository: http://www.mysite.org/downloads/myproject.xml

# If you change the autopackage but not the software itself,
# increment this number.

# PackageVersion: 2

# This is the version of the autopackage runtime this package is
# written for. Increasing this number implies you have read the
# "Migrating to 1.X" document and understand the impact it will have
# on your package. Some APIs may change their behaviour and new
# features will be enabled depending on what this is set to.
AutopackageTarget: 1.4

# Only uncomment InterfaceVersion if your package exposes interfaces
# to other software, for instance if it includes DSOs or python/perl
# modules. See the developer guide for more info, or ask on
# autopackage-dev if you aren't sure about interface versioning.
#
# InterfaceVersion: 0.0

[BuildPrepare]
# For ./configure based systems this is a good default
prepareBuild --with-some-feature

[BuildUnprepare]
unprepareBuild

[Globals]
# Anything put here will be run during makeinstall and at
# install/uninstall time. Define useful variables here:

# export MY_VAR=1

[Imports]
# You may wish to delete some things first, eg libtool .la files or
# development files (headers)

# rm -r include
# rm libs/*.la

# This imports every file in $build_root
# (ie, that is installed by "make install")
echo '*' | import


[Prepare]
# Dependency checking

# You can use "require" and "recommend". They both try to find the
# given dependency, and install it if missing. But require will return
# 1 (causing failure) if it can't do that whereas recommend will
# simply show a notice at the end of the install.

# The second argument here identifies a skeleton file, which is
# a file that encapsulates a dependency check. The second number
# identifies the interface version you need. Use as many of these
# as you need.

require @whatever.you/need 1.0

# The user may have already installed the program from an RPM.
# Let's try and uninstall it first. We only need one call if 3rd party
# packages have split the program up into multiple packages.

removeOwningPackage \$PREFIX/bin/my-program

[Install]
# Put your installation script here. See the quickstart guide on
# the website for an API cheat-sheet
installExe bin/*

[Uninstall]
# Usually just the following line is enough to uninstall everything
uninstallFromLog
EOF
	exit
fi


# 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

[ -e "`dirname \"$0\"`/etc/config-not-installed" ] && source "`dirname \"$0\"`/etc/config-not-installed"

_apspec_dir="`pwd`/autopackage"

if [[ "$autopackage_prefix" != "" ]]; then
	pushd "$autopackage_share" >/dev/null
	source "apkg-funclib"
	popd >/dev/null
else
	# link to autopackage functions and environment
	# sideload by changing into dir to source files within that directory
	pushd "$autopackage_share" >/dev/null
	source "../etc/config"
	source "apkg-funclib"
	popd >/dev/null

	# check and install SVN directory apbuild
	_installApbuild -q
fi

myname=`basename "$0"`
mydir=`dirname "$0"`
mydir=`cd "$mydir"; pwd`
alias makepackage="$mydir/$myname"
unset myname
unset mydir

apkg_logfile="/dev/null"
apkg_filelist="/dev/null"

# initialize variables
_initializeAutopackage

checkConfigVersion || exit 1;

# error codes
ERROR_NO_STUB=1;
ERROR_NO_INSTALLER=2;
ERROR_NO_DOWNLOADER=3;
ERROR_MISSING_SKELETON=5;
ERROR_SKELETON_API_MISMATCH=6;

###############################################################
## start here

# check for command line arguments
while getopts ":hcms" Option
do
	case $Option in
		c )
			export APKG_BUILD_SKIP_CONFIGURE=1
			;;
		m )
			export APKG_BUILD_SKIP_MAKE=1
			;;

        s )
            export APKG_NO_STRIP=1
            ;;

		h | * ) # output help text and unknown cases
			echo
			out "autopackage installer builder
Usage from source directory root:
    makepackage [--mkspec] | ['apspec-filename1' 'apspec-filename2' ... ]

If --mkspec is given, makepackage will print a sample specfile to standard
output. You can use this as a starting point for writing a new specfile.

If --mkspec is not given, makepackage will create a new .package based
on the given specfiles. If no specfile filename is declared then
spec filename autopackage/default.apspec will be used.

The script will create a software package that will
be written to the file specified in the spec file.

Options:
   -c     Do not run './configure' when building this package
          (only useful if you use prepareBuild)
   -m     Do not run 'make' when building this package
          (only useful if you use prepareBuild)
   -s     Do not strip ELF binaries
          (useful if you want to send a debug build to somebody)
   -h     Show this help screen"
			echo
			exit 0;;
	esac
done
shift $(($OPTIND - 1))

# This function uses xsltproc to transform XDG spec mime-type files
# into the KDE 3.x equivalents. Symlinks are created so that installMime
# can automatically install both the XDG and KDE mime-types.
# XML files must be located located in $build_root/share/mime/packages, otherwise
# broken symlinks will be constructed (links are made relative to share/mime/packages).
# NOTE: Private function, do not use in specfiles.

function generateLegacyMime() {
    outn "Converting XDG MIME type definitions to KDE 3.x equivalents ... "
    if locateCommand xsltproc; then
        # deal with KDE mime-types

        mkdir -p "$payload_dir/share/mimelnk"
        pushd "$payload_dir/share/mimelnk" > /dev/null
        for mimefile in "$@"; do
            if ! grep -q "http://www.freedesktop.org/standards/shared-mime-info" "$mimefile"; then
                red; outn "WARNING: "; normal; out "The FreeDesktop.org MIME Type file `basename "$mimefile"` does not appear to have a namespace declaration. KDE 3.x MIME Type files will not be generated."
            fi

            local i=0 # counts number of .desktop files created from a single XML file (for symlinks--hello.xml.1)
            for mimetype in $( $lc_location $autopackage_share/apkg-mimetype.xsl $mimefile ); do
                let i+=1
                # this command is run from share/mimelnk (so xsltproc files land in the right placage)
                # which is why the symlink is constructed from ../../share/mime/packages to share/mimelnk/
                ln -fs "../../../share/mimelnk/$mimetype.desktop" ../../share/mime/packages/`basename $mimefile.$i`
            done
        done
        popd > /dev/null
    else
        err "You need xsltproc installed to process mime-types."
    fi
    green; out "done"; normal
}

function safeRemove()
{
    test -z "$1" -o -z "${TMP}" && return
    # Only remove paths in ${TMP}
    if [[ "$1" == ${TMP}/* ]]; then 
	rm -rf "$1"
    fi
}

function cleanUp()
{
    safeRemove "$payload_dir"
    safeRemove "$metadata_dir"
    safeRemove "$current_directory"
    safeRemove "$_virtual_build_root"
    safeRemove "$__apkg_errors_file"
    unset payload_dir
    unset metadata_dir
    unset build_root
    unset __apkg_errors_file
    # all temporary files are prefixed with apkg-
    rm -fr "${TMP}"/apkg-* 2> /dev/null
    return 0
}

trap cleanUp EXIT

# Process a specfile
function process()
{
	# **********************************************************
	#  Process for building a .package file
	#
	#  1. Setup environment variables and perform sanity checks
	#
	#  2. Parse package metadata from Meta section of specfile
	#
	#  3. Load template files and substitute values
	#
	#  4. Generate build_root and run BuildPrepare
	#
	#  5. Import files into package
	#
	#  6. Create script files in meta directory
	#
	#  7. Start creating the package file
	#
	#  8. Generate package output files depending on type
	# **********************************************************


	# **********************************************************
	#  1. Setup environment variables and sanity checks
	# **********************************************************
	local specfile="$1"
	# The working directory from which makepackage is invoked;
	# usually the directory containing the source code.
	export source_dir
	# The main data payload directory
	payload_dir="${TMP}/apkg-payload-dir$$-$RANDOM"
	# The metadata payload directory
	export metadata_dir="${TMP}/apkg-meta$RANDOM$$"

	# The compiled files get copied to this dir. The extraction script
	# will copy files from this dir to $payload_dir
	export build_root="."

	# The apspec directory to search for skeleton files which is used in
	# _locateSkeleton function from apkg-dep.
	local __apkg_errors_file
	local oIFS
	local language

	local f
	local l

	# Is this specfile generated from a .apspec.in template? If so,
	# check if .apspec.in is newer than .apspec, and if yes regen
	if [[ -e config.status && -e "${specfile}.in" ]]; then
	    ./config.status --file="$specfile"
	    local exitCode=$?

	    if [ $exitCode != 0 ]; then
		return $exitCode
	    fi
	fi

	if [ ! -e "$specfile" ]; then
		red; outn "FAIL: "; normal;
		out "$specfile could not be found"
		return 1
	fi

	if file "$specfile" | grep -q CRLF; then
		red; outn "ERROR: "; normal; out "Specfile %s contains Windows line terminators (CRLF) and is therefore not compatible with makepackage." "$specfile"
		if yesNo "Should makepackage fix this for you? (Y/n)"; then
			sed 's/\r$//' -i "$specfile"
		else
			return 1
		fi
	fi

	# Ensure we have an absolute path
	source_dir=`pwd`;
	if [[ ${specfile:0:1} != "/" ]]; then
	    # Get absolute filename of specfile if it isn't an absolute filename already
	    specfile="$source_dir/$specfile"
	fi

	mkdir -p "$payload_dir"
	chmod 700 "$payload_dir"

	# Check the specfile exists
	if [ ! -e "$specfile" ]; then
		red; out "$specfile could not be found"; normal;
		return 1
	fi


	drawHeaderBlue "Building installer for %s" "$specfile"

	# **********************************************************
	#  2. Parse package metadata from Meta section of specfile
	# **********************************************************

	# **********************************************************
	#  2.1 Load specfile meta data
	# **********************************************************
	local meta meta_localized meta_matched
	meta=`getSection "$specfile" Meta`
	meta=`stripComments "$meta"`
	# **********************************************************
	#  2.2 Convert Meta section keys to variables
	# **********************************************************
	trace processing Meta section keys to variables
	trace "$meta"
	if [[ "$meta" != "" ]]; then
		function subup()
		{
			# grab non-localized keys to start
			if (( `echo "$meta_localized" | grep -i "^$1:" | wc -l` > 1 )); then
				err "Key $1 is duplicated, ignoring all but first"
			fi

			local line=`echo "$meta_localized" | grep -i "^$1:" | head -n 1`
			local start=`echo "$line" | awk 'BEGIN { FS=": " } { print $1 }' | sed 's/@/\_\_at\_\_/g'`
			local value=`echo "$line" | awk 'BEGIN { FS=": " } { print $2 }'`
			# continue if the specKey is found in the Meta section keys
			if [[ "$start" != "" ]]; then
				# translate key to CAPITALS
				local up=$( echo "$start" | tr 'a-z' 'A-Z' )
				# write CAPITAL case key new meta variable which only allows specified specKeys
				trace substituting meta key $start to be $up
				meta_matched=$( echo "$meta_matched"; echo "${up}=\"${value}" );
				# process localized keys
				oIFS="$IFS"
				IFS=$'\n'
				for line in `echo "$meta_localized" | grep -i "^${start}\["`; do
					line=$( echo "$line" | sed "s/^${start}\[/${up}_/g" );
					meta_matched=$( echo "$meta_matched"; echo "${line}" );
				done
				IFS="$oIFS"
			fi
		}

		# copy meta data to new variable
		meta_localized=`echo "$meta"`

		# converting Meta section keys to environment variables changes
		# the meta data between the listed formats and subup translates
		# the specKeys to be CAPITALS.
		# DisplayName: <data>		--->	DISPLAYNAME="<data>"
		# DisplayName[fr]: <data>	--->	DISPLAYNAME_fr="<data>"
		# Summary: <data>	    	--->	SUMMARY="<data>"
		# Summary[fr]: <data>		--->	SUMMARY_fr="<data>"
		# Summary[fr@Latn]: <data>	---->	SUMMARY_fr__at__Latn="<data>"
		#
		# allow ':' to be used in Meta data, need to focus on the first instance of ':'
		# first instance can be determined on localized keys because of the ']: ' so substitute in '='
		# and non-localized keys are converted to variables in subup function
		meta_localized=`echo "$meta_localized" | sed 's/\]: /\=\"/g'`
		meta_localized=`echo "$meta_localized" | sed 's/\(.\)$/\1"/g'`

		for state in $specKeys; do
			subup "${state}"
		done

		unset subup meta_localized
	fi

	# Unset specfile meta keys
	_resetKeys

	# Evaluate Meta section key
	trace evaluating Meta section key variables
	trace "$meta_matched"
	# evaluate to define values
	eval "$meta_matched" >/dev/null
	# allow any values to be substituted
	eval "$meta_matched" >/dev/null

	# **********************************************************
	#  2.3 Meta Sanity checks
	# **********************************************************
	if [[ "$DISPLAYNAME" == "" && "$PACKAGEDESKTOP" == "" ]]; then red; outn "FAIL: "; normal; out "No DisplayName key found in the [Meta] section. You need one"; cleanUp; return 1; fi
	if [[ "$SHORTNAME" == "" ]]; then red; outn "FAIL: "; normal; out "No ShortName key found in the [Meta] section."; cleanUp; return 1; fi
	if [[ "$ROOTNAME" == "" ]]; then red; outn "FAIL: "; normal; out "You forgot the RootName key in the [Meta] section. That's pretty important you know "; cleanUp; return 1; fi
	if [[ "$SOFTWAREVERSION" == "" ]]; then red; outn "FAIL: "; normal; out "No SoftwareVersion key found in the [Meta] section, please add one"; cleanUp; return 1; fi
	if [[ "$PACKAGEVERSION" != "" ]] && ! isInteger "$PACKAGEVERSION"; then red; outn "FAIL: "; normal; out "A valid PackageVersion key was not found in the [Meta] section. PackageVersion is an integer greater than 0."; cleanUp; return 1; fi
	if [[ "$UPDATEFOR" != "" && "$AUTOPACKAGETARGET" < "1.4" ]]; then red; outn "FAIL "; normal; out "You need to set AutopackageTarget to at least 1.4 to use UpdateFor."; cleanUp; return 1; fi

	trace ROOTNAME=$ROOTNAME
	trace SHORTNAME=$SHORTNAME
	trace SOFTWAREVERSION=$SOFTWAREVERSION
	trace INTERFACEVERSION=$INTERFACEVERSION
	trace DISPLAYNAME=$DISPLAYNAME
	trace AUTOPACKAGETARGET=$AUTOPACKAGETARGET

	# follow-up error checks on ROOTNAME
	unset _rootname_match
	# should be a leading @
	if [ -z "$_rootname_match" ]; then
		_rootname_match=$( expr index "$ROOTNAME" "@" )
		if ! (( _rootname_match == 1 )); then
			_rootname_match="no leading @"
		else
			unset _rootname_match
		fi
	fi
	# should be no spaces
	if [ -z "$_rootname_match" ]; then
		_rootname_match=$( expr index "$ROOTNAME" " " )
		if (( _rootname_match > 0 )); then
			_rootname_match="spaces"
		else
			unset _rootname_match
		fi
	fi
	# catch protocols
	if [ -z "$_rootname_match" ]; then
		_rootname_match=$( echo "$ROOTNAME" | grep 'http://' )
		[ -n "$_rootname_match" ] && _rootname_match="http://"
	fi
	if [ -z "$_rootname_match" ]; then
		_rootname_match=$( echo "$ROOTNAME" | grep 'https://' )
		[ -n "$_rootname_match" ] && _rootname_match="https://"
	fi
	if [ -z "$_rootname_match" ]; then
		_rootname_match=$( echo "$ROOTNAME" | grep 'ftp://' )
		[ -n "$_rootname_match" ] && _rootname_match="ftp://"
	fi
	# should be at least one forward slash
	if [ -z "$_rootname_match" ]; then
		_rootname_match=$( expr index "$ROOTNAME" "/" )
		if (( _rootname_match < 1 )); then
			_rootname_match="no secondary description"
		else
			unset _rootname_match
		fi
	fi
	# should be at least one colon
	if [ -z "$_rootname_match" ]; then
		_rootname_match=$( expr index "$ROOTNAME" ":" )
		if (( _rootname_match < 1 )); then
			_rootname_match="no software version"
		else
			unset _rootname_match
		fi
	fi
	# send error if match exists from any of the previous tests
	if [ -n "$_rootname_match" ]; then
		red; outn "ERROR: "; normal; out "Package RootName: '%s' is not correct because of '%s'. Please read Packagers Guide, Creating a package section for RootName guidelines." "$ROOTNAME" "$_rootname_match"
		return 1
	fi

	# follow-up warning checks on ROOTNAME
	# should not have server name be 'www'
	if [ -z "$_rootname_match" ]; then
		_rootname_match=$( echo "$ROOTNAME" | grep "@www" | wc -l )
		if (( _rootname_match > 0 )); then
			_rootname_match="www is not needed"
		else
			unset _rootname_match
		fi
	fi
	if [ -z "$_rootname_match" ]; then
		_rootname_match=$( versionFromRootName "$ROOTNAME" )
		if [[ "$_rootname_match" != "$SOFTWAREVERSION" ]]; then
			_rootname_match="root name version does not match software version"
		else
			unset _rootname_match
		fi
	fi
	# send warning if match exists from any of the previous tests
	if [ -n "$_rootname_match" ]; then
		red; outn "WARNING: "; normal; out "Package RootName: '%s' is not correct because of '%s'. Please read Packagers Guide, Creating a package section for RootName guidelines." "$ROOTNAME" "$_rootname_match"
	fi

	# follow-up checks on SHORTNAME
	unset _shortname_match
	# should be no spaces
	if [ -z "$_shortname_match" ]; then
		_shortname_match=$( expr index "$SHORTNAME" " " )
		if (( _shortname_match > 0 )); then
			_shortname_match="spaces"
		else
			unset _shortname_match
		fi
	fi
	# send error if match exists from any of the previous tests
	if [ -n "$_shortname_match" ]; then
		red; outn "ERROR: "; normal; out "Package ShortName: '%s' is not correct because of '%s'. Please read Packagers Guide, Creating a package section for ShortName guidelines." "$SHORTNAME" "$_shortname_match"
		return 1
	fi


	# **********************************************************
	#  2.4 Set Meta Defaults
	# **********************************************************

	# determine autopackage target api and normalize
	local apkgtarget_major=`getMajor "$AUTOPACKAGETARGET"`
	local apkgtarget_minor=`getMinor "$AUTOPACKAGETARGET"`
	if [ `expr index "$apkgtarget_major" '[abcdefghijklmnopqrstuvwxyz]'` -gt "0" ]; then
		apkgtarget_major="1"
		red; outn "WARNING: "; normal;
		out "No AutopackageTarget found in the specfile, default to '$apkgtarget_major'."
	fi
	if [ `expr index "$apkgtarget_minor" '[abcdefghijklmnopqrstuvwxyz]'` -gt "0" ] || [[ "$apkgtarget_minor" == "" ]]; then
		apkgtarget_minor="0"
	fi
	if [[ "$apkgtarget_major" != "" ]]; then
		AUTOPACKAGETARGET="$apkgtarget_major.$apkgtarget_minor"
	else
		AUTOPACKAGETARGET="1.2"
		red; outn "WARNING: "; normal;
		out "No AutopackageTarget found in the specfile, default to '$AUTOPACKAGETARGET'."
	fi
	trace setting api AUTOPACKAGETARGET=$AUTOPACKAGETARGET

	COMPRESSION=`echo "$COMPRESSION" | tr [:upper:] [:lower:]`
	if [[ "$COMPRESSION" != "" ]] &&
	   [[ "$COMPRESSION" != "bzip2" ]] &&
	   [[ "$COMPRESSION" != "lzma" ]]; then
		err "unknown compression method $COMPRESSION, selecting default"
		COMPRESSION=""
	fi

	if [[ "$COMPRESSION" == "" ]]; then
		if [[ "$AUTOPACKAGETARGET" == "1.0" ]]; then
			COMPRESSION="bzip2"
		else
			COMPRESSION="lzma"
		fi
	fi

	if [[ "$AUTOPACKAGETARGET" == "1.0" ]] && [[ "$COMPRESSION" == "lzma" ]]; then
		err "LZMA compression is not available when targetting the 1.0 runtime, using bzip2."
		COMPRESSION="bzip2"
	fi

	if [[ "$COMPRESSION" == "lzma" ]] && ! locateCommand autopackage-lzma; then
		red; outn "WARNING: "; normal; out "Command 'autopackage-lzma' not found. bzip2 compression will be used instead."
		COMPRESSION="bzip2"
	fi

	if [[ -n $CPUARCHITECTURE ]] && [[ "$AUTOPACKAGETARGET" == "1.4" ]]; then
		red; outn "WARNING: "; normal; out "CPUArchitecture is deprecated. Use CPUArchitectures instead."
	fi

	# determine interface version and normalize
	local interfaceversion_major=`getMajor "$INTERFACEVERSION"`
	local interfaceversion_minor=`getMinor "$INTERFACEVERSION"`
	if [[ -z "$INTERFACEVERSION" ]]; then
		trace defaulting INTERFACEVERSION=0.0
		INTERFACEVERSION="0.0"
	elif [[ "$interfaceversion_minor" == "" ]]; then
		trace normalizing INTERFACEVERSION=$interfaceversion_major.0
		INTERFACEVERSION="$interfaceversion_major.0"
	fi

	if (( PACKAGEVERSION < 1 )); then
		PACKAGEVERSION="1"
	fi

	ROOTINSTALLONLY=`echo "$ROOTINSTALLONLY" | tr [:upper:] [:lower:]`
	if [[ "$ROOTINSTALLONLY" == "yes" ]]; then
		ROOTINSTALLONLY="Yes"
	elif [[ "$ROOTINSTALLONLY" == "no" ]]; then
		ROOTINSTALLONLY="No"
	else
		trace defaulting ROOTINSTALLONLY="No"
		ROOTINSTALLONLY="No"
	fi

	PACKAGEREPORTING=`echo "$PACKAGEREPORTING" | tr [:upper:] [:lower:]`
	if [[ "$PACKAGEREPORTING" == "yes" ]]; then
		PACKAGEREPORTING="Yes"
	elif [[ "$PACKAGEREPORTING" == "no" ]]; then
		PACKAGEREPORTING="No"
	else
		trace defaulting PACKAGEREPORTING="Yes"
		PACKAGEREPORTING="Yes"
	fi

	if [ -z "$REPOSITORYFILENAME" ]; then
		trace defaulting REPOSITORYFILENAME="$SHORTNAME.xml"
		REPOSITORYFILENAME="$SHORTNAME.xml"
	fi

	# gather repository value from skeleton file if a skeleton file exists
	# always use skeleton repository value and warn if meta data also has a value set
	# save repository to environment file if meta data is used
	# set repository directory based on determined repository value
	local m_skelfile=`_locateSkeleton "$ROOTNAME"`
	if [ -n "$m_skelfile" ]; then
		m_repository=`getSectionKey "$m_skelfile" "Meta" "Repository"`
	fi
	local repository_dir=""
	if [ -n "$m_repository" ] && [ -n "$REPOSITORY" ]; then
		if [[ "$m_repository" != "$REPOSITORY" ]]; then
			red; outn "WARNING: "; normal; out "Repository value from skeleton file '$m_skelfile' is being used instead of package meta data '$REPOSITORY'."
		fi
		# skeleton value is going to be used so clear meta data value
		REPOSITORY=""
		repository_dir=`dirname "$m_repository"`
		trace using skeleton repository value $m_repository instead of metadata value
	elif  [ -n "$m_repository" ]; then
		repository_dir=`dirname "$m_repository"`
		trace using skeleton repository value $m_repository
	elif  [ -n "$REPOSITORY" ]; then
		repository_dir=`dirname "$REPOSITORY"`
		trace using meta data repository value $REPOSITORY
	fi
	trace REPOSITORY=$REPOSITORY

	EULADISPLAY=`echo "$EULADISPLAY" | tr [:upper:] [:lower:]`
	if [[ "$EULADISPLAY" == "installation" ]]; then
	    EULADISPLAY="Installation"
# 	elif [[ "$EULADISPLAY" == "execution" ]]; then
# 	    EULADISPLAY="Execution"
# 	elif [[ "$EULADISPLAY" == "both" ]]; then
# 	    EULADISPLAY="Both"
# 	elif [[ "$EULADISPLAY" == "none" ]]; then
# 	    EULADISPLAY="None"
	else
	    trace defaulting EULADISPLAY="None"
	    EULADISPLAY="None"
	fi


	# **********************************************************
	#  3. Load template files and substitute values
	# **********************************************************
	if [[ "$AUTOPACKAGETARGET" == "1.0" ]]; then
		trace loading 1.0 template files
		local stub=`<"$autopackage_share/stub.template"` || { echo "Couldn't load stub.template"; return $ERROR_NO_STUB; }
		local downloader=`<"$autopackage_share/downloader.template"` || { echo "Couldn't load downloader.template"; return $ERROR_NO_DOWNLOADER; }
	elif [[ "$AUTOPACKAGETARGET" < "1.4" ]]; then
		trace loading 1.2 template files
		local stub=`<"$autopackage_share/stub.2.template"` || { echo "Couldn't load stub.2.template"; return $ERROR_NO_STUB; }
		local downloader=`<"$autopackage_share/downloader.2.template"` || { echo "Couldn't load downloader.2.template"; return $ERROR_NO_DOWNLOADER; }
	else
		trace loading 1.4 template files
		local stub=`<"$autopackage_share/stub.4.template"` || { echo "Couldn't load stub.4.template"; return $ERROR_NO_STUB; }
		stub=$(substituteCode "$autopackage_share/apkg-bashlib" "START COMPAREVERSIONS SIMPLE" "END COMPAREVERSIONS SIMPLE" "$stub" "%CompareVersions%")
		stub=$(substituteCode "$autopackage_share/apkg-bashlib" "START MESSAGE" "END MESSAGE" "$stub" "%Message%")
		local downloader=`<"$autopackage_share/downloader.2.template"` || { echo "Couldn't load downloader.2.template"; return $ERROR_NO_DOWNLOADER; }
	fi

	installer=$(_getInstallerTemplate)
	if (($?	!= 0)); then
		echo "Error loading installer template"
		return $ERROR_NO_INSTALLER
	fi
	
	if [[ -z "$autopackage_share/backend.template" ]]; then
		echo "backend.template doesn't exist";
		return $ERROR_NO_BACKEND;
	fi

	downloader=`substituteCode "$autopackage_share/apkg-funclib" "START INSTALLAUTOPACKAGE" "END INSTALLAUTOPACKAGE" "$downloader" "%InstallAutopackage%"`
	downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START YESNO" "END YESNO" "$downloader" "%YesNo%"`
	downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START STARTDOWNLOAD" "END STARTDOWNLOAD" "$downloader" "%StartDownload%"`
	downloader=`substituteCode "$autopackage_share/apkg-funclib" "START DOWNLOADAUTOPACKAGEINFO" "END DOWNLOADAUTOPACKAGEINFO" "$downloader" "%DownloadAutopackageInfo%"`
	downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START DOWNLOADFUNCTION" "END DOWNLOADFUNCTION" "$downloader" "%DownloadFunction%"`
	downloader=`substituteCode "$autopackage_share/apkg-funclib" "START FINISHWINDOW" "END FINISHWINDOW" "$downloader" "%FinishWindow%"`
	downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START LAUNCHINTERMINAL" "END LAUNCHINTERMINAL" "$downloader" "%LaunchInTerminal%"`
	downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START LOCATECOMMAND" "END LOCATECOMMAND" "$downloader" "%LocateCommand%"`
	downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START MESSAGE" "END MESSAGE" "$downloader" "%Message%"`
	downloader=`substituteCode "$autopackage_share/apkg-funclib" "START AUTOSUCOMMAND" "END AUTOSUCOMMAND" "$downloader" "%AutosuCommand%"`
	downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START PUSHOPTE" "END PUSHOPTE" "$downloader" "%PushOptE%"`
	downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START POPOPTE" "END POPOPTE" "$downloader" "%PopOptE%"`
	downloader=`substituteCode "$autopackage_share/apkg-bashlib" "START RESOLVELINK" "END RESOLVELINK" "$downloader" "%ResolveLink%"`
	downloader=`substituteCode "$autopackage_share/apkg-script-utils" "START SCANLDLIBPATH" "END SCANLDLIBPATH" "$downloader" "%ScanLDLibPath%"`
	downloader=`substituteCode "$autopackage_share/apkg-script-utils" "START GETLIBRARYPATHS" "END GETLIBRARYPATHS" "$downloader" "%GetLibraryPaths%"`
	downloader=`substituteCode "$autopackage_share/apkg-script-utils" "START TESTFORLIB" "END TESTFORLIB" "$downloader" "%TestForLib%"`
	downloader=`substituteCode "$autopackage_share/apkg-script-utils" "START ISLIBRARY32" "END ISLIBRARY32" "$downloader" "%IsLibrary32%"`
	trace loaded

	###### Substitute values into templates

	# Sets _payload_dir and _meta_dir before package expansion; used by _retrieveLocalPackage
	stub=$( echo "$stub" | replaceStr "%AutopackageVersion%" "$autopackage_version" )
	stub=$( echo "$stub" | replaceStr "%RootName%" "$ROOTNAME" )
	stub=$( echo "$stub" | replaceStr "%ShortName%" "$SHORTNAME" )
	stub=$( echo "$stub" | replaceStr "%SoftwareVersion%" "$SOFTWAREVERSION" )
	stub=$( echo "$stub" | replaceStr "%InterfaceVersion%" "$INTERFACEVERSION" )
	stub=$( echo "$stub" | replaceStr "%PackageVersion%" "$PACKAGEVERSION" )
	stub=$( echo "$stub" | replaceStr "%CPUArchitecture%" "x86" ) # Pre 1.4 packages only support x86
	stub=$( echo "$stub" | replaceStr "%AutopackageTarget%" "$AUTOPACKAGETARGET" )

	# Make the built package require the current autopackage version
	installer=$( echo "$installer" | replaceStr "%RootName%" "$ROOTNAME" )


	####

	# **********************************************************
	#  3. Generate package scripts
	# **********************************************************
	#  3.1. Prepare script
	# **********************************************************
	local prep_script=$( getSection "$specfile" Prepare )
	if [[ "$prep_script" == "" ]]; then
	    red; outn "WARNING: "; normal; out "No prep script [Prepare] found in the specfile, you might want one of these";
	fi

	# **********************************************************
	#  3.1.1. Check for require calls
	# **********************************************************
	# Scan for proper "require*" and "recommend*" lines
    echo "$prep_script" | while read; do

        # skip blank and commented lines
        if [ -z "$REPLY" ] || [[ ${REPLY:0:1} == "#" ]]; then
            continue
        fi

        # prepare could have logic so try to capture at least space leading lines
        local mode_check=`echo "$REPLY" | awk 'BEGIN{FS=" "}; { print $1 }' - | tr -d "\";" | tr -d "\';"`
        local rootname_check=`echo "$REPLY" | awk 'BEGIN{FS=" "}; { print $2 }' - | tr -d "\";" | tr -d "\';"`
        local version_check=`echo "$REPLY" | awk 'BEGIN{FS=" "}; { print $3 }' - | tr -d "\";" | tr -d "\';"`

        if [[ "$mode_check" == "require" ]] || [[ "$mode_check" == "recommend" ]]; then
            if [ -n "`versionFromRootName $rootname_check`" ] || [ -z "$version_check" ]; then
                err "require/recommend needs an unversioned rootname and an interface version - '$REPLY'"
                return 1
            else
                trace prepare call verified mode=$mode_check rootname=$rootname_check version=$version_check
            fi
        fi

        if [[ "$mode_check" == "requireExact" ]] || [[ "$mode_check" == "requireAtLeast" ]] || [[ "$mode_check" == "recommendExact" ]] || [[ "$mode_check" == "recommendAtLeast" ]]; then
            if [ -z "`versionFromRootName $rootname_check`" ] || [ -n "$version_check" ]; then
                err "requireExact/requireAtLeast/recommendExact/recommendAtLeast needs an versioned rootname and an interface version - '$REPLY'"
                return 1
            else
                trace prepare call verified mode=$mode_check rootname=$rootname_check version=$version_check
            fi
        fi

        unset mode_check rootname_check version_check

    done

	# Incorporate "require*" and "recommend*" lines
	local requires=` echo "$prep_script" | awk '/^[ \t]*[require|recommend]*/ {
		i=1
		while (i < NF && $i != "#") {
			if ( $i == "require" || $i == "requireExact" || $i == "requireAtLeast" || $i == "recommend" || $i == "recommendExact" || $i == "recommendAtLeast" ) {
				i++;
				print $i;
			}
			i++;
		}
	} ' | tr -d "\";" | tr -d "\';" `

	# **********************************************************
	#  3.1.2. Check for required skeletons
	# **********************************************************
	if [[ "$requires" != "" ]]; then
		# Ensure we have the needed skeleton packages
		i=1
		local requirement=` getLine "$requires" $i `
		local requirements=""
		local foundSkelFile
		while [[ "$requirement" != "" ]]; do
			requirements="$requirements $requirement"; # Add to list, this accumulates versioned root names....
			foundSkelFile=`_locateSkeleton "$requirement"`
			res=$?
			skels_to_copy_files="$skels_to_copy_files $foundSkelFile"

			if [[ "$res" != "0" ]]; then # and this accumulates the file refs: @gnome.org/libxml/skeleton.2
				if [[ "$res" == "1" ]]; then
					red; outn "FAIL: "; normal;  out "Could not locate skeleton package for '%s'" "$requirement";
					normal; out "Try running svn update in the skeletons directory to get the latest files"
					return $ERROR_MISSING_SKELETON;
				elif [[ "$res" == "2" ]]; then
					red; outn "FAIL: "; normal; out "Bad skeleton for %s, not in ASCII text format" "$requirement";
					normal; out "Try running svn update in the skeletons directory to get the latest files"
					return $ERROR_MISSING_SKELETON;
				elif [[ "$res" == "3" ]]; then
					red
					out "Skeleton for %s was found, but the skeleton file has an incorrect root name (%s)" "$requirement" "$foundSkelFile"
					normal
					return $ERROR_MISSING_SKELETON;
				fi
			fi

			# check sanity of skelVersionReq, code stolen from check for $AUTOPACKAGETARGET
			skelVersionReq=`getSectionKey "$foundSkelFile" Meta AutopackageTarget`
			local skel_apkgtarget_major=`getMajor "$skelVersionReq"`
			local skel_apkgtarget_minor=`getMinor "$skelVersionReq"`

			if [ `expr index "$skel_apkgtarget_major" '[abcdefghijklmnopqrstuvwxyz]'` -gt "0" ]; then
				skel_apkgtarget_major="1"
			fi

			if [ `expr index "$skel_apkgtarget_minor" '[abcdefghijklmnopqrstuvwxyz]'` -gt "0" ] || [[ "$skel_apkgtarget_minor" == "" ]]; then
				skel_apkgtarget_minor="0"
			fi

			if [[ "$skel_apkgtarget_major" != "" ]]; then
				skelVersionReq="$skel_apkgtarget_major.$skel_apkgtarget_minor"
			else
				skelVersionReq="1.0"
			fi

			if ! compareVersions $skelVersionReq $AUTOPACKAGETARGET; then
				red; outn "FAIL: " ; normal; out "Skeleton for '%s' requires Autopackage API version $skelVersionReq. Increase AutopackageTarget in your specfile to $skelVersionReq." "$requirement"
				return $ERROR_SKELETON_API_MISMATCH
			fi

			(( i++ ));
			trace added requirement $requirement, `_locateSkeleton $requirement`
			requirement=` getLine "$requires" $i `;
		done
	fi
	if [[ "$AUTOPACKAGETARGET" < "1.4" ]]; then
		prep_script=$(_getBackendTemplate "prep" "$prep_script")
	fi

	# **********************************************************
	#  3.2. Uninstall script
	# **********************************************************
	local uninstall=$( getSection "$specfile" Uninstall )
	if [[ "$uninstall" == "" ]]; then
	    red; outn "WARNING: "; normal; out "No uninstaller script found in the specfile, you should add one"
	fi

	# **********************************************************
	#  3.4. Globals section
	# **********************************************************
	globals=`getSection "$specfile" "Globals"`
	globals=`stripComments "$globals"`
	globals=`stripBlankLines "$globals"`

	# evaluate it, so the definitions are available in BuildPrepare and Imports
	eval "$globals" >/dev/null

	# **********************************************************
	#  4. Generate build_roots and build software
	# **********************************************************
	local prepare=`getSection "$specfile" BuildPrepare`
	if [[ "$prepare" == "" ]]; then
		red; outn "WARNING: "; normal; out "No BuildPrepare section found in the specfile. Is that intended?";
	fi
	local unprepare=`getSection "$specfile" BuildUnprepare`
	if [[ "$prepare" != "" ]] && [[ "$unprepare" == "" ]]; then
		red; outn "WARNING: "; normal; out "You have a BuildPrepare section but no BuildUnprepare";
	fi

	prepare=`stripComments "$prepare"`
	unprepare=`stripComments "$unprepare"`

	pushd "$source_dir" >/dev/null

	if [[ "$APKG_BUILD_ROOT" != "" ]]; then
		export original_build_root="$APKG_BUILD_ROOT"
	else
                export original_build_root="${TMP}/apkg-build-root.$$"
                mkdir -p "$original_build_root"
	fi

        # prepareBuild may modify it to make things more convenient for specfile writers
        # this is a dubious design decision
        export build_root="$original_build_root"

	if [[ "$prepare" != "" ]]; then
		pushOptE; set +e;

                # set the apbuild projectname var, so we get an rpath of $PREFIX/lib/$SHORTNAME
                export APBUILD_PROJECTNAME=$SHORTNAME

                function doPrepare()
                {
			# protect us from script authors moving around inside BuildPrepare
		        pushd . >/dev/null
		        if ! eval "$prepare"; then
			        red
			        out "Prepare failed. Please refer to above messages to see why."
			        normal
			        popd >/dev/null
			        popOptE
			        return 1
		        fi
                        popd >/dev/null
                }

                echo "build root is $build_root"
                if [[ "$CXX1" != "" ]]; then
                      export APBUILD_CXX1="$CXX1"
                fi
                doPrepare
                if [[ "$CXX2" != "" ]]; then
                        export APBUILD_CXX1="$CXX2"

                        # make another build root we can install into and diff against the first
                        export build_root1="$build_root"
                        export _virtual_build_root1="$_virtual_build_root"

                        export build_root="$original_build_root.2"
                        mkdir -p "$build_root"

                        # This messing around with virtual build roots
                        # crap is a mess and a break of encapsulation.
                        # This stuff really needs to be rethought to
                        # use a little less convenient magic and a
                        # little more robust design ....

                        # Here we are assuming that BuildPrepare
                        # cleans up after itself. This is not
                        # necessarily the case. We could detect this
                        # to help the developer by timing the build.
                        # A significant difference probably means we
                        # didn't do a "make clean".
                        
                        echo
                        echo "Building using second compiler ..."
                        echo
                        doPrepare
                        export build_root2="$build_root"
                        export _virtual_build_root2="$_virtual_build_root"

                        # confused? build_root1 and build_root2 are now the two roots *after*
                        # being prepared twice.

                        echo
                        echo -n "Copying across double-compiled ELF binaries ..."
                        pushd $build_root2 >/dev/null
                        find -type f | while read; do
                                if isFileELF "$REPLY"; then
                                        cp "$REPLY" "$build_root1/$REPLY.GCCABI2"
                                        md5sum $REPLY "$build_root1/$REPLY"
                                        echo -n "."
                                fi
                        done
                        green; echo " done"; normal;
                        popd >/dev/null

                        export build_root="$build_root1"
                fi
				if [[ "$HYBRID_PACKAGE" != "" ]]; then
					outn "Extracting package %s ..." "$HYBRID_PACKAGE"
					extractPackage "$HYBRID_PACKAGE"
					r="$?"
					if [[ "$r" != "0" ]]; then
						red; outn "FAIL: "; normal; out "Couldn't extract $HYBRID_PACKAGE."; exit 1
					fi
					# Before decompressing the payload we need to overwrite the existing definition
					# of progressBar to avoid syntax errors in apkg-io
					function progressBar()
					{
						outn ".";
					}
					_decompressPayload
					HYBRID_BUILD_ROOT="$_payload_dir"
					green; out " done"; normal;
				fi
				if [[ "$HYBRID_BUILD_ROOT" != "" ]]; then
					outn "Copying across architecture depended files ..."
					pushd "$HYBRID_BUILD_ROOT" >/dev/null
					find -type f | while read; do
						if [[ -e "$build_root/$REPLY" ]]; then
							if [[ "$(md5sum < "$REPLY")" != "$(md5sum < "$build_root/$REPLY")" ]]; then
								cp "$REPLY" "$build_root/$REPLY.HYBRID"						
								outn "."
							fi
						fi
					done
					popd >/dev/null
					green; out " done"; normal;
				fi
		popOptE
	fi

	# **********************************************************
	#  5. Import files into package
	# **********************************************************
	# now figure out what files we need to import and copy them into the working directory
	# the [Imports] section is a script, so define the functions it needs and then run it
	imports=$( getSection "$specfile" Imports )
	if [[ "$imports" == "" ]]; then
	    red; outn "WARNING: "; normal; out "No [Imports] section found."
	fi

	##
	# import [LOCATION]
	# LOCATION: the path in the package payload where the files should be placed. Optional. If skipped, "./" is assumed.
	#
	# import takes a set of files on STDIN to be copied into the package payload.
	# The easiest way to invoke it is using a here-doc, as shown in the example.
	# Each file to be imported must be on a separate line. You can also pass it wildcards.
	#
	# Example:
	# import share/foobar <<EOF
	# share/foobar/open.png
	# share/foobar/close.png
	# EOF
	# echo 'bin/foobar' | extract
	# (you now have 1 file in the root of the payload, foobar, and 2 in the ./share/foobar directory)
	function import() {
		local path_to="$1"

		out "Importing files to $payload_dir/$path_to"

		# create destination path in payload, if it doesn't exist
		[ ! -e "$payload_dir/$path_to" ] && { mkdir -p -- "$payload_dir/$path_to"; }

		# yes, this is quite possibly a winner for the most disgusting bash construct ever invented.
		# blame the fact that piping something to a while statement forks a subshell -mh
		local id=$$
		if ! cat | while read; do
			# check each import to see if it's a symlink
			for f in $REPLY; do
			    if [ -L "$f" ]; then
				red; outn "WARNING: "; normal; out "Importing a symlink ($f), is that intentional?";
			    fi
			done
			if ! cp -dpR $REPLY "$payload_dir/$path_to"; then
				echo $REPLY >"${TMP}/apkg-evilhack1-$id"
				exit 1
			fi
	  	done; then
		        local n=`<"${TMP}/apkg-evilhack1-$id"`
			red; outn "Failed"; normal; out "Could not extract files: %s" $n;
			echo
			out "Perhaps you need to update the specfile? The following files are in that directory:"
			ls `dirname $n`
			echo
			rm "${TMP}/apkg-evilhack1-$id"
			exit 1 # dive dive dive!
		fi

		trace "extraction ok!"
		return 0;
	}

	# Process imports to force exit on first failed extraction
	if [[ "$imports" != "" ]]; then

		if ! pushd "$build_root" >/dev/null; then
			red
			out "Unable to change to folder $build_root"
			normal
			exit 1
		fi
		( eval "$imports" )
		if [[ $? != 0 ]]; then
			red
			out "Importing failed."
			normal
			cleanUp
			return 1
		fi
		popd >/dev/null  # pop out of the build root
	fi

	if [[ "$unprepare" != "" ]]; then
		pushOptE; set +e;

                [[ "$_virtual_build_root1" != "" ]] && export _virtual_build_root="$_virtual_build_root1"
		# protect us from script authors moving around inside BuildUnprepare
		pushd . >/dev/null
		if ! eval "$unprepare"; then
			popd >/dev/null
			popOptE;
			return 1;
		fi
		popd >/dev/null

                if [[ "$_virtual_build_root1" != "" ]]; then
			export _virtual_build_root="$_virtual_build_root2"
			pushd . >/dev/null
			if ! eval "$unprepare"; then
				popd >/dev/null
				popOptE;
				return 1;
			fi
			popd >/dev/null
                fi
                
		popOptE
	fi

	popd >/dev/null  # pop out of the source/source dir

	echo

	# **********************************************************
	#  5.0   Scan for symlinks. copyFile/copyFiles() doesn't
	#        handle symlinks very well, so just delete them
	#        It's a lot eaiser than doing all sorts of linkFile
	#        and readlink magic. Scan here so that we don't
	#        strip out the symlinks that generateLegacyMime creates.
	# **********************************************************
	oIFS="$IFS"
	IFS=$'\n'
	local found_symlinks
	for f in $( find "$payload_dir" -type l ); do
		# do not warn about symlinks to shared libraries that
		# ldconfig and libtool generate
		if ! file "`readlink -f "$f"`" | grep -q "shared object"; then
			found_symlinks="$found_symlinks"$'\n'"* $f"
		fi
		removeFile "$f"
	done
	IFS="$oIFS"

	if [ -n "$found_symlinks" ]; then
		# knock off beginning newline of message
		found_symlinks=`echo "$found_symlinks" | sed -e '/^$/d'`
		red; outn "WARNING: "; normal; out "Symbolic links were found in payload and removed. If symbolic links are necessary then use the linkFile function within the [Install] section of the apspec file."
		out "The following links were deleted:"
		out "$found_symlinks"
	fi
	unset found_symlinks

	# **********************************************************
	#  5.0.1 Generate mime-type files for legacy desktops
	# **********************************************************
	# If there are any XDG mime-files installed into the proper
	# location (share/mime/packages), then the KDE equivalents are
	# generated.
	trace "checking for XDG mime-files to convert to legacy .desktop files"
	if [[ $( ls "$payload_dir"/share/mime/packages/*.xml 2> /dev/null ) != "" ]]; then # are there mime type files in the rigth place?
		generateLegacyMime "$payload_dir/share/mime/packages/"*.xml
	fi

	# **********************************************************
	#  5.1. Generate install script
	# **********************************************************
	# Get the install script from the specfile
	local install_script=$( getSection "$specfile" Install )
	if [[ "$install_script" == "" ]]; then
		if [[ "$AUTOPACKAGETARGET" < "1.4" ]]; then
			# try to auto-write it
			drawHeaderCyan "Analyzing imported files to generate install script..."
			install_script=$( analyze "$payload_dir" )
			echo "$install_script"
			echo
		else
			install_script="installEverything"
		fi
	fi

	if [[ "$AUTOPACKAGETARGET" < "1.4" ]]; then
		install_script=$(_getBackendTemplate "install" "$install_script")
	fi

	drawHeaderCyan "Generating payload and package file..."

	# **********************************************************
	#  5.2 Scan the extracted files for ELF glibc symbol versions,
	#      and add checking for them to the scripts
	# **********************************************************

	outn "Checking ELF binaries for highest GLIBC versions used ... "
	local symbols

	symbols=$( _findGlibcVersions "$payload_dir" )
	symbols=$(  for s in $symbols; do echo -n "GLIBC_$s "; done; )
	trace "required libc symbols are $symbols"
	prep_script=`echo "$prep_script" | sed "s/%LibCSymbols%/$symbols/"`
	install_script=`echo "$install_script" | sed "s/%LibCSymbols%/$symbols/"`
	stub=$(echo "$stub" | sed "s/%LibCSymbols%/$symbols/")
	found_too_new=false
	for s in $symbols; do
		if echo "$s" | grep -E -q "GLIBC_2\.[4-9]"; then
			found_too_new=true
		fi
	done
	if $found_too_new; then
		green; out "done with warnings";
		red; outn "WARNING: "; normal; out "Symbols from glibc 2.4 (or newer) were found. Consider using apbuild to allow users of older distros to run this binary.\nIf you are statically linking any libraries, make sure they are compiled with apbuild too.";
	else
		green; out "done"; normal;
	fi


	# **********************************************************
	#  5.3 Scan the working directory for all ELF binaries, and strip them.
	#      This can reduce the size of the package significantly.
	#
	#      Also check if the binaries link against the DSO versions of any
	#      X11 extension client libraries. The XFree project ship these as
	#      static archives, however some distros also provide .so versions.
	#      You can't guarantee these DSOs will always be present though,
	#      so scan for them here.
	#
	#      Scan for KDE apps so we can set PREFIX
	#      to $KDEDIR when installing.
	# **********************************************************

	outn "Scanning and stripping ELF binaries ... "
	if ! pushd "$payload_dir" >/dev/null; then
		red
		outn "Unable to change to folder $payload_dir"
		normal
		exit 1
	fi

	local warnings

	oIFS="$IFS"
	IFS=$'\n'
	local _PLATFORM=""
	local found_32bit_binary=""
	local found_64bit_binary=""
	for f in $( find -perm -754 -type f ); do
		if LC_ALL=C file "$f" | LC_ALL=C grep "ELF" >/dev/null; then
			if [[ "$APKG_NO_STRIP" == "" ]]; then
				strip "$f"
			fi

			# check that apbuild was used
			if [[ "$f" != *.HYBRID && $( dump-elf-metadata "$f" | grep 'apbuild.version' ) == "" ]]; then
			    warnings=$( red; outn "WARNING: "; normal; out "ELF binary $f was compiled without apbuild."; echo "$warnings"; )
			fi

			if ldd "$f" | grep -q libkdecore; then
				_PLATFORM="KDE"
                                # used to determine which prefix to go to
				trace "switching to KDE platform because of $f"
			fi
		fi
		if LC_ALL=C file "$f" | LC_ALL=C grep "ELF 32-bit" >/dev/null; then
			found_32bit_binary=$f
		fi
		if LC_ALL=C file "$f" | LC_ALL=C grep "ELF 64-bit" >/dev/null; then
			found_64bit_binary=$f
		fi
	done
	IFS="$oIFS"
	
	if [[ "$AUTOPACKAGETARGET" < "1.4" ]] && [[ "$found_64bit_binary" != "" ]]; then
		warnings=$( red; outn "WARNING: "; normal; out "AutopackageTarget should be set to at least 1.4 because your package contains 64 bit binaries."; echo "$warnings"; )
	fi

	if [[ "$AUTOPACKAGETARGET" > "1.2" ]]; then
		if [[ "$CPUARCHITECTURES" == "" ]]; then
			if [[ "$found_32bit_binary$found_64bit_binary" == "" ]]; then
				CPUARCHITECTURES="all"
				warnings=$( red; outn "WARNING: "; normal; out "CPUArchitectures set to all. Please set CPUArchitectures in your specfile."; echo "$warnings"; )
			else
				if [[ "found_32bit_binary" != "" ]]; then
					CPUARCHITECTURES="x86"
				fi
				if [[ "found_64bit_binary" != "" ]]; then
					CPUARCHITECTURES="x86_64 $CPUARCHITECTURES"
				fi
			fi
			trace CPUArchitectures=$CPUARCHITECTURES
		else
			if [[ "$CPUARCHITECTURES" != *x86* ]] && [[ "$found_32bit_binary" != "" ]]; then
				warnings=$( red; outn "WARNING: "; normal; out "32-bit ELF binary $found_32bit_binary found, but CPUArchitectures doesn't contain x86."; echo "$warnings"; )
			fi
			if [[ "$CPUARCHITECTURES" != *x86_64* ]] && [[ "$found_64bit_binary" != "" ]]; then
				warnings=$( red; outn "WARNING: "; normal; out "64-bit ELF binary $found_64bit_binary found, but CPUArchitectures doesn't contain x86_64."; echo "$warnings"; )
			fi
		fi
		stub=$( echo "$stub" | replaceStr "%CPUArchitectures%" "$CPUARCHITECTURES" )
	fi

        # check for DSOs and no InterfaceVersion key, a common mistake
        if [[ $( find -type f -name 'lib*.so.*' ) != "" ]] && [[ "$INTERFACEVERSION" == "" ]]; then
            warnings=$( echo "$warnings"; red; outn "WARNING: "; normal; out "Shared libraries are in payload, but no InterfaceVersion key is set?" )
        fi


	popd >/dev/null;
	if [[ "$warnings" == "" ]]; then
		green; out "done"; normal;
	else
		green; out "done with warnings"; normal;
		echo "$warnings";
	fi

	# **********************************************************
	#  5.4 Check for sealed package components
	# **********************************************************
	mkdir "$metadata_dir"
	chmod 700 "$metadata_dir"

	# if making a sealed installer package - add packages to $metadata_dir
	# support code package is required to be included in the packages directory - gtkfe inclusion is highly recommended
	if ! dirIsEmpty "$source_dir/autopackage/packages"; then
		normal; out "Making sealed package."
		if [ ! -f "$source_dir/autopackage/packages/autopackage.tar.bz2" ]; then
			red; outn "FAIL: "; normal; out "Using this package as a sealed installer requires that autopackage.tar.bz2 is included in the autopackage/packages directory."
			exit 1
		fi
		
		if [ ! -f "$source_dir/autopackage/packages/autopackage-gtk-$autopackage_version.package" ]; then
			red; outn "WARNING: "; normal; out "When using this package as a sealed installer, it's highly recommended that %s is included in the autopackage/packages directory." "autopackage-gtk-$autopackage_version.package"
		fi
		
		green; outn "Adding contents of: "; normal; out "$source_dir/autopackage/packages"
		cp -Rf "$source_dir/autopackage/packages" "$metadata_dir"
	fi

	# **********************************************************
	#  5.5 Copy over the 'requires' skeleton files
	# **********************************************************
	# Requires holds the skeleton packages that are required.
        # Copy them from the skeletons directory
	if [[ "$requires" != "" ]]; then
		requirements=( $requirements );
		i=0
		for skel in $skels_to_copy_files; do
			[[ "$skel" == "" ]] && continue;

			trace copying skel $skel
			skel_root=`getSection $skel Meta | getKey - RootName`
			skel_version=`getSection $skel Meta | getKey - Skeleton-Version`

			trace copying skeleton $skel, version $skel_version
			_mkdirs "$metadata_dir/$skel_root" >/dev/null
			cp $skel "$metadata_dir"/"$skel_root"

			if [[ "$skel_version" == "" ]]; then
				red
				outn "FAIL: "
				normal
				out "skeleton file (%s) is missing version" $skel
				cleanUp
				return 1
			fi

			echo $skel_root/skeleton.$skel_version > "$metadata_dir/$skel_root/skeleton_ref"
			trace skeleton ref was set to $skel_root/skeleton.$skel_version
			(( i++ ));
		done
	fi


	# **********************************************************
	#  5.6 Scan for .GCCABI2 executables and create patches
	#      for them.
	# **********************************************************

	outn "Scanning for C++ binaries ... "
	if ! pushd "$payload_dir" >/dev/null; then
		red
		outn "Unable to change to folder $payload_dir"
		normal
		exit 1
	fi

	local original
	local found=0
	warnings=
	oIFS="$IFS"
	IFS=$'\n'
	for f in $(find -name '*.GCCABI2'); do
		if [[ "$found" == "0" ]]; then
			found=1
			if [[ "$AUTOPACKAGETARGET" == "1.0" ]]; then
				warnings="Your package contains C++ binaries, but AutopackageTarget is set to 1.0. You should set it to at least 1.2."
			else
				green
				out "done"
				normal
				outn "Creating ABI patches for C++ binaries ... "
			fi
		fi

		original=`echo "$f" | sed 's/\.GCCABI2$//'`
		if ! "$autopackage_prefix/libexec/autopackage/bsdiff" "$original" "$f" "$f.PATCH"; then
			red
			outn "FAIL: "
			normal
			cleanUp
			return 1
		fi
		rm -f "$f"
	done
	IFS="$oIFS"

	popd >/dev/null
	if [[ "$warnings" == "" ]]; then
		green; out "done"; normal;
	else
		green; out "done with warnings"; normal;
		echo "$warnings";
	fi

	# **********************************************************
	#  5.6 Scan for .HYBRID files and create patches for them.
	# **********************************************************

	outn "Scanning for HYBRID files ... "
	if ! pushd "$payload_dir" >/dev/null; then
		red
		outn "Unable to change to folder $payload_dir"
		normal
		exit 1
	fi

	local original
	local found=0
	warnings=
	oIFS="$IFS"
	IFS=$'\n'
	for f in $(find -name '*.HYBRID'); do
		if [[ "$found" == "0" ]]; then
			found=1
			if [[ "$AUTOPACKAGETARGET" < "1.4" ]]; then
				warnings="Your package contains HYBRID files, but AutopackageTarget is set to $AUTOPACKAGETARGET. You should set it to at least 1.4."
			else
				green
				out "done"
				normal
				outn "Creating architecture patches for HYBRID files ... "
			fi
		fi

		original=$(echo "$f" | sed 's/\.HYBRID$//')
		if [[ "$cpu_architecture" == "x86" ]]; then
			new="$f.PATCH.x86_64"
		else
			new="$f.PATCH.x86"
		fi
		if ! "$autopackage_prefix/libexec/autopackage/bsdiff" "$original" "$f" "$new"; then
			red
			outn "FAIL: "
			normal
			cleanUp
			return 1
		fi
		rm -f "$f"
	done
	IFS="$oIFS"

	popd >/dev/null
	if [[ "$warnings" == "" ]]; then
		green; out "done"; normal;
	else
		green; out "done with warnings"; normal;
		echo "$warnings";
	fi

	# **********************************************************
	#  6. Create script files in meta directory
	# **********************************************************
	trace writing scripts out
	echo "$installer" > "$metadata_dir/apkg-installer"
	chmod a+x "$metadata_dir/apkg-installer"
	echo "$downloader" > "$metadata_dir/apkg-downloader"
	chmod a+x "$metadata_dir/apkg-downloader"
	echo "$prep_script" > "$metadata_dir/apkg-prep-install-script"
	chmod a+x "$metadata_dir/apkg-prep-install-script"
	echo "$install_script" > "$metadata_dir/apkg-install-script"
	chmod a+x "$metadata_dir/apkg-install-script"
	echo "$uninstall" >> "$metadata_dir/apkg-uninstall"

    # **********************************************************
    #  6.1 Add display-tool binaries to package if required
    # **********************************************************
    if [[ "$EULADISPLAY" != "None" ]] && [ -n "$EULAFILENAME" ]; then
        outn "Generating display-tool (eula) binaries ... "
        # check for SVN directory display-tool
        if [ ! -e "$autopackage_share/../../display-tool" ]; then
            err "Need to have SVN directory autopackage/display-tool available"
            err "so that it can be installed for use."
            return 1
        fi
        BEFOREEULA="`pwd`"

        cd "$autopackage_share/../../display-tool/gtk"
        make clean > /dev/null 2>&1
        make gtk2 > /dev/null 2>&1
        if [ -f display-eula-gtk2 ]; then
            [ ! -d "$metadata_dir/eula" ] && mkdirs "$metadata_dir/eula"
            cp display-eula-gtk2 "$metadata_dir/eula"
        else
            red; outn "ERROR: "; normal;
            out "File `pwd`/display-eula-gtk2 was not found. Unable to complete.";
            return 1
        fi

#         make gtk1 > /dev/null 2>&1
#         if [ -f display-eula-gtk1 ]; then
#             cp display-eula-gtk1 "$metadata_dir/"
#         else
#             red; outn "ERROR: "; normal;
#             out "File `pwd`/display-eula-gtk1 was not found. Unable to complete.";
#             return 1
#         fi

        cd "$autopackage_share/../../display-tool/qt3"
        make clean > /dev/null 2>&1
        qmake > /dev/null 2>&1
        make clean > /dev/null 2>&1
        make CC=apgcc CXX=apg++ LINK=apg++ > /dev/null 2>&1
        if [ -f display-eula-qt ]; then
            [ ! -d "$metadata_dir/eula" ] && mkdirs "$metadata_dir/eula"
            cp display-eula-qt "$metadata_dir/eula"
        else
            red; outn "ERROR: "; normal;
            out "File `pwd`/display-eula-qt was not found. Unable to complete.";
            return 1
        fi
        cd "$BEFOREEULA"
        unset BEFOREEULA
        green; out "done"; normal;
    fi

	# **********************************************************
	#  6.2 Add autopackage-curl binary to package
	# **********************************************************

	cp "$autopackage_prefix/libexec/autopackage/autopackage-curl" "$metadata_dir"

	# **********************************************************
	#  7. Start creating the package file
	# **********************************************************
	#  7.1 Generate language list
	# **********************************************************
	# determine which file to gather translations from and start using Metadata
	meta_desktop_file=`echo "$meta" | grep -i 'PackageDesktop:'`
	meta_desktop_file=`echo "$meta_desktop_file" | awk 'BEGIN { FS=": " } { print $2 }'`

	local meta_names meta_name_en meta_comments meta_comment_en meta_descriptions
	local meta_desktop_languages meta_desktop_language_add meta_languages_list PACKAGELANGUAGES

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

	if [ ! -f "$payload_dir/$meta_desktop_file" ]; then

        # give a warning that a PackageDesktop key was loaded but file not found
        if [[ "$meta_desktop_file" != "" ]]; then
            red; outn "WARNING: "; normal;
            out "PackageDesktop key was loaded from specfile but $meta_desktop_file was not found in payload. Defaulting to use specfile for DisplayName and Summary information.";
        fi

		# determine languages available from specfile
		trace using $specfile for DisplayName and Summary information
		meta_names=`echo "$meta" | grep 'DisplayName\[' | sed 's/DisplayName\[//g'`
		meta_descriptions=`echo "$meta" | grep 'Summary\[' | sed 's/Summary\[//g'`

		# gather languages and always include en as defined by apspec file specification
		meta_desktop_languages="en"
		for line in $meta_names $meta_descriptions; do
			meta_desktop_language_add=`echo "$line" | awk 'BEGIN { FS="]:" } { print $1 }'`
			meta_desktop_languages=`echo "$meta_desktop_languages"; echo "$meta_desktop_language_add"`
		done

	else

		# determine languages available from desktop file
		trace using $payload_dir/$meta_desktop_file for DisplayName and Summary information
		meta_desktop=`getSection "$payload_dir/$meta_desktop_file" "Desktop Entry"`

		meta_names=`echo "$meta_desktop" | grep '^Name\[' | sed 's/Name\[//g'`
		meta_comments=`echo "$meta_desktop" | grep '^Comment\[' | sed 's/Comment\[//g'`

		# gather languages and always include en as defined by .desktop specification
		meta_desktop_languages="en"
		for line in $meta_names $meta_comments; do
			meta_desktop_language_add=`echo "$line" | awk 'BEGIN { FS="]=" } { print $1 }'`
			meta_desktop_languages=`echo "$meta_desktop_languages"; echo "$meta_desktop_language_add"`
		done

		# convert Name to DISPLAYNAME
		meta_names=`echo "$meta_desktop" | grep '^Name' | sed 's/^Name/DISPLAYNAME/g' | sed 's/\[/\_/g' | sed 's/\]\=/\=\"/g' | sed 's/@/\_\_at\_\_/g'`
		[[ "$meta_names" != "" ]] && meta_names=`echo "$meta_names" | sed 's/$/"/g' | sed 's/^DISPLAYNAME\=/DISPLAYNAME\=\"/g'`
		# check to see if DISPLAYNAME_en is available and if not use DISPLAYNAME instead and write DISPLAYNAME_en to $meta_names
		meta_name_en=`echo "$meta_names" | grep '^DISPLAYNAME_en=' | awk 'BEGIN { FS="=" } { print $2 }'`
		if [ "$meta_name_en" == "" ]; then
			meta_name_en=`echo "$meta_names" | grep '^DISPLAYNAME=' | awk 'BEGIN { FS="=" } { print $2 }'`
			meta_names=`echo "DISPLAYNAME_en=${meta_name_en}"; echo "$meta_names"`
		fi
		eval "$meta_names" >/dev/null

		# convert Comment to SUMMARY
		meta_comments=`echo "$meta_desktop" | grep '^Comment' | sed 's/^Comment/SUMMARY/g' | sed 's/\[/\_/g' | sed 's/\]\=/\=\"/g' | sed 's/@/\_\_at\_\_/g'`
		[[ "$meta_comments" != "" ]] && meta_comments=`echo "$meta_comments" | sed 's/$/"/g' | sed 's/^SUMMARY\=/SUMMARY\=\"/g'`
		# check to see if SUMMARY_en is available and if not use SUMMARY instead and write SUMMARY_en to $meta_comments
		meta_comment_en=`echo "$meta_comments" | grep '^SUMMARY_en=' | awk 'BEGIN { FS="=" } { print $2 }'`
		if [ "$meta_comment_en" == "" ]; then
			meta_comment_en=`echo "$meta_comments" | grep '^SUMMARY=' | awk 'BEGIN { FS="=" } { print $2 }'`
			meta_comments=`echo "SUMMARY_en=${meta_comment_en}"; echo "$meta_comments"`
		fi
		eval "$meta_comments" >/dev/null

	fi

	if [[ "$DISPLAYNAME" == "" ]]; then red; outn "FAIL: "; normal; out "No DisplayName key found neither in the [Meta] section nor in $PACKAGEDESKTOP. You need one"; cleanUp; return 1; fi 

	# translate meta_desktop_languages to be a list
	meta_desktop_languages=`echo "$meta_desktop_languages" | sort | uniq`
	for line in $meta_desktop_languages; do
		if [[ "$meta_languages_list" == "" ]]; then
			meta_languages_list=`echo "$line"`
		else
			meta_languages_list=`echo -n "$meta_languages_list"; echo " $line"`
		fi
	done
	PACKAGELANGUAGES=`echo "$meta_languages_list"`

    IFS="$oIFS"


	# **********************************************************
	#  7.2. Grab expandedSize and encode the payload directory
	# **********************************************************
	local oldpwd="$PWD"
	cd "$payload_dir"

	# Grab expanded size of archive for stub
	local EXPANDSIZE=`du -bs | awk '{print $1}'`
	local filecount
	if [[ "`ls -1`" == "" ]]; then # if we have no files in the payload (ie it's an empty package)
		touch "${TMP}/apkg-payload.$$" # create an empty file
		if [[ "$COMPRESSION" == "lzma" ]]; then
			trace "compressing with autopackage-lzma"
			autopackage-lzma e "${TMP}/apkg-payload.$$" "${TMP}/apkg-payload.$$.lzma" -fb64 >/dev/null
            mv "${TMP}/apkg-payload.$$.lzma" "${TMP}/apkg-payload.$$"
		elif [[ "$COMPRESSION" == "bzip2" ]]; then
			trace compressing with bzip2
			bzip2 "${TMP}/apkg-payload.$$" # and compress it :)
			mv "${TMP}/apkg-payload.$$.bz2" "${TMP}/apkg-payload.$$"
		fi
		FILETOTAL=0
	else
		# Compress the files directory and sub in the file count
		if [[ "$COMPRESSION" == "lzma" ]]; then
			# We're checking to see if there are files that start with a dot.
			# If we simply tar up '.[^.+]* *', tar will error out about "file not found"
			# if it doesn't find any files that start what a dot.

			local match=`ls .[^.+]* 2> /dev/null | wc -l` # How many files do we have that start with a single "."?
			if (( match > 0 )); then # if we have some then pick them up. Not using ".*" because that will match "..", which leads to recursion issues.
				FILETOTAL=`tar -c -vf "${TMP}/apkg-payload.$$" * .[^.+]* | wc -l | sed 's/^ *//' `
			else
				FILETOTAL=`tar -c -vf "${TMP}/apkg-payload.$$" * | wc -l | sed 's/^ *//' `
			fi

			trace compressing with autopackage-lzma
			outn "Compressing ... "
			autopackage-lzma e "${TMP}/apkg-payload.$$" "${TMP}/apkg-payload.$$.lzma" -fb64 >/dev/null
			green; out "done"; normal;
                        mv "${TMP}/apkg-payload.$$.lzma" "${TMP}/apkg-payload.$$"
		elif [[ "$COMPRESSION" == "bzip2" ]]; then
			trace compressing with bzip2
			outn "Compressing ... "
			local match=`ls .[^.+]* 2> /dev/null | wc -l`
			if (( match > 0 )); then
				FILETOTAL=`tar -c --bzip2 -vf "${TMP}/apkg-payload.$$" * .[^.+]* | wc -l | sed 's/^ *//' `
			else
				FILETOTAL=`tar -c --bzip2 -vf "${TMP}/apkg-payload.$$" * | wc -l | sed 's/^ *//' `
			fi
			green; out "done"; normal;
		fi
	fi

	if locateCommand hostname > /dev/null 2>&1; then
		"$lc_location" --fqdn > "${TMP}/apkg-hostname" 2>&1
		if [[ "$?" == "0" ]]; then
			BUILDHOST=`<"${TMP}/apkg-hostname"`
		else
			"$lc_location" > "${TMP}/apkg-hostname"
			BUILDHOST=`<"${TMP}/apkg-hostname"`
 		fi
		rm -f "${TMP}/apkg-hostname"
	fi
	TIMESTAMPBUILD="`LC_ALL=C date --utc --iso-8601=seconds | cut -b -19`Z"


	# **********************************************************
	#  7.3 With environment variables now defined, generate
	#      environment state files (metadata)
	# **********************************************************
	#  7.3.1 Generate l10n environment files
	# **********************************************************
	# Create l10n environment files
	# for each language listed in PACKAGELANGUAGES, create a environment variable for
	# the language from a Meta section key, if not found use the default english
	# key entry. Therefore if a language is listed but does not have any Meta key
	# entries, then the environment is the same as the apkg-environment.en file.
    outn "Generating environment files ... "
	for language in $PACKAGELANGUAGES; do

		trace processing l10n Meta section keys to "$metadata_dir/apkg-environment.${language}"
		echo "# Package specfile information" >> "$metadata_dir/apkg-environment.${language}"
		for state in $specKeys; do

			for allowed in $intlKeys; do
				if [[ "$state" == "$allowed" ]]; then
					state_matched=1
				fi
			done

			if [ -z "$state_matched" ]; then
				b="${state}"
				text=`echo "${!b}"`
			else
				b="${state}_$(echo ${language} | sed 's/@/\_\_at\_\_/g')"
				text=`echo "${!b}"`
				if [ -z "$text" ]; then
					b="${state}"
					text=`echo "${!b}"`
				fi
			fi
			unset state_matched

			# in dealing with ${!b} - if there is no value (whitespace) to substitute then
			# text might be `<key>:' - check for text to the right of `:' and clear value if no text exists
			if [ `expr index "$text" ':'` -gt "0" ]; then
				text_text=`echo $text | awk 'BEGIN { FS=":" } { print $2 }'`
				if [[ "$text_text" == "" ]]; then
					trace erasing $state=\"$text\"
					unset text
				fi
				unset text_text
			fi

			# copy out to file for use in stub creation
			if [[ "$state" == "DISPLAYNAME" ]]; then
				echo "# DisplayName ${language} $text" >> "${TMP}/apkg-stub-displayname"
			elif [[ "$state" == "SUMMARY" ]]; then
				echo "# Summary ${language} $text" >> "${TMP}/apkg-stub-summary"
			fi

            # check that EULAFileName exists in metadata directory
            # give an error that a EULAFileName key was loaded but file not found
            if [[ "$state" == "EULAFILENAME" ]] && [ -n "$text" ]; then
                outn "packing license files ... "
                if [ ! -f "$source_dir/$text" ]; then
                    red; outn "ERROR: "; normal;
                    out "EULAFileName key was loaded from specfile but '$text' was not found in source directory '$source_dir'.";
                    return 1
                else
                    text_adjusted=`basename "$text"`
                    [ ! -d "$metadata_dir/eula" ] && mkdirs "$metadata_dir/eula"
                    cp "$source_dir/$text" "$metadata_dir/eula/$text_adjusted"
                    unset text_adjusted
                fi
            fi

			# leave out some meta keys for being added to environment file
			if [[ "$state" != "COMPRESSION" ]]; then
				echo "export ${state}=\"$text\"" >> "$metadata_dir/apkg-environment.${language}"
				trace adding $state=\"$text\"
			fi

		done

	done
    green; out "done"; normal;

	# **********************************************************
	#  7.3.2 Generate stub file
	# **********************************************************
	pass_through=false
	# escape quote backslashes because of echoing output to file
	stub=$( echo "$stub" | sed 's|\\|\\\\|g' );
	# special case: stub is already escape quoting - reduce from four to three backslashes
	stub=$( echo "$stub" | sed 's|\\\\\\\\|\\\\\\|g' );
	echo "$stub" | while read; do
		# at the first empty line the DisplayName and Summary will be placed
		if $pass_through || echo "$REPLY" | grep -qv '^$'; then
			echo "$REPLY" >> "${TMP}/apkg-stub"
		else
			cat "${TMP}/apkg-stub-displayname" >> "${TMP}/apkg-stub"
			cat "${TMP}/apkg-stub-summary" >> "${TMP}/apkg-stub"
			if [[ "$UPDATEFOR" != "" ]]; then
				echo "# UpdateFor: $UPDATEFOR" >> "${TMP}/apkg-stub"
			fi
			echo >> "${TMP}/apkg-stub"
			pass_through=true
		fi
	done
	rm -f "${TMP}/apkg-stub-displayname" "${TMP}/apkg-stub-summary"

	# **********************************************************
	#  7.3.3 Add Global section to environment state files
	# **********************************************************
	for language in $PACKAGELANGUAGES; do
		if [[ "$globals" != "" ]]; then
			trace processing Globals section to "$metadata_dir/apkg-environment.${language}"
			echo "" >> "$metadata_dir/apkg-environment.${language}"
			echo "# Package specfile Globals section information" >> "$metadata_dir/apkg-environment.${language}"
			echo "$globals" >> "$metadata_dir/apkg-environment.${language}"
		fi
		trace processing build keys to "$metadata_dir/apkg-environment.${language}"
		echo "" >> "$metadata_dir/apkg-environment.${language}"
		echo "# Package build information" >> "$metadata_dir/apkg-environment.${language}"
		for state in $buildKeys; do
			a="${state}"
			text=`echo "${!a}"`
			echo "export ${state}=\"$text\"" >> "$metadata_dir/apkg-environment.${language}"
		done
	done

	# **********************************************************
	#  7.4 Compress metadata directory
	# **********************************************************
	cd "$metadata_dir"
	tar czf "${TMP}/apkg-payload-meta.$$" *
	cd "$oldpwd"
	metaSize=`getFile --size "${TMP}/apkg-payload-meta.$$"`
	dataSize=`getFile --size "${TMP}/apkg-payload.$$"`

	# **********************************************************
	#  7.4.1 Generate last environment variables
	# **********************************************************
	trace computing MD5SUM
	# Compute MD5 sum after locating a MD5 binary
	local md5sum="00000000000000000000000000000000"
	local OLD_PATH="$PATH"
	PATH=${GUESS_MD5_PATH:-"$OLD_PATH:/bin:/usr/bin:/sbin:/usr/local/ssl/bin:/usr/local/bin:/opt/openssl/bin"}
	local MD5_PATH=`type -p md5sum`
	MD5_PATH=${MD5_PATH:-`type -p md5`}
	PATH="$OLD_PATH"
	if [ -x "$MD5_PATH" ]; then
		md5sum=`getFile --md5 "${TMP}/apkg-payload.$$"`
	else
		outn "No md5sum executable was found."
		return 1
	fi

	# **********************************************************
	#  7.4.2 Calculate the length of the stub
	#        Substitute in the last metadata into the stub file
	# **********************************************************
	local stubLength=`wc -l <"${TMP}/apkg-stub" | tr -d ' '`
	let "stubLength += 1"
	trace last modify of stub
	safeSed "${TMP}/apkg-stub" "s/%MD5Sum%/$md5sum/; s/%metaSize%/$metaSize/; s/%dataSize%/$dataSize/; s/%Compression%/$COMPRESSION/; s/%skipLines%/$stubLength/;"

	# **********************************************************
	#  8. Generate package output files depending on type
	# **********************************************************
	# source in environment file to grab defaults and maintain package environment variable consistency
	echo
	source "$metadata_dir/apkg-environment.en"

	if [ -n "$PACKAGEFILENAME" ] &&  `echo "$PACKAGEFILENAME" | grep -q -v '\.package$'`; then
		red; outn "WARNING: "; normal; out "PackageFileName '%s' should have a .package suffix. Please change the value of the filename to end in '.package' ." "$PACKAGEFILENAME"
		trace adjusting PACKAGEFILENAME to be $PACKAGEFILENAME.package
		PACKAGEFILENAME=$( echo "$PACKAGEFILENAME".package )
	elif [ -z "$PACKAGEFILENAME" ]; then
		if [[ "$AUTOPACKAGETARGET" == "1.0" ]]; then
			if (( PACKAGEVERSION > 1 )); then
				PACKAGEFILENAME="$SHORTNAME-$SOFTWAREVERSION-$PACKAGEVERSION.x86.package"
			else
				PACKAGEFILENAME="$SHORTNAME-$SOFTWAREVERSION.x86.package"
			fi
		else
			if (( PACKAGEVERSION > 1 )); then
				PACKAGEFILENAME="$DISPLAYNAME $SOFTWAREVERSION-$PACKAGEVERSION.package"
			else
				PACKAGEFILENAME="$DISPLAYNAME $SOFTWAREVERSION.package"
			fi
		fi
	fi

	# generate .package and .package.meta for all types
	cp "${TMP}/apkg-stub" "$PACKAGEFILENAME"
	cat "${TMP}/apkg-payload-meta.$$" >> "$PACKAGEFILENAME"
	cat "${TMP}/apkg-payload.$$" >> "$PACKAGEFILENAME"
	chmod +x "$PACKAGEFILENAME" &>/dev/null
	rm -f "${TMP}/apkg-stub"
	cp -f "${TMP}/apkg-payload-meta.$$" "$PACKAGEFILENAME.meta"

	out "The meta package is '$PACKAGEFILENAME.meta'."
	out "The complete package is '$PACKAGEFILENAME'."

	# generate xml repository file

	# rename previous xml repository file as to not overwrite previous entry
	if [ -e "$REPOSITORYFILENAME" ]; then
	    [ -e "$REPOSITORYFILENAME.old" ] && removeFile "$REPOSITORYFILENAME.old"
	    mv -f "$REPOSITORYFILENAME" "$REPOSITORYFILENAME.old"
	fi
	local xmlfile="$REPOSITORYFILENAME"
	trace xmlfile=$xmlfile

	XML_SOFTWARE_ENTRY_TOP="<?xml version=\"1.0\" ?>
<!DOCTYPE luau-repository SYSTEM
	\"http://luau.sourceforge.net/luau-repository-1.2.dtd\">

<luau-repository interface=\"1.2\">
"
	XML_SOFTWARE_ENTRY_BOTTOM="</luau-repository>"

	echo "$XML_SOFTWARE_ENTRY_TOP" > "$xmlfile"
	_xmlSoftwareEntry "$PACKAGEFILENAME" "$PACKAGEFILENAME.meta" "$repository_dir/$PACKAGEFILENAME" >> "$xmlfile"
	echo "$XML_SOFTWARE_ENTRY_BOTTOM" >> "$xmlfile"
	out "The Luau repository XML entry file is '$xmlfile'."

	# tidy up
	trace cleaning up
	cleanUp
}


if [ ! -e "$autopackage_share/stub.template" ]; then
        err the autopackage developer files are not installed
        exit 1
fi

if [[ "$#" = "0" ]]; then
	process "autopackage/default.apspec"
	exit $?
else
	for SPEC in "$@"; do
		process "$SPEC"

		exitCode=$?
		if [[ $exitCode != 0 ]]; then
			exit $exitCode
		fi
	done
fi
