#!/bin/sh
# Apt configurator.
# Copyright GPL 1999-2004 by Joey Hess
set -e

# If the first parameter is "probe", do cd autoprobing on startup.
if [ "$1" = probe ]; then
	CDPROBE=1
fi

# If the second parameter is "-N", this is a new install; do not set seen
# flags before asking questions; this allows for preseeding. Also some
# queston priorities change.
if [ "x$2" = "x-N" ]; then
	NEW=1
fi

# Where is the mirrors master list?
MIRRORLIST=/usr/lib/base-config/Mirrors.masterlist

. /usr/share/debconf/confmodule

TEXTDOMAIN=base-config
export TEXTDOMAIN

ARCH="$(dpkg --print-architecture)"
export ARCH

# Get the configuration from /etc/apt/apt.conf
APTGET="/usr/bin/apt-get"
APTETC="/etc/apt/"
APTCDROM="/usr/bin/apt-cdrom"
RES=`apt-config shell \
	APTGET Dir::Bin::apt-get/d \
	APTETC Dir::Etc/d \
	APTCDROM Dir::Bin::apt-cdrom/d`
eval $RES
APTGET="$APTGET -o Acquire::gpgv::Options::=--ignore-time-conflict"
APTCDROM="$APTCDROM -o Acquire::gpgv::Options::=--ignore-time-conflict"

DO_PROGRESS=
db_capb
for capb in $RET; do
	if [ "$capb" = progress ]; then
		DO_PROGRESS=1
		break
	fi
done

# Clear the screen if we're on a tty, but don't fail if we're not.
clear_screen () {
	if [ ! "$DO_PROGRESS" ]; then
		clear >/dev/tty </dev/tty 2>/dev/null || true
	fi
}

country_i18n () {
	# convert country name using iso_3166 table
	case "$1" in
	local)
		perl -e '
			use Locale::gettext;
			use POSIX;
			textdomain("iso_3166");
			$s = shift;
			$s =~ s/,/, /go;
			print gettext($s);
			' $2 | sed -e 's/, /./g'
	;;
	C)
		perl -e '
			use Locale::gettext;
			use POSIX;
			textdomain("iso_3166");
			$country=shift;
			$ret= "";

			open (T, "/usr/share/iso-codes/iso_3166.tab") || open(T, "/usr/share/zoneinfo/iso3166.tab");
			while (<T>) {
				next if /^#/;
				chomp;
				($code, $long)=split(/\t/, $_);
				if (gettext($long) eq $country) {
				    $ret = $long;
				    $ret =~ s/, /,/go;
				    close T;
				}
			}
			close T;
			print $ret ? $ret : $country;
			' $2
		;;
	esac
}

# Expand country wildcards in mirror list. The following substitution
# variables are available:
#   ${CC}: lower-case country code
#   ${UCC}: upper-case country code
#   ${CNAME}: country name
# This is useful if you have a mirror hierarchy using wildcard DNS.
expand_mirror_list () {
	perl -ne '
		BEGIN {
			open (T, "/usr/share/iso-codes/iso_3166.tab") || open (T, "/usr/share/zoneinfo/iso3166.tab");
			my $id=-1;
			while (<T>) {
				next if /^#/;
				chomp;
				($code, $long)=split(/\t/, $_);
				$co[++$id]=[$code, $long];
			}
			close T;
			$/="\n\n";
		}
		if (/^Site: .*\${CC}/im) {
			foreach my $id (0..$#co) {
				my ($code, $long)=@{$co[$id]};
				my $expanded=$_;
				$expanded=~s/\${CC}/lc($code)/eg;
				$expanded=~s/\${UCC}/uc($code)/eg;
				$expanded=~s/\${CNAME}/$long/g;
				print $expanded;
				# cope with expanding final entry
				if ($expanded !~ /\n\n\z/ and $id != $#co) {
					print "\n";
				}
			}
		} else {
			print;
		}
	' $MIRRORLIST
}

# Pass in a URI type; this function returns a list of countries
# that have mirrors in them that match the type.
country_list () {
	# translators: there MUST be a comma followed by a space at the end
	# of your translation, or things will break!
	gettext "enter information manually, "
	expand_mirror_list | perl -ne '
		BEGIN {
			use Locale::gettext;
			use POSIX;
			textdomain("iso_3166");
			$type=shift;
			open (T, "/usr/share/iso-codes/iso_3166.tab") || open (T, "/usr/share/zoneinfo/iso3166.tab");
			while (<T>) {
				next if /^#/;
				chomp;
				($code, $long)=split(/\t/, $_);
				$co{$code}=$long;
			}
			close T;
			$/="\n\n";
		}
		if (/Archive-architecture: (.*)/i and length $ENV{ARCH}) {
			my @arches = split " ", $1;
			if (grep /^!/, @arches) {
				my %notarches = map { substr($_, 1) => 1 } grep /^!/, @arches;
				next if exists $notarches{$ENV{ARCH}};
			} else {
				my %arches = map { $_ => 1 } @arches;
				next if not exists $arches{$ENV{ARCH}};
			}
		}
		if (/Archive-$type:/) {
			($c)=/Country: (.*?)\s+.*\n/;
			($s)=gettext($co{$c});
			$s =~ s/, /,/go;
			$countries{$s}=1 if $c;
		}
		END { print join(", ", sort(keys %countries)) }
	' $1
}

