#!/bin/sh

if [ -z "$1" ] ; then
	echo
	echo "Usage:"
	echo
	echo " ./scripts/Download [ options ] Filename(s)"
	echo " ./scripts/Download [ options ] -pattern Pattern(s)"
	echo " ./scripts/Download [ options ] -package Package(s)"
	echo
	echo " ./scripts/Download [ options ] -all"
	echo " ./scripts/Download [ options ] -base"
	echo
	echo " Where [ options ] can be:"
	echo "   -nock"
	echo "   -mirror Mirror"
	echo "   -check"
	echo "   -check-url"
	echo
	echo " ./scripts/Download -mk-cksum Filename(s)"
	echo
	echo " ./scripts/Download -list"
	echo " ./scripts/Download -list-unknown"
	echo " ./scripts/Download -list-missing"
	echo
	echo "Type './scripts/Help Download' for details."
	echo
	exit 1
fi

if [ -z "$BASH_VERSION" ] ; then
	echo
	echo 'To run this script, /bin/sh must be a bash!'
	echo
	exit 1
fi

if ! type [[ >/dev/null 2>&1 ; then
	echo
	echo "It seams like /bin/sh is a version of bash which does not have"
	echo "support for the '[[' keyword. Please upgrade your bash to"
	echo "a '[[' enabled version (and make sure /bin/sh points to it)."
	echo
	exit 1
fi

# Handle -mk-cksum mode
#
if [ "$1" = -mk-cksum ] ; then
    shift 1
    for x ; do
	echo -n "$x: "
	if [ ! -f "$x" ] ; then
	    echo "No such file."
	elif [[ "$x" == *.bz2 ]] || [[ "$x" == *.tbz2 ]] ; then
	    bunzip2 < "$x" | cksum | cut -f1 -d' '
	elif [[ "$x" == *.gz ]] || [[ "$x" == *.tgz ]] ; then
	    gunzip < "$x" | cksum | cut -f1 -d' '
	else
	    cksum < "$x" | cut -f1 -d' '
	fi
    done
    exit 1
fi

# Handle Options
#
mirror='' ; checkonly=0
nocheck=0 ; checkurl=0 
options=''

#
if [ "$1" = -nock ] ; then
	options="$options -nock"
	nocheck=1 ; shift 1
fi
#
if [ "$1" = -mirror ] ; then
	options="$options -mirror $2"
	mirror=$2 ; shift 2
fi
#
if [ "$1" = -check ] ; then
	options="$options -check"
	checkonly=1 ; shift 1
fi
#
if [ "$1" = -check-url ] ; then
	options="$options -check-url"
	checkurl=1 ; shift 1
fi

# Handle Aliases
#
if [ "$1" = -all -o "$1" = -base ] ; then
	{
	  if [ $checkonly = 1 -o $checkurl = 1 ] ; then
		./scripts/Download $options -list
	  else 
		./scripts/Download $options -list-missing
	  fi
	} | {
	  if   [ "$1" = -all  ] ; then cat
	  elif [ "$1" = -base ] ; then egrep '^(pkg|opt)-archive/' ; fi
	} | {
	  while read fn ; do
		[ $checkonly = 1 -o $checkurl = 1 ] || echo "Downloading $fn ..."
		./scripts/Download $options $fn
	  done
	}
	exit 0
fi


# cksum_chk filename cksum origfile
#
# It seams like the [ ] command has problems with comparing high numbers.
# That's why I'm using 'bc' to calculate the difference betwen the numbers.
#
cksum_chk() {
	[ $nocheck = 1 -o "$2" = "0" ] && return 0
	#x="`cksum "$1" | cut -f1 -d' '`" ; y="`echo $x - $2 | bc`"
	#if [ $y -ne 0 ] ; then
	if [ "`cksum "$1"`" = "$2" ] ; then
		echo "Cksum ERROR: $3.cksum-err ($x)"
		mv "$3" "$3.cksum-err" ; return 1
	fi
	return 0
}

# download_file local-filename download-location cksum
#
download_file() {

	# Init
	#
	gzfile="$1" ; location="$2" ; cksum="$3" ; mkdir -p src/
	bzfile="`echo "$gzfile" | sed 's,.\(\t\?\)gz$,.\1bz2,'`"
	lkfile="src/down.lockfile.`echo $bzfile | tr / -`"

	# Check if we only like to test the download URL
	#
	if [ $checkurl = 1 ] ; then
		filename="`echo $gzfile | sed 's,.*/,,'`"
		
		# hacking for the overwrite "!" URL format
		if [[ "$location" == \!* ]] ; then
			location=`echo "$location" | sed 's,!,,'`
			filename=`basename $location`
			location=`dirname $location`
		fi
		
		mode="`echo $location | sed 's,://.*,,'`"
		# echo "$mode $location$filename"
		
		if [ "$mode" = "http" ] ; then
			wget --tries=2 --spider $location$filename 2>/dev/null || error=1;
		elif [ "$mode" = "ftp" ] ; then
			temp=`lynx -dump $location 2>/dev/null | grep $filename`
			if [ ".$temp" = "." ] ; then
				error=1;
			fi
		else
			echo "\nerror: only http and ftp are implemented ..."
			error=1;
		fi
		if [ ".$error" = ".1" ] ; then
			echo "\nerror: $location$filename"
		else
			echo -n "."
		fi
	# Check if we only like to test the cksum(s)
	#
	elif [ $checkonly = 1 ] ; then
		gzfile="$bzfile"
		if [ ! -f "$bzfile" ] ; then
			echo "File missing: $bzfile" ; return 0
		fi
		if [ "$cksum" -eq 0 ] ; then
			echo "No checksum: $bzfile" ; return 0
		fi
	else
		# Is it a local symlink ?
		#
		if [[ $location == intern://* ]] ; then
			x="`echo $location | sed s,intern://,../../misc/ext-intern/,`"
			y="`echo $bzfile | sed 's,.*/,,'`"
			if [ ! -e "$bzfile" ] ; then ln -svf "$x$y" "$bzfile"
			else rm -f "$bzfile" ; ln -sf "$x$y" "$bzfile" ; fi
			return 0
		fi
		#
		if [[ $location == \!intern://* ]] ; then
			x="`echo $location | sed s,!intern://,../misc/ext-intern/,`"
			if [ ! -e "$bzfile" ] ; then ln -svf "$x" "$bzfile"
			else rm -f "$bzfile" ; ln -sf "$x" "$bzfile" ; fi
			return 0
		fi

		# Check if it's already here, make locking
		#
		[ -s "$lkfile" ] && echo "Found $lkfile -> skip download."
		[ -s "$bzfile" -o -s "$lkfile" ] && return 0
		echo $$ > "$lkfile"
		trap "rm -f $lkfilei" INT
		
		# Mirroring
		#
		if [ "$mirror" ] ; then
			location="!$mirror/$bzfile"
			gzfile="$bzfile"
		fi
		
		# Create URL
		#
		if [[ "$location" == \!* ]] ; then
			url="`echo "$location" | sed 's,!,,'`"
		else
			url="`echo "$location" | \
				sed 's,/[^/]*$,,'`/`echo $gzfile | sed 's,.*/,,'`"
		fi
		
		# Download
		#
		if [ -s "$gzfile.cksum-err" ] ; then
			echo "Found $gzfile.cksum-err -> skip download."
			rm -f "$lkfile" ; return 1
		elif [ ! -s "$gzfile" ] ; then
			if ! wget --passive-ftp "$url" -O "$gzfile" || [ ! -s "$gzfile" ]
			then
				rm -f "$gzfile" "$lkfile"
				return 1
			fi
		fi

	fi  # checkurl, checkonly
	
  if [ $checkurl = 0 ] ; then
	# Convert a .gz to .bz2 and make cksum testing
	#
	if [ "$gzfile" != "$bzfile" ] ; then
		echo "gzip->bzip2 + cksum-test: $gzfile"
		gunzip < "$gzfile" > src/temp.$$.dat
		if cksum_chk src/temp.$$.dat $cksum "$gzfile" ; then
			bzip2 < src/temp.$$.dat > "$bzfile" ; rm -f "$gzfile"
		fi
		rm -f src/temp.$$.dat
	#
	# Make a cksum test on a bzip2 file
	#
	elif [[ "$gzfile" == *.bz2 ]] || [[ "$gzfile" == *.tbz2 ]] ; then
		echo "cksum-test (bzip2): $bzfile"
		if [ $nocheck = 0 ] ; then
			bunzip2 < "$bzfile" > src/temp.$$.dat
			cksum_chk src/temp.$$.dat $cksum "$bzfile"
		fi
		rm -f src/temp.$$.dat
	#
	# Make a cksum test on a raw data file
	#
	else
		echo "cksum-test (raw): $gzfile"
		cksum_chk "$gzfile" $cksum "$gzfile"
	fi

	# Free Lock
	#
	[ $checkonly = 0 ] && rm -f "$lkfile"
	trap INT
  fi
	return 0
}

handle_file() {
	# Files in pkg-archive/ and opt-archive/
	#
	for y in pkg-archive opt-archive ; do
	    if [[ "$1" == $y/* ]] ; then
		x="`echo $1 | sed s,$y/,,`"
		if grep -q "^$x " $y/INDEX ; then
		    if grep -q " $1" scripts/cksum.cache ; then
			cksum="`grep " $1" scripts/cksum.cache | cut -f1 -d' '`"
		    else cksum=0 ; fi
		    download_file $y/`grep "^$x " $y/INDEX` $cksum
		    return 0
		fi
	    fi
	done

	# Can't handle file / file not found
	#
	return 1
}

if [ "$1" = "-list" ] ; then
	grep '^[^#]' pkg-archive/INDEX | cut -f1 -d' ' | sed 's,^,pkg-archive/,'
	grep '^[^#]' opt-archive/INDEX  | cut -f1 -d' ' | sed 's,^,opt-archive/,'
	exit 0
fi

if [ "$1" = "-list-unknown" ] ; then
	mkdir -p src/ ; ./scripts/Download -list | \
		sed 's,.\(\t\?\)gz$,.\1bz2,' > src/temp.$$.lst
	find opt-archive/* pkg-archive/* -type f -o -type l | \
	egrep -v '((opt|pkg)-archive)/INDEX' | \
	while read fn ; do
		grep -qx "$fn" src/temp.$$.lst ||
			echo "Unknown file: $fn"
	done
	rm -f src/temp.$$.lst
	exit 0
fi

if [ "$1" = "-list-missing" ] ; then
	./scripts/Download -list | \
	sed 's,.\(\t\?\)gz$,.\1bz2,' | \
	while read fn ; do
		[ -f "$fn" ] || echo "$fn"
	done
	exit 0
fi

if [ "$1" = "-pattern" ] ; then
	shift 1
	for pattern ; do
		echo "Processing pattern $pattern ..."
		./scripts/Download -list |
		while read fn ; do
			if [[ "$fn" == $pattern ]] ; then
				echo "Matched: $fn"
				./scripts/Download $options "$fn"
			fi
		done
		./scripts/Download -list |
		while read fn ; do
			if [[ "$fn" == $pattern ]] ; then
				echo "Matched: $fn"
				./scripts/Download $options "$fn"
			fi
		done
	done
	exit 0
fi

if [ "$1" = "-package" ] ; then
	shift 1
	for package ; do

	    package=${package#pkg-config/}
	    package=${package%/}
	    
	    if [ -f pkg-config/$package/$package.desc ] ; then
		echo "Downloading pkg-archive/$package/* ..."
		grep "\[D\]" pkg-config/$package/$package.desc |
		cut -d ' ' -f 3 |
		while read fn
		do ./scripts/Download $options "pkg-archive/$fn"
		done
	    else
		find arch-conf/ subdists/ scripts/ \
		     -name "$package.pz" | \
		while read pz ; do
			echo "Downloading all from $pz ..."
			section=none
			cat $pz | while read a b c ; do
				if [ "$a" = ---- ] ; then
					section="$b"
				elif [ "$section" = pkg-archive/INDEX ] ; then
					echo "pkg-archive/$a"
				elif [ "$section" = opt-archive/INDEX ] ; then
					echo "opt-archive/$a"
				fi
			done | while read fn
			do ./scripts/Download $options "$fn" ; done
		done
	    fi
	done
	exit 0
fi

if [[ "$1" == -* ]] ; then
	exec ./scripts/Download
fi

for file_name ; do
	if [[ "$file_name" == *[\*\?]* ]] ; then
		./scripts/Download $options -pattern "$file_name"
	elif ! handle_file "$file_name" ; then
		file_name="`echo "$file_name" | sed 's,.\(\t\?\)bz2$,.\1gz,'`"
		if ! handle_file "$file_name" ; then
			echo "ERROR: Unknown file: $file_name."
		fi
	fi
done

exit 0