# Pass in a country (C locale); this function returns the corresponding
# country code.
country_code () {
	perl -e '
		$country=shift;
		open (T, "/usr/share/zoneinfo/iso3166.tab");
		$ret="";
		while (<T>) {
			next if /^#/;
			chomp;
			($code, $long)=split(/\t/, $_);
			if ($long eq $country) {
				$ret=$code;
				last;
			}
		}
		close T;
		print "$ret\n";
	' "$1"
}

# Pass in a URI type and a country; this function returns a 
# list of mirrors of the correct type in the country.
# The list is ordered with push mirrors at the top.
# Other orderings can be added here.
mirror_list () {
	expand_mirror_list | perl -ne '
		BEGIN {
			$type=shift;
			$country=shift;
			open (T, "/usr/share/iso-codes/iso_3166.tab") || open (T, "/usr/share/zoneinfo/iso3166.tab");
			while (<T>) {
				next if /^#/;
				chomp;
				($code, $long)=split(/\t/, $_);
				$long =~ s/, /,/go;
				if ($long eq $country) {
					$country=$code;
				        close T;
				}
			}
			close T;
			$/="\n\n";
		}
		if (/Archive-architecture: (.*)/i and length $ENV{ARCH}) {
			my @arches = split " ", $1;
			if (grep /^!/, @arches) {
				my %notarches = map { substr($_, 1) => 1 } grep /^!/, @arches;
				next if exists $notarches{$ENV{ARCH}};
			} else {
				my %arches = map { $_ => 1 } @arches;
				next if not exists $arches{$ENV{ARCH}};
			}
		}
		if (/Archive-$type:/ && /Country: $country\s+.*\n/) {
			($s)=/Site: (.*?)\n/;
			($t)=/Type: (.*?)\n/;
			$rating=0;
			$rating=1 if $t=~/push/i;
			$rating=2 if $t=~/push-primary/i;
			$mirrors{$s}=$rating;
		}
		END { print join(", ",
			sort { $mirrors{$b} <=> $mirrors{$a} }
			(keys %mirrors)) }
	' $1 "$2"
}

# Pass in the URI type and the hostname of a mirror; this returns the
# directory the debian mirror is located in on that host.
mirror_dir () {
	expand_mirror_list | perl -ne '
		BEGIN { $/="\n\n"; $type=shift; $mirror=shift }
		if (/Archive-architecture: (.*)/i and length $ENV{ARCH}) {
			my @arches = split " ", $1;
			if (grep /^!/, @arches) {
				my %notarches = map { substr($_, 1) => 1 } grep /^!/, @arches;
				next if exists $notarches{$ENV{ARCH}};
			} else {
				my %arches = map { $_ => 1 } @arches;
				next if not exists $arches{$ENV{ARCH}};
			}
		}
		if (/Site: $mirror/ && /Archive-$type: (.*)\n/) {
			print $1;
			exit;
		}
	' $1 $2
}

# Some sites don't mirror source; in these cases, look for a Source-site:
# field in the mirror list and use that instead.
source_site () {
	expand_mirror_list | perl -ne '
		BEGIN { $/="\n\n"; $mirror=shift }
		if (/Archive-architecture: (.*)/i and length $ENV{ARCH}) {
			my @arches = split " ", $1;
			if (grep /^!/, @arches) {
				my %notarches = map { substr($_, 1) => 1 } grep /^!/, @arches;
				next if exists $notarches{$ENV{ARCH}};
			} else {
				my %arches = map { $_ => 1 } @arches;
				next if not exists $arches{$ENV{ARCH}};
			}
		}
		if (/Site: $mirror/) {
			if (/Source-site: (.*)\n/i) {
				print $1;
			}
			exit;
		}
	' $1
}

# After mounting a cd, call this function to scan
# it with apt-cdrom, which also adds it to the sources.list.
# The cd will then be unmounted.
scan_cd () {
	clear_screen
	if [ ! "$DO_PROGRESS" ]; then
		gettext "Scanning CD, this will take a minute."
		echo
	fi
	# Touch file because apt-cdrom bails if it doesn't exist.
	touch ${APTETC}sources.list
	CODE=0
	if [ "$DO_PROGRESS" ]; then
		# TODO: would be nice if the output went somewhere useful
		$APTCDROM add --no-mount </dev/null >/dev/null || CODE=$?
	else
		$APTCDROM add --no-mount </dev/tty >/dev/tty || CODE=$?
	fi
	if [ "$CODE" -eq 0 ]; then
		umount /cdrom 2>/dev/null || true
		clear_screen
		return 0
	else
		umount /cdrom 2>/dev/null || true
		clear_screen
		# Apt didn't like the cdrom for some reason.
		db_input critical apt-setup/cd/bad || true
		db_go || true
		db_fset apt-setup/cd/bad seen false
		return 1
	fi
}

# This function should be called only after one cd has been successfully
# scanned. It prompts the user if there are more cd's to scan and
# scans them. Pass in the device that is known to be the cd drive.
handle_rest_cds () {
	# Ubuntu-specific: we will never ship "another CD" (bug #355).
	if [ "$NEW" ]; then return 0; fi
	LOOP=1
	while [ "$LOOP" ]; do
		# Make sure the cd is unmounted, we may be prompting
		# them to change cd's.
		umount /cdrom 2>/dev/null || true

		db_set apt-setup/cd/another false
		db_input high apt-setup/cd/another || true
		db_go || true
		db_fset apt-setup/cd/another seen false
		db_get apt-setup/cd/another
		if [ "$RET" = true ]; then
			while ! mount $1 /cdrom -o ro -t iso9660
			do
				db_input critical apt-setup/cd/dev || true
				if ! db_go; then
					db_fset apt-setup/cd/dev seen false
					continue 2
				fi
				db_fset apt-setup/cd/dev seen false
				db_get apt-setup/cd/dev
				CDDEV="$RET"
			done
			scan_cd || true
		else
			LOOP=''
		fi
	done
}

# This function will ask the user if they want to add another
# apt source. If so, it returns true.
add_another () {
	# Default to adding another source if all the current sources do
	# not provide at least 300 packages. If it's closer to 200, then
	# they may be using a netinst cdrom or something, and should add
	# more sources.
	PACKAGE_COUNT=$(LC_ALL=C apt-cache stats | grep -i 'Normal Packages:' | awk '{ print $3 }')
	if [ "$PACKAGE_COUNT" -ge 300 ]; then
		prio=medium
		db_set apt-setup/another false
	else
		prio=high
		db_set apt-setup/another true
	fi
	
	#  Several notes for translators:
	#  * The singular form is only there to make use of plural forms;
	#  * If package count is 0, a separate error message should be displayed.
	#  * This sentence is part of a longer paragraph, full stop is omitted here.
	#  * "${PACKAGE_COUNT}" must not be translated.
	MESSAGE=$(ngettext 'The Debian package management tool, apt, is now configured, and can install ${PACKAGE_COUNT} package' 'The Debian package management tool, apt, is now configured, and can install ${PACKAGE_COUNT} packages' $PACKAGE_COUNT | sed -e "s/\${PACKAGE_COUNT}/$PACKAGE_COUNT/")
	db_subst apt-setup/another MESSAGE $MESSAGE

	db_input $prio apt-setup/another || return 1
	if ! db_go; then
		db_fset apt-setup/another seen false
		return 1 # effectively backup to the menu.
	fi
	db_fset apt-setup/another seen false
	db_get apt-setup/another
	if [ "$RET" = true ]; then
		return 0
	else
		return 1
	fi
}

# Asks for a http proxy to use if none is yet set.
ask_http_proxy () {
	if [ ! -e "$APTETC/apt.conf" ] || \
	   ! grep -iq 'Acquire::http::Proxy' $APTETC/apt.conf; then
		db_input medium mirror/http/proxy || true
		if ! db_go; then
			db_fset mirror/http/proxy seen false
			continue
		fi
		db_fset mirror/http/proxy seen false
	
		# Add a trailing slash if missing.
		db_get mirror/http/proxy || true
		if [ -n "$RET" ]; then
			db_set mirror/http/proxy "$(echo $RET | sed 's/[/]*$/\//')" || true 
		fi
	fi
}

db_capb backup
db_settitle apt-setup/title

# The slow things here are mounting the CD-ROM and running 'apt-get update'.
# The progress bar therefore looks like this:
#
#   0: CD-ROM autodetection
#   1: main loop
#   2: main archive (network)
#   3: security archive (network)
#   4: finished
if [ "$DO_PROGRESS" ]; then
	db_progress START 0 4 apt-setup/progress/title
fi

MAINLOOP=1

# First, try to do cdrom autodetection. This is so in the most common case,
# you don't have to configure anything at all.

if [ "$DO_PROGRESS" ]; then
	db_progress INFO apt-setup/progress/cdrom
fi

# If /dev/cdrom exists, use it.
if [ -e /dev/cdrom ]; then
	CDDEV=/dev/cdrom
	db_set apt-setup/cd/dev "$CDDEV"
else
	# If there is a fstab entry for /cdrom or /media/cdrom0, use its device.
	CDDEV=$(grep "[[:space:]]/media/cdrom0/*[[:space:]]" /etc/fstab | awk '{print $1}')
	if [ -z "$CDDEV" ]; then
		CDDEV=$(grep "[[:space:]]/cdrom/*[[:space:]]" /etc/fstab | awk '{print $1}')
	fi
	if [ -n "$CDDEV" ] && [ -e "$CDDEV" ]; then
		db_set apt-setup/cd/dev "$CDDEV"
	fi
fi

# Don't probe for CD if preseeded to use some other uri_type.
if [ -n "$NEW" ]; then
	db_fget apt-setup/uri_type seen
	if [ "$RET" = true ]; then
		db_get apt-setup/uri_type
		if [ "$RET" != "cdrom" ]; then
			CDPROBE=""
		fi
	fi
fi

if [ "$CDPROBE" ] && [ "$CDDEV" ] && [ "$RET" = false ]; then
	umount /cdrom 2>/dev/null || true
	# Try mounting the detected cd rom.
	if mount $CDDEV /cdrom -o ro -t iso9660 2>/dev/null && scan_cd; then
		handle_rest_cds $CDDEV
		MAINLOOP=''
	else
		# Unable to mount it, or the cd was bad. Make sure that cdrom
		# is the default, and just go on to ask them where they want
		# apt to install from.
		db_set apt-setup/uri_type "cdrom"
		db_subst apt-setup/uri_type note $(gettext 'You probably used a CD to install the Debian base system, but it is not currently in the drive. You should probably just insert it and select "cdrom".')
	fi
fi

if [ "$NEW" ] && grep -qs '^deb cdrom' /etc/apt/sources.list; then
	# d-i has already done the work
	MAINLOOP=
fi

if [ "$DO_PROGRESS" ]; then
	db_progress STEP 1
fi

while [ "$MAINLOOP" ] || add_another; do
	if [ "$DO_PROGRESS" ]; then
		db_progress INFO apt-setup/progress/mainloop
	fi

	# Ask what source apt should install from.
	db_input critical apt-setup/uri_type || true
	if ! db_go; then
		db_fset apt-setup/uri_type seen false
		exit 30
	fi
	db_fset apt-setup/uri_type seen false
	db_get apt-setup/uri_type
	URI="$RET"
	# Clear any note that is on the uri_type, now that they've seen it.
	db_subst apt-setup/uri_type note ""

	# If they chose to use CD, there is little point in asking
	# these questions, since the CD's they insert will answer them for us.
	# Same goes if they are entering manually.
	# Warty change: we setup apt to fetch from the net anyway.
	if [ "$URI" != "edit sources list by hand" ]; then
		db_beginblock
		db_input low apt-setup/non-free || true
		db_input low apt-setup/universe || true
		db_input low apt-setup/backports || true
		db_endblock

		if ! db_go; then
			db_fset apt-setup/non-free seen false
			db_fset apt-setup/universe seen false
			db_fset apt-setup/backports seen false
			continue
		fi
		db_fset apt-setup/non-free seen false
		db_fset apt-setup/universe seen false
		db_fset apt-setup/backports seen false
	fi

	case "$URI" in
	ftp|http)
		# Ask them which country they're in.
		db_subst apt-setup/country countries "`country_list $URI`"
		db_fget apt-setup/country seen
		if [ "$RET" = "false" ]; then
			# Set default country
			db_get debian-installer/country
			COUNTRY=$(perl -e '
				$countrycode=shift;
				open (T, "/usr/share/iso-codes/iso_3166.tab") || open (T, "/usr/share/zoneinfo/iso3166.tab");
				while (<T>) {
					next if /^#/;
					chomp;
					($code, $long)=split(/\t/, $_);
					$long =~ s/, /,/go;
					if ($code eq $countrycode) {
						print "$long";
					        close T;
					}
				}
				close T;
		   	' $RET)
		   	if [ -n "$COUNTRY" ]; then
		   		db_set apt-setup/country "$COUNTRY"
		  	fi
		fi
		db_get apt-setup/country
		IFS=""
		db_set apt-setup/country $(country_i18n local "$RET")
		db_get apt-setup/country
		unset IFS
		db_input critical apt-setup/country || true
		if ! db_go; then
			db_fset apt-setup/country seen false
			continue
		fi
		db_fset apt-setup/country seen false

		db_get apt-setup/country
		if [ "$RET, " != "$(gettext 'enter information manually, ')" ]; then
		   IFS=""
		   db_set apt-setup/country $(country_i18n C "$RET")
		   unset IFS
		else
		   db_set apt-setup/country 'enter information manually'
		fi

		db_get apt-setup/country
		if [ "$RET" != "enter information manually" ]; then
			COUNTRY_C="$(country_i18n C "$RET")"

			# Now prompt with the mirrors in the selected country.
			db_subst apt-setup/mirror mirrors "`mirror_list $URI \"$RET\"`"
			db_fget apt-setup/mirror seen
			if [ "$RET" = false ] && [ "$COUNTRY_C" ]; then
				db_set apt-setup/mirror "$(country_code "$COUNTRY_C" | tr A-Z a-z).archive.ubuntu.com"
			fi
			db_input critical apt-setup/mirror || true
			if ! db_go; then
				db_fset apt-setup/mirror seen false
				continue
			fi
			db_fset apt-setup/mirror seen false
			
			# Now shove the data about the mirror into some other
			# questions.
			db_get apt-setup/mirror
			MIRROR="$RET"
			db_set apt-setup/hostname $MIRROR
			db_set apt-setup/directory "`mirror_dir $URI $MIRROR`"
		else
			# They elected to enter info manually.
			# Prompt for hostname and directory the mirror is in.
			db_beginblock
			db_input critical apt-setup/hostname || true
			db_input critical apt-setup/directory || true
			db_endblock
			if ! db_go; then
				db_fset apt-setup/hostname seen false
				db_fset apt-setup/directory seen false
				continue
			fi
			db_fset apt-setup/hostname seen false
			db_fset apt-setup/directory seen false
		fi

		if [ "$URI" = "http" ]; then
			ask_http_proxy
			http_proxy_asked=1
		fi
	;;
	cdrom)
		# We've already probed earlier to try to figure out the
		# cd device.
		LOOP=1
		LOOPCOUNT=5
		while [ "$LOOP" ]; do
			# Make sure the cd is unmounted, we may be prompting
			# them to change cd's.
			umount /cdrom 2>/dev/null || true
		
			# Prompt for the cd device if it wasn't autodetected.
			# TODO: We could give them a list of likely devices..
			#       This is unfriendly right now.
			if [ -z "$CDDEV" ]; then
				db_input critical apt-setup/cd/dev || true
				db_go || continue 2
				db_get apt-setup/cd/dev
				CDDEV="$RET"
				# Make /dev/cdrom link now, with device
				# they entered. This is for later use by
				# apt.
				if [ "$CDDEV" ] && [ "$CDDEV" != '/dev/cdrom' ]; then
					ln -sf $CDDEV /dev/cdrom
				fi
			fi
			
			# Now try to mount the cdrom.
			if mount $CDDEV /cdrom -o ro -t iso9660; then
				LOOP=""
				if scan_cd; then
					handle_rest_cds $CDDEV
					MAINLOOP=""
				fi
			else
				# Only loop LOOPCOUNT times.
				LOOPCOUNT=`expr $LOOPCOUNT - 1` || true
				if [ "0" -ge "$LOOPCOUNT" ]; then
					exit 1
				fi
				
				if [ "$LOOPCOUNT" = 4 ]; then
					# Display a less scary "missing CD"
					# message on the first loop.
					db_fset apt-setup/cd/missing seen false
					db_input critical apt-setup/cd/missing || true
					db_go || continue 2
				else
					# Loop and prompt again for cd device.
					db_fset apt-setup/cd/dev seen false
					CDDEV=""
				fi
			fi
		done
		continue
	;;
	
	filesystem)
		# they need to have a mirror already mounted somewhere.
		URI=file
		LOOP=1
		LOOPCOUNT=5
		while [ "$LOOP" ]; do
			db_input critical apt-setup/directory || true
			if ! db_go; then
				db_fset apt-setup/directory seen false
				continue 2
			fi
			db_fset apt-setup/directory seen false
			db_get apt-setup/directory
			
			# A very simple mirror sanity check.
			if [ ! -d "$RET" ]; then
				db_input critical apt-setup/baddir || true
				db_go || true
				db_fset apt-setup/baddir seen false
			elif [ ! -d "$RET/dists" ]; then
				db_input critical apt-setup/not-mirror || true
				db_go || true
				db_fset apt-setup/not-mirror seen false
			else
				LOOP=''
			fi
			
			# Only try LOOPCOUNT times.
			LOOPCOUNT=`expr $LOOPCOUNT - 1` || true
			if [ "0" -ge "$LOOPCOUNT" ]; then
				exit 1
			fi
		done
	;;
	*)
		touch ${APTETC}sources.list
		cp -f ${APTETC}sources.list ${APTETC}sources.list.bak
		# Just run an editor on the sources.list file, then
		# check the result. If it fails, show the problem and loop.
		# TODO: what happens if a debconf frontend is active?
		if [ -z "$EDITOR" ]; then
			EDITOR=/usr/bin/editor
		fi
		EDITOK=""
		while [ ! "$EDITOK" ]; do
			touch ${APTETC}sources.list
			$EDITOR ${APTETC}sources.list >/dev/tty </dev/tty
			tempfile=`tempfile`
			clear_screen
			if [ "$DO_PROGRESS" ]; then
				db_progress INFO apt-setup/progress/mainloop-testing
			else
				gettext "Testing apt sources..."
				echo
			fi
			if $APTGET -o APT::Get::List-Cleanup=false -o Dir::Etc::sourcelist=${APTETC}sources.list update 2>$tempfile; then
				clear_screen
				EDITOK=1
			else
				clear_screen
				db_subst apt-setup/badedit apt_error `tr '\n' ' ' < $tempfile`
				db_input critical apt-setup/badedit || true
				db_go || true
				db_fset apt-setup/badedit seen false
				db_get apt-setup/badedit
				if [ "$RET" != "edit" ]; then
					mv -f ${APTETC}sources.list.bak ${APTETC}sources.list
					continue 2
				fi
			fi
		done
		MAINLOOP=""
		rm -f ${APTETC}sources.list.bak
		continue
	esac

	# The temporary file to use as sources.list for testing
	# new items.
	tmpsources=`tempfile`

	db_get apt-setup/hostname
	HOST="$RET"
	db_get apt-setup/directory
	DIR="$RET"
	db_get mirror/suite
	DIST="$RET"

	SRCHOST="$(source_site "$HOST")"
	if [ "$SRCHOST" ]; then
		SRCDIR="$(mirror_dir "$URI" "$SRCHOST")"
	else
		SRCHOST="$HOST"
		SRCDIR="$DIR"
	fi

	db_get apt-setup/non-free
	if [ "$RET" = true ]; then
		NONFREE=" restricted"
	else
		NONFREE=""
	fi
	db_get apt-setup/universe
	if [ "$RET" = true ]; then
		UNIVERSE=" universe"
	else
		UNIVERSE=""
	fi

	if [ "$URI" = ftp ] || [ "$URI" = http ]; then
		SEP=//
	else
		SEP=""
	fi
	if [ "$URI" = file ]; then
		HOST=""
	fi

	echo "deb $URI:$SEP$HOST$DIR $DIST main$NONFREE$UNIVERSE" >> $tmpsources
	SRCENTRY="deb-src $URI:$SEP$SRCHOST$SRCDIR $DIST main$NONFREE$UNIVERSE"

	# If there is a http proxy, make apt use it temporarily.
	db_get mirror/http/proxy
	if [ "$RET" ]; then
		PROXY_OPTS="-o Acquire::http::Proxy=\"$RET\""
	else
		PROXY_OPTS=""
	fi

	# As a final sanity check, run apt-get update, and catch the
	# return code and errors.
	tempfile=`tempfile`
	clear_screen
	if [ "$DO_PROGRESS" ]; then
		db_progress INFO apt-setup/progress/mainloop-testing
	else
		gettext "Testing apt sources..."
		echo
	fi
	if ! $APTGET $PROXY_OPTS -o APT::Get::List-Cleanup=false -o Dir::Etc::sourcelist=$tmpsources update 2>$tempfile; then
		clear_screen
		# Show the user the error message and loop.
		db_subst apt-setup/badsource apt_error `tr '\n' ' ' < $tempfile`
		db_input critical apt-setup/badsource || true
		db_go || true
		db_fset apt-setup/badsource seen false
		rm -f $tempfile $tmpsources
		continue
	fi
	# Success, so add the entry to the real sources.list
	touch ${APTETC}sources.list
	echo "" >> ${APTETC}sources.list
	cat $tmpsources >> ${APTETC}sources.list
	MAINLOOP=""
	
	# Success, so add proxy information if not already present.
	db_get mirror/http/proxy
	if [ "$RET" ]; then
		touch $APTETC/apt.conf
		if ! grep -iq 'Acquire::http::Proxy' $APTETC/apt.conf; then
			echo "Acquire::http::Proxy \"$RET\";" >> $APTETC/apt.conf
		fi
	fi
	
	# We have a deb-src line to add too. Test it, see if it works. If not,
	# don't fail, just don't add it.
	echo "$SRCENTRY" > $tmpsources
	if $APTGET -o APT::Get::List-Cleanup=false -o Dir::Etc::sourcelist=$tmpsources update 2>/dev/null; then
		echo "$SRCENTRY" >> ${APTETC}sources.list
	fi
	clear_screen

	rm -f $tempfile $tmpsources
done

if [ "$DO_PROGRESS" ]; then
	db_progress STEP 1
fi

# Warty change add extra apt-lines and needs to be done outside MAINLOOP
# because cdrom installation has 2000 different exceptions.

# get mirror information
# if we are installing from cd we will get the default and on net install
# we will get the user selection

db_get apt-setup/hostname
HOST="$RET"
if [ -z "$HOST" ]; then
	db_get debian-installer/country
	COUNTRY_CODE="$(echo "$RET" | tr A-Z a-z)"
	HOST="$COUNTRY_CODE.archive.ubuntu.com"
fi
db_get apt-setup/directory
DIR="$RET"
db_get mirror/suite
DIST="$RET"
SRCHOST="$(source_site "$HOST")"
if [ "$SRCHOST" ]; then
	SRCDIR="$(mirror_dir http "$SRCHOST")"
else
	SRCHOST="$HOST"
	SRCDIR="$DIR"
fi
db_get apt-setup/non-free
if [ "$RET" = true ]; then
	NONFREE=" restricted"
else
	NONFREE=""
fi
db_get apt-setup/universe
if [ "$RET" = true ]; then
	UNIVERSE=" universe"
else
	UNIVERSE=""
fi

# URI is defined only in the main loop that we do not enter always.
if [ -z "$URI" ]; then
	URI=cdrom
fi

if [ "$URI" = "cdrom" ] && ! grep -q 'ncomment the following' ${APTETC}sources.list && ! grep -q '^[^#]*$HOST' ${APTETC}sources.list; then
	if [ "$DO_PROGRESS" ]; then
		db_progress INFO apt-setup/progress/network
	fi

	LINE="http://$HOST$DIR $DIST main$NONFREE"
	SRCLINE="http://$SRCHOST$SRCDIR $DIST main$NONFREE"

	COMMENT="# "
	SRCCOMMENT="# "

	db_input medium apt-setup/network-updates || true
	if ! db_go; then
		db_fset apt-setup/network-updates seen false
		exit 30
	fi
	db_fset apt-setup/network-updates seen false
	db_get apt-setup/network-updates
	if [ "$RET" = true ]; then
		PROXY_OPTS=""
		if [ -z "$http_proxy_asked" ]; then
			ask_http_proxy
	
			# If there is a new http proxy, make apt use it
			# temporarily.
			db_get mirror/http/proxy
			if [ "$RET" ]; then
				PROXY_OPTS="-o Acquire::http::Proxy=\"$RET\""
			fi
		fi

		# Test it.
		tmpsources=`tempfile`
		tempfile=`tempfile`
		echo "deb $LINE" > $tmpsources
		clear_screen
		if [ "$DO_PROGRESS" ]; then
			db_progress INFO apt-setup/progress/network-testing
		else
			gettext "Testing apt sources..."
			echo
		fi
		echo "" >> ${APTETC}sources.list
		if ! $APTGET $PROXY_OPTS -o APT::Get::List-Cleanup=false -o Dir::Etc::sourcelist=$tmpsources update 2>$tempfile; then
			# We add the lines with COMMENT since apt failed
			echo "## Uncomment the following two lines to fetch updated software from the network" >> ${APTETC}sources.list
		else
			COMMENT=""
			# checking the src too
			echo "deb-src $SRCLINE" > $tmpsources
			clear_screen
			if [ ! "$DO_PROGRESS" ]; then
				gettext "Testing apt sources..."
				echo
			fi
			if ! $APTGET -o APT::Get::List-Cleanup=false -o Dir::Etc::sourcelist=$tmpsources update 2>$tempfile; then
				SRCCOMMENT="# "
			else
				SRCCOMMENT=""
			fi
		fi

		rm -f $tmpsources $tempfile
	else
		echo >> ${APTETC}sources.list
		echo "## Uncomment the following two lines to fetch updated software from the network" >> ${APTETC}sources.list
	fi

	echo "${COMMENT}deb $LINE" >> ${APTETC}sources.list
	echo "${SRCCOMMENT}deb-src $SRCLINE" >> ${APTETC}sources.list

	if [ "$COMMENT" ]; then
		cat <<EOF >> ${APTETC}sources.list

## Uncomment the following two lines to fetch major bug fix updates produced
## after the final release of the distribution.
EOF
	else
		cat <<EOF >> ${APTETC}sources.list

## Major bug fix updates produced after the final release of the
## distribution.
EOF
	fi

	echo "${COMMENT}deb http://$HOST$DIR $DIST-updates main$NONFREE" >> ${APTETC}sources.list
	echo "${SRCCOMMENT}deb-src http://$SRCHOST$SRCDIR $DIST-updates main$NONFREE" >> ${APTETC}sources.list
fi

if ([ "$URI" = "cdrom" ] || [ "$URI" = "http" ] || [ "$URI" = "ftp" ]) && ! grep -q 'universe' ${APTETC}sources.list; then
	db_get apt-setup/universe
	echo >> ${APTETC}sources.list
	COMMENT=
	if [ "$RET" = false ]; then
		cat <<EOF >> ${APTETC}sources.list
## Uncomment the following two lines to add software from the 'universe'
## repository.
EOF
		COMMENT="# "
	fi
	cat <<EOF >> ${APTETC}sources.list
## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## universe WILL NOT receive any review or updates from the Ubuntu security
## team.
${COMMENT}deb http://$HOST$DIR $DIST universe
${COMMENT}deb-src http://$SRCHOST$SRCDIR $DIST universe
EOF
fi

if ([ "$URI" = "cdrom" ] || [ "$URI" = "http" ] || [ "$URI" = "ftp" ]) && ! grep -q 'backports' ${APTETC}sources.list; then
	db_get apt-setup/backports
	echo >> ${APTETC}sources.list
	COMMENT=
	if [ "$RET" = false ]; then
		cat <<EOF >> ${APTETC}sources.list
## Uncomment the following two lines to add software from the 'backports'
## repository.
EOF
		COMMENT="# "
	fi
	cat <<EOF >> ${APTETC}sources.list
## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
${COMMENT}deb http://$HOST$DIR $DIST-backports main restricted universe multiverse
${COMMENT}deb-src http://$SRCHOST$SRCDIR $DIST-backports main restricted universe multiverse
EOF
fi

if [ "$DO_PROGRESS" ]; then
	db_progress STEP 1
fi

# Finally, see about adding a security.ubuntu.com entry. Deal with these
# situations:
# * already have it in sources.list
# * Add it always, if security.ubuntu.com is reachable make it available
#   otherwise add it commented out.

if apt-cache policy | grep "o=Ubuntu,a=" && \
   ! grep -q '^[^#]*security.ubuntu.com' ${APTETC}sources.list; then
	if [ "$DO_PROGRESS" ]; then
		db_progress INFO apt-setup/progress/security
	fi

	# Figure out what line to add (we're definitely going to add something,
	# even if it's just a comment).
	#
	# To determine if universe and restricted should be included, grep
	# the file to see if they are listed in it.
	#DISTS="main"
	#for dist in non-free contrib; do
	#	if grep -q '^[^#]*'$dist ${APTETC}sources.list; then
	#		DISTS="$DISTS $component"
	#	fi
	#done

	# Figure out which suite to use.
	#if apt-cache policy | grep "o=Debian,a=" | grep -q 'a=testing'; then
	#    SUITE="testing"
	#else
	#    SUITE="stable"
	#fi

	SECHOST=security.ubuntu.com
	SECDIR=/ubuntu

	LINE="http://$SECHOST$SECDIR $DIST-security main$NONFREE"

	COMMENT="# "
	SRCCOMMENT="# "

	# Now find out if they want the entry to be added. (The question
	# won't be asked at all for network installs.)
	db_get apt-setup/network-updates
	if [ "$RET" = true ]; then
		PROXY_OPTS=""
		if [ -z "$http_proxy_asked" ]; then
			ask_http_proxy
	
			# If there is a new http proxy, make apt use it
			# temporarily.
			db_get mirror/http/proxy
			if [ "$RET" ]; then
				PROXY_OPTS="-o Acquire::http::Proxy=\"$RET\""
			fi
		fi

		# Test it.
		tmpsources=`tempfile`
		echo "deb $LINE" > $tmpsources
		clear_screen
		if [ "$DO_PROGRESS" ]; then
			db_progress INFO apt-setup/progress/security-testing
		else
			gettext "Testing apt sources..."
			echo
		fi
		tempfile=`tempfile`
		if ! $APTGET $PROXY_OPTS -o APT::Get::List-Cleanup=false -o Dir::Etc::sourcelist=$tmpsources update 2>$tempfile; then
			# Display failure message
			# TODO should loop and re-ask for http proxy if the
			# user just entered one, in case it was bad.
			clear_screen
			db_subst apt-setup/network-updates-failed site security.ubuntu.com
			db_subst apt-setup/network-updates-failed apt_error `tr '\n' ' ' < $tempfile`
			db_input medium apt-setup/network-updates-failed || true
			db_go || true
			db_fset apt-setup/network-updates-failed seen false
		else
			# Success. Don't comment them out.
			COMMENT=""

			# Success, so add proxy information if not already present.
			db_get mirror/http/proxy
			if [ "$RET" ]; then
				touch $APTETC/apt.conf
				if ! grep -iq 'Acquire::http::Proxy' $APTETC/apt.conf; then
					echo "Acquire::http::Proxy \"$RET\";" >> $APTETC/apt.conf
				fi
			fi
			
			echo "deb-src $LINE" > $tmpsources
			clear_screen
			if [ ! "$DO_PROGRESS" ]; then
				gettext "Testing apt sources..."
				echo
			fi
			if ! $APTGET -o APT::Get::List-Cleanup=false -o Dir::Etc::sourcelist=$tmpsources update 2>$tempfile; then
				SRCCOMMENT="# "
			else
				SRCCOMMENT=""
			fi
		fi
	
		rm -f $tempfile $tmpsources
	fi

	# Now add the entry, commented out or not. (Don't add the commented
	# version if a commented version already exists.)
	if [ -z "$COMMENT" ] || ! grep -q '#.*security.ubuntu.com' ${APTETC}sources.list; then
		echo "" >>${APTETC}sources.list
		echo "${COMMENT}deb $LINE" >>${APTETC}sources.list
		echo "${SRCCOMMENT}deb-src $LINE" >>${APTETC}sources.list

		# Security sources for universe; not used much, but e.g.
		# unsupported binary packages from a supported source
		# package will end up here.
		db_get apt-setup/universe
		if [ "$RET" = false ]; then
			COMMENT="# "
			SRCCOMMENT="# "
		fi
		echo "" >>${APTETC}sources.list
		echo "${COMMENT}deb http://$SECHOST$SECDIR $DIST-security universe" >>${APTETC}sources.list
		echo "${SRCCOMMENT}deb-src http://$SECHOST$SECDIR $DIST-security universe" >>${APTETC}sources.list
	fi
fi

if [ "$DO_PROGRESS" ]; then
	db_progress STEP 1
	db_progress STOP
fi
